#!/usr/bin/env python3
import sys
import os
import asyncio
from datetime import datetime
from typing import List, Dict, Any

sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))

from infrastructure.elasticsearch.client import ElasticsearchClient
from domain.services.calculador_pontuacao import CalculadorPontuacao
from domain.entities.consultor import Consultor, CoordenacaoCapes, Consultoria, Premiacao, Periodo

ES_URL = os.getenv("ES_URL", "http://localhost:9200")
ES_INDEX = os.getenv("ES_INDEX", "atuacapes")
ES_USER = os.getenv("ES_USER", "")
ES_PASSWORD = os.getenv("ES_PASSWORD", "")

NOMES_BUSCAR = [
    "Veronica Maria de Araujo Calado",
    "Manoel Damiao de Sousa Neto"
]


def parse_date(date_str):
    if not date_str:
        return None
    try:
        if '/' in date_str:
            return datetime.strptime(date_str[:10], '%d/%m/%Y')
        else:
            return datetime.strptime(date_str[:10], '%Y-%m-%d')
    except:
        return None


def extrair_coordenacoes_capes(atuacoes: List[Dict]) -> List[CoordenacaoCapes]:
    coordenacoes_data = [
        a for a in atuacoes
        if a.get("tipo") in [
            "Coordenação de Área de Avaliação",
            "Histórico de Coordenação de Área de Avaliação",
        ]
    ]

    result = []
    for coord in coordenacoes_data:
        dados = coord.get("dadosCoordenacaoArea") or coord.get("dadosHistoricoCoordenacaoArea") or {}

        nome = coord.get("nome", "")
        if "câmara" in nome.lower() or "camara" in nome.lower():
            tipo = "CAM"
        elif "mestrado profissional" in nome.lower():
            tipo = "CAJ-MP"
        elif "adjunt" in nome.lower():
            tipo = "CAJ"
        else:
            tipo = "CA"

        inicio = parse_date(coord.get("inicio") or dados.get("inicio"))
        fim = parse_date(coord.get("fim") or dados.get("fim"))

        if not inicio:
            continue

        area = dados.get("areaAvaliacao", {})
        if isinstance(area, dict):
            area_nome = area.get("nome", "N/A")
        else:
            area_nome = str(area) if area else "N/A"

        periodo = Periodo(inicio=inicio, fim=fim)

        result.append(CoordenacaoCapes(
            tipo=tipo,
            area_avaliacao=area_nome,
            periodo=periodo,
            areas_adicionais=[],
            ja_coordenou_antes=False
        ))

    return result


def extrair_consultoria(atuacoes: List[Dict]) -> Consultoria:
    consultorias = [
        a for a in atuacoes
        if a.get("tipo") in ["Consultor", "Histórico de Consultoria"]
    ]

    if not consultorias:
        return None

    datas = []
    areas = set()
    total_eventos = len(consultorias)
    vezes_responsavel = 0

    for cons in consultorias:
        dados = cons.get("dadosConsultoria", {})

        inicio = parse_date(cons.get("inicio"))
        fim = parse_date(cons.get("fim"))

        if inicio:
            datas.append(inicio)
        if fim:
            datas.append(fim)

        area = dados.get("areaAvaliacao")
        if area:
            areas.add(area)

        if dados.get("responsavel"):
            vezes_responsavel += 1

    if not datas:
        return None

    primeiro_evento = min(datas)
    ultimo_evento = max(datas)

    limite_recente = datetime.now().replace(year=datetime.now().year - 2)
    eventos_recentes = sum(1 for d in datas if d >= limite_recente)

    anos = (datetime.now() - primeiro_evento).days / 365.25

    return Consultoria(
        total_eventos=total_eventos,
        eventos_recentes=eventos_recentes,
        primeiro_evento=primeiro_evento,
        ultimo_evento=ultimo_evento,
        areas=list(areas),
        situacao="Ativo" if eventos_recentes > 0 else "Histórico",
        anos_completos=int(anos),
        anos_consecutivos=int(anos),
        retornos=0
    )


def extrair_premiacoes(atuacoes: List[Dict]) -> List[Premiacao]:
    premiacoes_data = [
        a for a in atuacoes
        if a.get("tipo") in [
            "Premiação Prêmio",
            "Avaliação Prêmio",
            "Inscrição Prêmio",
        ]
    ]

    result = []
    mapa_pontos = {
        "Premiação Prêmio": 60,
        "Avaliação Prêmio": 40,
        "Inscrição Prêmio": 20,
    }

    for prem in premiacoes_data:
        tipo = prem.get("tipo", "")
        dados = prem.get("dadosPremiacaoPremio") or prem.get("dadosParticipacaoPremio") or prem.get("dadosParticipacaoInscricaoPremio") or {}

        nome_premio = dados.get("premio", "") or prem.get("descricao", "")
        ano_str = dados.get("ano") or prem.get("inicio", "")

        try:
            ano = int(ano_str) if isinstance(ano_str, (int, str)) and str(ano_str).isdigit() else 0
        except:
            ano = 0

        pontos = mapa_pontos.get(tipo, 0)

        result.append(Premiacao(
            tipo=tipo,
            nome_premio=nome_premio,
            ano=ano,
            pontos=pontos
        ))

    return result


