import streamlit as st
# Do not load st-gsheets-connection
# from streamlit_gsheets import GSheetsConnection
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import hmac

# Standard imports
import pandas as pd

# Custom and other imports
import project_config
# from utils import add_logo
from menu import menu

# Insert logo
# add_logo(project_config.MEDIA_DIR / 'gravity_logo.png')

# Initialize st.session_state.role to None
if "role" not in st.session_state:
    st.session_state.role = None

# # Retrieve the role from Session State to initialize the widget
# st.session_state._role = st.session_state.role

# def set_role():
#     # Callback function to save the role selection to Session State
#     st.session_state.role = st.session_state._role


# From https://stackoverflow.com/questions/55961295/serviceaccountcredentials-from-json-keyfile-name-equivalent-for-remote-json
# See also https://www.slingacademy.com/article/pandas-how-to-read-and-update-google-sheet-files/
# See also https://docs.streamlit.io/develop/tutorials/databases/private-gsheet
# Note that the secrets cannot be passed in a group in HuggingFace Spaces, 
#   which is required for the native Streamlit implementation
def create_keyfile_dict():
    variables_keys = {
        # "spreadsheet": st.secrets['spreadsheet'], # spreadsheet
        "type": st.secrets['type'], # type
        "project_id": st.secrets['project_id'], # project_id
        "private_key_id": st.secrets['private_key_id'], # private_key_id
        # Have to replace \n with new lines (^l in Word) by hand
        "private_key": st.secrets['private_key'], # private_key
        "client_email": st.secrets['client_email'], # client_email
        "client_id": st.secrets['client_id'], # client_id
        "auth_uri": st.secrets['auth_uri'], # auth_uri
        "token_uri": st.secrets['token_uri'], # token_uri
        "auth_provider_x509_cert_url": st.secrets['auth_provider_x509_cert_url'], # auth_provider_x509_cert_url
        "client_x509_cert_url": st.secrets['client_x509_cert_url'], # client_x509_cert_url
        "universe_domain": st.secrets['universe_domain'] # universe_domain
    }
    return variables_keys


def check_password():
    """Returns `True` if the user had a correct password."""

    def login_form():
        """Form with widgets to collect user information"""
        # Header
        col1, col2, col3 = st.columns(3)
        with col2:
            st.image(str(project_config.MEDIA_DIR / 'gravity_logo.svg'), width=300)

        # col1, col2, col3 = st.columns(3)
        # with col1:
        #     st.header("Log In")

        with st.form("Credentials"):
            st.text_input("Username", key="username")
            st.text_input("Password", type="password", key="password")
            st.form_submit_button("Log In", on_click=password_entered)

    def password_entered():
        """Checks whether a password entered by the user is correct."""

        # Define the scope
        scope = [
            'https://spreadsheets.google.com/feeds',
            'https://www.googleapis.com/auth/drive'
        ]

        # Add credentials to the account
        creds = ServiceAccountCredentials.from_json_keyfile_dict(create_keyfile_dict(), scope)

        # Authenticate and create the client
        client = gspread.authorize(creds)

        # Open the spreadsheet
        sheet = client.open_by_url(st.secrets['spreadsheet']).worksheet("user_db")
        data = sheet.get_all_records()
        user_db = pd.DataFrame(data)
        
        # # Create a connection object to Google Sheets
        # conn = st.connection("gsheets", type=GSheetsConnection)

        # # Read the user database
        # user_db = conn.read()
        # user_db.dropna(axis=0, how="all", inplace=True)
        # user_db.dropna(axis=1, how="all", inplace=True)

        # Check if the username is in the database
        if st.session_state["username"] in user_db.username.values:

            st.session_state["username_correct"] = True

            # Check if the password is correct
            if hmac.compare_digest(
                st.session_state["password"],
                user_db.loc[user_db.username == st.session_state["username"], "password"].values[0],
            ):
                
                st.session_state["password_correct"] = True
                
                # Check if the username is an admin
                if st.session_state["username"] in user_db[user_db.role == "admin"].username.values:
                    st.session_state["role"] = "admin"
                else:
                    st.session_state["role"] = "user"

                # Retrieve and store user name and team
                st.session_state["name"] = user_db.loc[user_db.username == st.session_state["username"], "name"].values[0]
                st.session_state["team"] = user_db.loc[user_db.username == st.session_state["username"], "team"].values[0]
                # st.session_state["profile_pic"] = user_db.loc[user_db.username == st.session_state["username"], "profile_pic"].values[0]
                st.session_state["profile_pic"] = st.session_state["username"]

                # Don't store the username or password
                del st.session_state["password"]
                # del st.session_state["username"]

            else:
                st.session_state["password_correct"] = False

        else:
            st.session_state["username_correct"] = False
            st.session_state["password_correct"] = False

    # Return True if the username + password is validated
    if st.session_state.get("password_correct", False):
        return True

    # Show inputs for username + password
    login_form()
    if "password_correct" in st.session_state:

        if not st.session_state["username_correct"]:
            st.error("User not found.")
        elif not st.session_state["password_correct"]:
            st.error("The password you entered is incorrect.")
        else:
            st.error("An unexpected error occurred.")

    return False

menu() # Render the dynamic menu!

if not check_password():
    st.stop()