from __future__ import annotations

import json
import re
from typing import Any

from sqlalchemy import create_engine, text
from sqlalchemy.engine import URL

from app.settings import (
    APP_AUTH_MODE,
    SSO_ENVIRONMENT,
    SSO_MYSQL_DATABASE,
    SSO_MYSQL_HOST,
    SSO_MYSQL_PASSWORD,
    SSO_MYSQL_PORT,
    SSO_MYSQL_USER,
)


def sso_habilitado() -> bool:
    return APP_AUTH_MODE == "sso_keepedu"


def _engine_sso():
    if not SSO_MYSQL_DATABASE:
        raise RuntimeError("SSO_MYSQL_DATABASE nao configurado no .env")

    url = URL.create(
        drivername="mysql+pymysql",
        username=SSO_MYSQL_USER,
        password=SSO_MYSQL_PASSWORD,
        host=SSO_MYSQL_HOST,
        port=SSO_MYSQL_PORT,
        database=SSO_MYSQL_DATABASE,
        query={"charset": "utf8mb4"},
    ).render_as_string(hide_password=False)
    return create_engine(url, pool_pre_ping=True, future=True)


def consumir_token_sso(token: str) -> dict[str, Any] | None:
    token = str(token or "").strip()
    if not token:
        return None

    engine = _engine_sso()
    with engine.begin() as conn:
        linha = conn.execute(
            text(
                """
                SELECT token, auth_data
                FROM sso_tokens
                WHERE token = :token
                  AND used = 0
                  AND expires_at > NOW()
                  AND environment = :environment
                LIMIT 1
                """
            ),
            {"token": token, "environment": SSO_ENVIRONMENT},
        ).mappings().first()

        if not linha:
            return None

        conn.execute(
            text("UPDATE sso_tokens SET used = 1 WHERE token = :token"),
            {"token": token},
        )

    try:
        auth_data = json.loads(linha["auth_data"])
    except (TypeError, json.JSONDecodeError):
        return None

    if not isinstance(auth_data, dict):
        return None

    return auth_data


def _id_usuario_gestor(*candidatos: Any) -> str:
    """Usa o id numérico da tabela usuario do gestor (não o UUID do Keep Empresas)."""
    for candidato in candidatos:
        texto = str(candidato or "").strip()
        if texto.isdigit() and int(texto) > 0:
            return texto
    return ""


def extrair_dados_usuario_sso(auth_data: dict[str, Any]) -> dict[str, Any]:
    user = auth_data.get("user") or {}
    if not isinstance(user, dict):
        user = {}

    school = str(
        auth_data.get("school")
        or auth_data.get("schoolSlug")
        or auth_data.get("cliente_usuario")
        or ""
    ).strip().lower()

    email = str(auth_data.get("email") or user.get("email") or "").strip()
    nome = str(user.get("name") or user.get("nome") or "").strip()
    usuario_id = _id_usuario_gestor(
        auth_data.get("gestorUsuarioId"),
        auth_data.get("usuario_id"),
        user.get("gestorId"),
        user.get("usuario_id"),
        user.get("id"),
        auth_data.get("userId"),
        user.get("userId"),
    )

    institute = ""
    for chave in ("institute", "instituteId", "institute_id", "Institute"):
        valor = auth_data.get(chave) or user.get(chave)
        if valor:
            institute = str(valor).strip()
            break

    logout_url = str(auth_data.get("logoutUrl") or "").strip()
    gestor_home_url = str(
        auth_data.get("gestorHomeUrl")
        or auth_data.get("gestor_home_url")
        or ""
    ).strip()
    school_name = str(
        auth_data.get("schoolName")
        or auth_data.get("school_name")
        or auth_data.get("nomeEmpresa")
        or user.get("schoolName")
        or user.get("nomeEmpresa")
        or ""
    ).strip()

    if not school:
        for url_key in ("gestorHomeUrl", "logoutUrl", "gestor_home_url"):
            url = str(auth_data.get(url_key) or "").strip()
            match = re.search(r"https?://([a-z0-9-]+)\.keepedu\.com\.br", url, re.I)
            if match:
                school = match.group(1).lower()
                break

    return {
        "school": school,
        "email": email,
        "name": nome,
        "usuario_id": usuario_id,
        "institute": institute,
        "logout_url": logout_url,
        "gestor_home_url": gestor_home_url,
        "school_name": school_name,
    }