async def buscar_por_nome(es_client, nome):
    query = {
        "size": 5,
        "query": {
            "match": {
                "dadosPessoais.nome": {
                    "query": nome,
                    "fuzziness": "AUTO"
                }
            }
        },
        "_source": ["id", "dadosPessoais", "atuacoes"]
    }

    response = await es_client.client.post(
        f"{es_client.url}/{es_client.index}/_search",
        json=query
    )
    response.raise_for_status()
    result = response.json()
    return result.get("hits", {}).get("hits", [])


async def main():
    print("Conectando ao Elasticsearch...")
    es_client = ElasticsearchClient(ES_URL, ES_INDEX, ES_USER, ES_PASSWORD)
    await es_client.connect()

    calculador = CalculadorPontuacao()

    try:
        for nome_buscar in NOMES_BUSCAR:
            print(f"\n{'='*100}")
            print(f"BUSCANDO: {nome_buscar}")
            print(f"{'='*100}")

            hits = await buscar_por_nome(es_client, nome_buscar)

            if not hits:
                print(f"   Nenhum resultado encontrado para '{nome_buscar}'")
                continue

            print(f"   Encontrados {len(hits)} resultados")

            for hit in hits:
                doc = hit["_source"]
                id_pessoa = doc.get("id")
                dados_pessoais = doc.get("dadosPessoais", {})
                nome = dados_pessoais.get("nome", "N/A")
                cpf = dados_pessoais.get("cpf", "")
                atuacoes = doc.get("atuacoes", [])

                print(f"\n   CONSULTOR ENCONTRADO: {nome}")
                print(f"   ID: {id_pessoa}")

                tipos_atuacao = {}
                for a in atuacoes:
                    tipo = a.get("tipo", "Desconhecido")
                    tipos_atuacao[tipo] = tipos_atuacao.get(tipo, 0) + 1

                print(f"\n   TIPOS DE ATUAÇÃO:")
                for tipo, count in sorted(tipos_atuacao.items()):
                    print(f"      - {tipo}: {count}")

                coordenacoes_capes = extrair_coordenacoes_capes(atuacoes)
                consultoria = extrair_consultoria(atuacoes)
                premiacoes = extrair_premiacoes(atuacoes)

                consultor = Consultor(
                    id_pessoa=id_pessoa,
                    nome=nome,
                    cpf=cpf,
                    coordenacoes_capes=coordenacoes_capes,
                    coordenacoes_programas=[],
                    consultoria=consultoria,
                    premiacoes=premiacoes
                )

                pontuacao = calculador.calcular_pontuacao_completa(consultor)
                consultor.pontuacao = pontuacao

                print(f"\n   PONTUAÇÃO CALCULADA:")
                print(f"   TOTAL: {consultor.pontuacao_total:.2f} pontos")
                print(f"   Componente A (Coordenação CAPES): {consultor.pontuacao.componente_a.total:.2f}")
                print(f"      Base: {consultor.pontuacao.componente_a.base} | Tempo: {consultor.pontuacao.componente_a.tempo}")
                print(f"      Extras: {consultor.pontuacao.componente_a.extras} | Bônus: {consultor.pontuacao.componente_a.bonus} | Retorno: {consultor.pontuacao.componente_a.retorno}")
                print(f"   Componente B (Coordenação PPG): {consultor.pontuacao.componente_b.total:.2f}")
                print(f"   Componente C (Consultoria): {consultor.pontuacao.componente_c.total:.2f}")
                if consultoria:
                    print(f"      Base: {consultor.pontuacao.componente_c.base} | Tempo: {consultor.pontuacao.componente_c.tempo}")
                    print(f"      Extras: {consultor.pontuacao.componente_c.extras}")
                    print(f"      Eventos: {consultoria.total_eventos} | Recentes: {consultoria.eventos_recentes}")
                    print(f"      Situação: {consultoria.situacao}")
                    print(f"      Anos: {consultoria.anos_completos}")
                print(f"   Componente D (Premiações): {consultor.pontuacao.componente_d.total:.2f}")
                if premiacoes:
                    print(f"      Total de premiações: {len(premiacoes)}")
                    for p in premiacoes[:5]:
                        print(f"         - {p.tipo}: {p.nome_premio} ({p.ano}) = {p.pontos} pts")

                print(f"\n   DETALHAMENTO COMPLETO:")
                if coordenacoes_capes:
                    print(f"   Coordenações CAPES ({len(coordenacoes_capes)}):")
                    for coord in coordenacoes_capes:
                        status = "ATIVA" if coord.periodo.ativo else "ENCERRADA"
                        print(f"      - {coord.tipo}: {coord.area_avaliacao}")
                        print(f"        Período: {coord.periodo.inicio} até {coord.periodo.fim or 'atual'} ({status})")
                        print(f"        Anos: {coord.periodo.anos_decorridos:.1f}")

    finally:
        await es_client.close()


if __name__ == "__main__":
    asyncio.run(main())
