import requests
import re

from app.keepedu_http import post_json_comprimido
from app.settings import KEEPEDU_API_KEY
from app.tenant import get_institute_id, resolve_keepedu_url


def _extrair_objeto_aluno(resposta_api):
    """
    Tenta encontrar o objeto do aluno em diferentes formatos possíveis de resposta.
    Como ainda não sabemos o JSON exato da API, deixamos flexível.
    """

    if isinstance(resposta_api, list):
        if len(resposta_api) == 1 and isinstance(resposta_api[0], dict):
            return resposta_api[0]
        return None

    if not isinstance(resposta_api, dict):
        return None

    possiveis_chaves = [
        "aluno",
        "data",
        "dados",
        "result",
        "resultado",
        "response"
    ]

    for chave in possiveis_chaves:
        valor = resposta_api.get(chave)

        if isinstance(valor, dict):
            return valor

        if isinstance(valor, list) and len(valor) == 1 and isinstance(valor[0], dict):
            return valor[0]

    return resposta_api


def _extrair_id_aluno(aluno):
    if not isinstance(aluno, dict):
        return ""

    possiveis_campos_id = [
        "id",
        "id_aluno",
        "idAluno",
        "id_pessoa",
        "idPessoa",
        "codigo",
        "codigo_aluno",
        "codigoAluno"
    ]

    for campo in possiveis_campos_id:
        valor = aluno.get(campo)

        if valor:
            return str(valor).strip()

    return ""


def _extrair_campo_texto(aluno, possiveis_campos, padrao=""):
    if not isinstance(aluno, dict):
        return padrao

    for campo in possiveis_campos:
        valor = aluno.get(campo)

        if valor is None:
            continue

        texto = str(valor).strip()

        if texto:
            return texto

    return padrao


def buscar_aluno_por_ra(ra: str):
    """
    Consulta a API do KeepEdu pelo RA e retorna o ID do aluno.

    Entrada:
    {
        "ra": "123456"
    }

    Retorno esperado internamente:
    {
        "encontrado": True,
        "id": "...",
        "ra": "...",
        "nome": "...",
        "raw": {...}
    }
    """

    ra = str(ra or "").strip()
    ra = re.sub(r"\D", "", ra)

    if not ra or len(ra) < 5 or ra == "000000":
        return {
            "encontrado": False,
            "motivo": f"RA inválido para consulta: {ra or 'vazio'}",
            "ra": ra
        }

    if not KEEPEDU_API_KEY:
        return {
            "encontrado": False,
            "motivo": "ApiKey não configurada no arquivo .env."
        }

    headers = {
        "ApiKey": KEEPEDU_API_KEY,
        "Institute": get_institute_id(),
        "Content-Type": "application/json",
        "Accept": "application/json"
    }

    payload = {
        "ra": ra
    }

    try:
        resposta = post_json_comprimido(
            resolve_keepedu_url("customers/buscar-id-aluno", "KEEPEDU_BUSCAR_ID_URL"),
            payload,
            headers=headers,
            timeout=20
        )

        if resposta.status_code == 404:
            return {
                "encontrado": False,
                "motivo": "RA não encontrado na API.",
                "status_code": resposta.status_code
            }

        resposta.raise_for_status()

        dados = resposta.json()
        aluno = _extrair_objeto_aluno(dados)
        id_aluno = _extrair_id_aluno(aluno)

        if not id_aluno:
            return {
                "encontrado": False,
                "motivo": "API respondeu, mas não foi possível localizar o campo de ID do aluno.",
                "ra": ra,
                "raw": dados
            }

        return {
            "encontrado": True,
            "id": id_aluno,
            "rmb": _extrair_campo_texto(
                aluno,
                ["cd_aluno", "codigo_aluno", "codigoAluno", "rmb", "RMB"]
            ),
            "ra": _extrair_campo_texto(
                aluno,
                ["cd_ra", "ra", "RA", "registro_academico"],
                ra
            ),
            "nome": _extrair_campo_texto(
                aluno,
                ["nm_pessoa", "nome", "nm_aluno"],
                ""
            ),
            "turma": _extrair_campo_texto(aluno, ["turma", "nm_turma"], ""),
            "unidade": _extrair_campo_texto(aluno, ["unidade", "escola", "nm_unidade"], ""),
            "status_matricula": _extrair_campo_texto(
                aluno,
                ["status_matricula", "nu_ativo", "in_bloqueado"],
                ""
            ),
            "raw": dados
        }

    except requests.exceptions.Timeout:
        return {
            "encontrado": False,
            "motivo": "Tempo limite excedido ao consultar a API."
        }

    except requests.exceptions.RequestException as e:
        return {
            "encontrado": False,
            "motivo": f"Erro ao consultar API: {str(e)}"
        }

    except ValueError:
        return {
            "encontrado": False,
            "motivo": "A API não retornou um JSON válido."
        }


def buscar_aluno_por_id(aluno_id: str, ra: str = ""):
    """Consulta os dados cadastrais do aluno pelo ID, com RA opcional."""
    aluno_id = re.sub(r"\D", "", str(aluno_id or ""))
    ra = re.sub(r"\D", "", str(ra or ""))

    if not aluno_id:
        return {"encontrado": False, "motivo": "ID do aluno inválido."}
    if not KEEPEDU_API_KEY:
        return {"encontrado": False, "motivo": "ApiKey não configurada no arquivo .env."}

    headers = {
        "ApiKey": KEEPEDU_API_KEY,
        "Institute": get_institute_id(),
        "Content-Type": "application/json",
        "Accept": "application/json",
    }
    payload = {"aluno_id": int(aluno_id)}
    if ra:
        payload["ra"] = int(ra)

    try:
        resposta = post_json_comprimido(
            resolve_keepedu_url("customers/buscar-id-aluno", "KEEPEDU_BUSCAR_ID_URL"),
            payload,
            headers=headers,
            timeout=20,
        )
        if resposta.status_code == 404:
            return {"encontrado": False, "motivo": "Aluno não encontrado na API."}
        resposta.raise_for_status()
        dados = resposta.json()
        aluno = _extrair_objeto_aluno(dados)
        nome = _extrair_campo_texto(aluno, ["nm_pessoa", "nome", "nm_aluno"], "")
        if not nome:
            return {
                "encontrado": False,
                "motivo": "API respondeu, mas não retornou o nome do aluno.",
                "raw": dados,
            }
        return {
            "encontrado": True,
            "id": _extrair_id_aluno(aluno) or aluno_id,
            "ra": _extrair_campo_texto(aluno, ["cd_ra", "ra", "RA", "registro_academico"], ra),
            "nome": nome,
            "raw": dados,
        }
    except requests.exceptions.Timeout:
        return {"encontrado": False, "motivo": "Tempo limite excedido ao consultar a API."}
    except requests.exceptions.RequestException as erro:
        return {"encontrado": False, "motivo": f"Erro ao consultar API: {erro}"}
    except ValueError:
        return {"encontrado": False, "motivo": "A API não retornou um JSON válido."}


def buscar_aluno_por_nome(nome: str):
    """
    Por enquanto não será usado no fluxo principal.
    Regra atual:
    - Se tiver ID no cartão, usa ID.
    - Se não tiver ID, usa RA para buscar ID.
    - Se não tiver RA, cai em validação cadastral.
    """

    return {
        "encontrado": False,
        "motivo": "Consulta por nome não será usada neste fluxo."
    }
