from datetime import datetime, timezone, timedelta
from fastapi import HTTPException
import jwt
import psycopg2
from services.encryption import EncryptionService
from services.fgts_client import FgtsClient

class SessionService:
    def __init__(self, db_conn):
        self.conn = db_conn
        self.crypto = EncryptionService()
        self.fgts = FgtsClient()

    def get_customer_session(self, company_cnpj: str, customer_cnpj: str):
        with self.conn.cursor() as cur:
            # 1. Tenta buscar o vínculo completo
            query = """
                SELECT 
                    co.id, co.cookie, 
                    cu.cookie, cu.expires_on, cu.id
                FROM companies co
                LEFT JOIN customers cu ON (cu.company_id = co.id AND cu.cnpj = %s)
                WHERE co.cnpj = %s
            """
            cur.execute(query, (customer_cnpj, company_cnpj))
            result = cur.fetchone()

            # Se não achou nem a Company, aí é erro mesmo
            if not result:
                raise HTTPException(status_code=404, detail="Empresa Contábil (Company) não encontrada.")

            company_id, company_cookie, customer_cookie, customer_expires_on, customer_id = result

            now_utc = datetime.now(timezone.utc)

            # CASO A: Cliente existe no banco e token está válido
            if customer_id and customer_cookie and customer_expires_on:
                if customer_expires_on > (now_utc + timedelta(minutes=2)):
                    decrypted_cookie = self.crypto.decrypt_data(customer_cookie)
                    # Adiciona o fgtsd_ni_usuario=company_cnpj se não existir
                    if 'fgtsd_ni_usuario=' not in decrypted_cookie:
                        decrypted_cookie = f"{decrypted_cookie}; fgtsd_ni_usuario={company_cnpj}"
                    return decrypted_cookie, customer_expires_on

            # CASO B: Cliente não existe OU Token expirou -> Precisamos ir ao FGTS
            
            # Descriptografa cookie da company
            raw_company_cookie = self.crypto.decrypt_data(company_cookie)

            try:
                new_session_data = self.fgts.swap_context(
                    company_cookie_decrypted=raw_company_cookie,
                    customer_cnpj=customer_cnpj
                )
            except Exception as e:
                # Se falhar aqui, pode ser que a empresa não tenha procuração para esse cliente
                raise HTTPException(status_code=403, detail=f"Falha ao obter sessão. Verifique a procuração: {str(e)}")

            new_session_data['cookie'] = f"{new_session_data['cookie']}; fgtsd_ni_usuario={company_cnpj}"

            # Prepara dados para salvar
            # new_cookie_enc = self.crypto.encrypt_data(new_session_data['cookie'])
            new_cookie_enc = self.crypto.encrypt_data(new_session_data['cookie'])
            new_expires_on = new_session_data['expires_on']
            
            # Extra: Tentar pegar o nome do cliente do JWT para salvar no banco bonitinho
            # (Assumindo que você extraiu isso no FgtsClient, senão pode salvar NULL ou string vazia)
            # TODO: criar uma trait para tratar captura do cookie e buscar os dados do JWT
            # customer_name = new_session_data.get('name', f"Cliente {customer_cnpj}")
            cookie = new_session_data['cookie']
            fgtsd_token_str = next((s.split('=')[1] for s in cookie.split('; ') if s.startswith('fgtsd_token=')), None)

            if not fgtsd_token_str:
                raise ValueError("O 'fgtsd_token' não foi encontrado na string de cookie.")
        
            decoded_token = jwt.decode(fgtsd_token_str, options={"verify_signature": False})
            # raise Exception(f"Debug: {decoded_token['fgtsdigital.gov.br/nome_perfil']}")
            # exit()
            customer_name = decoded_token['fgtsdigital.gov.br/nome_perfil']

            if customer_id:
                # Atualiza existente
                update_sql = """
                    UPDATE customers 
                    SET cookie = %s, expires_on = %s, updated_at = NOW(), status = 'active'
                    WHERE id = %s
                """
                cur.execute(update_sql, (new_cookie_enc, new_expires_on, customer_id))
            else:
                # Cria novo (Auto-cadastro)
                insert_sql = """
                    INSERT INTO customers (company_id, cnpj, name, cookie, expires_on, status, created_at)
                    VALUES (%s, %s, %s, %s, %s, 'active', NOW())
                """
                cur.execute(insert_sql, (company_id, customer_cnpj, customer_name, new_cookie_enc, new_expires_on))
            
            self.conn.commit()

            return new_session_data['cookie'], new_expires_on