import json
import logging
from typing import Any, Dict, List, Optional

from ...domain.entities.consultor_ranking import ConsultorRanking
from ...interface.schemas.ranking_schema import ConsultorRankingResumoSchema

logger = logging.getLogger(__name__)

TIPOS_ATUACAO_ORDEM = [
    ("Coordenador", "coordenacoes_capes"),
    ("Consultor", "consultoria"),
    ("Avaliador", "avaliacoes_comissao"),
    ("Premiado", "premiacoes"),
    ("Orientador", "orientacoes"),
    ("Bolsista CNPq", "bolsas_cnpq"),
    ("Inscrito Premio", "inscricoes"),
    ("Projeto", "participacoes_projeto"),
    ("Evento", "participacoes_evento"),
]


class RankingMapper:
    @staticmethod
    def _extrair_tipos_atuacao(jd: Dict[str, Any]) -> List[str]:
        tipos = []
        for label, campo in TIPOS_ATUACAO_ORDEM:
            if campo == "consultoria":
                if jd.get("consultoria"):
                    tipos.append(label)
            elif campo == "participacoes_projeto":
                participacoes = jd.get("participacoes") or []
                if any(p.get("codigo") == "PROJ" for p in participacoes):
                    tipos.append(label)
            elif campo == "participacoes_evento":
                participacoes = jd.get("participacoes") or []
                if any(p.get("codigo") == "EVENTO" for p in participacoes):
                    tipos.append(label)
            else:
                dados = jd.get(campo)
                if dados and (isinstance(dados, list) and len(dados) > 0):
                    tipos.append(label)
        return tipos

    @staticmethod
    def consultor_ranking_to_schema(c: ConsultorRanking) -> ConsultorRankingResumoSchema:
        consultoria = None
        coordenacoes_capes = None
        inscricoes = None
        avaliacoes_comissao = None
        premiacoes = None
        bolsas_cnpq = None
        participacoes = None
        orientacoes = None
        membros_banca = None
        pontuacao = None
        tipos_atuacao = []

        try:
            jd = json.loads(c.json_detalhes) if c.json_detalhes else {}
            if isinstance(jd, dict):
                consultoria = jd.get("consultoria")
                coordenacoes_capes = jd.get("coordenacoes_capes")
                inscricoes = jd.get("inscricoes")
                avaliacoes_comissao = jd.get("avaliacoes_comissao")
                premiacoes = jd.get("premiacoes")
                bolsas_cnpq = jd.get("bolsas_cnpq")
                participacoes = jd.get("participacoes")
                orientacoes = jd.get("orientacoes")
                membros_banca = jd.get("membros_banca")
                pontuacao = jd.get("pontuacao")
                tipos_atuacao = RankingMapper._extrair_tipos_atuacao(jd)
        except (json.JSONDecodeError, TypeError) as e:
            logger.warning(f"Erro ao parsear json_detalhes do consultor {c.id_pessoa}: {e}")

        pontuacao_total = float(c.pontuacao_total or 0)
        bloco_a = float(c.componente_a or 0)
        bloco_b = float(c.componente_b or 0)
        bloco_c = float(c.componente_c or 0)
        bloco_d = float(c.componente_d or 0)

        pontuacao_ajustada = RankingMapper._ajustar_pontuacao(
            pontuacao, bloco_a, bloco_b, bloco_c, bloco_d, pontuacao_total
        )

        return ConsultorRankingResumoSchema(
            id_pessoa=c.id_pessoa,
            nome=c.nome,
            posicao=c.posicao,
            pontuacao_total=pontuacao_total,
            bloco_a=bloco_a,
            bloco_b=bloco_b,
            bloco_c=bloco_c,
            bloco_d=bloco_d,
            ativo=c.ativo,
            anos_atuacao=c.anos_atuacao,
            tipos_atuacao=tipos_atuacao,
            consultoria=consultoria,
            coordenacoes_capes=coordenacoes_capes,
            inscricoes=inscricoes,
            avaliacoes_comissao=avaliacoes_comissao,
            premiacoes=premiacoes,
            bolsas_cnpq=bolsas_cnpq,
            participacoes=participacoes,
            orientacoes=orientacoes,
            membros_banca=membros_banca,
            pontuacao=pontuacao_ajustada if pontuacao_ajustada else None,
        )

    @staticmethod
    def _ajustar_pontuacao(
        pontuacao: Optional[Dict],
        bloco_a: float,
        bloco_b: float,
        bloco_c: float,
        bloco_d: float,
        pontuacao_total: float,
    ) -> Dict[str, Any]:
        if isinstance(pontuacao, dict):
            pontuacao_ajustada = dict(pontuacao)
        else:
            pontuacao_ajustada = {}

        def ajustar_bloco(chave: str, total: float, letra: str):
            b = pontuacao_ajustada.get(chave)
            if isinstance(b, dict):
                b2 = dict(b)
                b2["bloco"] = letra
                b2["total"] = total
                pontuacao_ajustada[chave] = b2
            else:
                pontuacao_ajustada[chave] = {"bloco": letra, "total": total, "atuacoes": []}

        ajustar_bloco("bloco_a", bloco_a, "A")
        ajustar_bloco("bloco_b", bloco_b, "B")
        ajustar_bloco("bloco_c", bloco_c, "C")
        ajustar_bloco("bloco_d", bloco_d, "D")
        pontuacao_ajustada["pontuacao_total"] = pontuacao_total

        return pontuacao_ajustada
