import math
import os
import csv
import json
from datetime import datetime

# =====================================================================
# TOKENS DE IDENTIDADE VISUAL MINDCORE (PALETA OFICIAL)
# =====================================================================
HEX_OBSIDIANA = "#0B0F19"  # Fundo escuro profundo / Modo escuro real
HEX_VIOLETA = "#6D28D9"    # Elementos estruturais / Cabeçalhos primários
HEX_MAGENTA = "#D946EF"    # Destaques exponenciais / Alertas de excelência
HEX_TEXTO_MUT = "#64748B"  # Textos secundários / Muted slate
HEX_GRAFITE = "#1E293B"    # Linhas alternadas de tabela


class DatabaseCloudNexus:
    """Camada ORM para persistência distribuída em nuvem e arquivos CSV."""

    @staticmethod
    def conectar_e_persistir(dados_registro, nome_csv="historico_matriz_nexus.csv"):
        arquivo_existe = os.path.exists(nome_csv)
        with open(nome_csv, "a", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            if not arquivo_existe:
                writer.writerow(["Data", "Nome", "Pilar", "IEH", "Classificacao", "Sub_Indicadores", "Dataset_Charts"])
            writer.writerow([
                dados_registro["data"], dados_registro["usuario"], dados_registro["pilar"],
                dados_registro["ieh"], dados_registro["estagio"],
                json.dumps(dados_registro["sub_indicadores"], ensure_ascii=False),
                json.dumps(dados_registro["charts"], ensure_ascii=False),
            ])
        return True


class MatrizUniversalNexus:
    """Motor matemático avançado com cálculo ponderado de sub-indicadores."""

    CONFIG_PILARES = {
        1: {"nome": "Alta Performance Cognitiva", "sub_nomes": ["Foco Profundo", "Retencao", "Velocidade Decisoria"],
            "pesos": [0.4, 0.3, 0.3], "limites": [(2, 16), (1, 10), (1, 10)], "tempo_max": 60.0},
        2: {"nome": "Resistência e Potência Física", "sub_nomes": ["Forca Bruta", "Endurance", "Regeneracao"],
            "pesos": [0.3, 0.4, 0.3], "limites": [(10, 500), (1, 1000), (1, 10)], "tempo_max": 40.0},
        3: {"nome": "Consistência e Longevidade Estratégica", "sub_nomes": ["Longevidade", "Automacao", "Gestao de Crises"],
            "pesos": [0.4, 0.3, 0.3], "limites": [(1, 10), (1, 10), (1, 10)], "tempo_max": 84.0},
        4: {"nome": "Inteligência Financeira Sistêmica", "sub_nomes": ["Equity", "Alocacao Ativos", "Blindagem Patrimonial"],
            "pesos": [0.4, 0.3, 0.3], "limites": [(1, 100), (1, 10), (1, 10)], "tempo_max": 50.0},
        5: {"nome": "Liderança de Impacto e Legado", "sub_nomes": ["Sucessores", "Cultura", "Influencia"],
            "pesos": [0.4, 0.3, 0.3], "limites": [(0, 200), (1, 10), (1, 10)], "tempo_max": 60.0},
    }

    @staticmethod
    def calcular_min_max(valor, ref_min, ref_max):
        if valor >= ref_max:
            return 1.0
        if valor <= ref_min:
            return 0.0
        return (valor - ref_min) / (ref_max - ref_min)

    @classmethod
    def processar_pilar_complexo(cls, opcao_pilar, inputs_sub):
        """Combina a média ponderada dos sub-indicadores com a curva logística de estabilidade temporal."""
        cfg = cls.CONFIG_PILARES[opcao_pilar]
        notas_norm = []

        for i, valor in enumerate(inputs_sub[:-1]):
            v_min, v_max = cfg["limites"][i]
            notas_norm.append(cls.calcular_min_max(valor, v_min, v_max))

        eficiencia_pico = sum(n * p for n, p in zip(notas_norm, cfg["pesos"]))

        tempo_anos = inputs_sub[-1]
        proporcao_tempo = tempo_anos / cfg["tempo_max"]
        if proporcao_tempo >= 1.0:
            estabilidade_temporal = 1.0
        elif proporcao_tempo <= 0:
            estabilidade_temporal = 0.0
        else:
            estabilidade_temporal = 1 / (1 + math.exp(-10 * (proporcao_tempo - 0.5)))

        ieh = round(math.sqrt(eficiencia_pico * estabilidade_temporal), 4)
        return cfg["nome"], cfg["sub_nomes"], ieh, notas_norm, tempo_anos, eficiencia_pico, estabilidade_temporal


class GeradorMetasUniversais:
    """Planos de ação em Markdown, datasets de gráficos e relatório PDF executivo com radar nativo."""

    @staticmethod
    def classificar_estagio_humano(ieh):
        if ieh >= 0.90:
            return "Nivel Epico/Exorbitante (Limite do Potencial Humano)"
        elif ieh >= 0.70:
            return "Nivel de Excelencia Magistral (Alta Consistencia)"
        elif ieh >= 0.45:
            return "Nivel de Alta Performance Expansiva (Acima da Media)"
        else:
            return "Nivel de Desenvolvimento Basal (Estagio de Fundacao)"

    @classmethod
    def gerar_plano_acao_markdown(cls, nome_pilar, sub_nomes, notas_norm, ieh, nome_txt):
        """Plano de ação semanal dinâmico em Markdown, gravado em disco."""
        estagio = cls.classificar_estagio_humano(ieh)
        md = []
        md.append(f"# PLANO DE ACAO SEMANAL MINDCORE - {nome_pilar.upper()}")
        md.append(f"**Status da Matriz:** {estagio} | **IEH:** {ieh}")
        md.append(f"**Data de Geracao:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        md.append("## Diagnostico dos Sub-indicadores")

        necessita_recuperacao = False
        for nome_sub, nota in zip(sub_nomes, notas_norm):
            pct = round(nota * 100, 2)
            status_sub = "EXCELENCIA" if pct >= 70 else "ATENCAO CRITICA"
            md.append(f"* **{nome_sub}:** {pct}% do potencial maximo de mercado — [{status_sub}]")
            if pct < 70:
                necessita_recuperacao = True

        md.append("\n## Diretrizes de Engenharia Comportamental Semanal")
        if necessita_recuperacao:
            md.append("### PROTOCOLO DE RECUPERACAO DA MATRIZ")
            md.append("1. **Isolamento de Ruido:** suspender rotinas acessorias focando no sub-indicador vulneravel.")
            md.append("2. **Pratica Deliberada:** dedicar os primeiros 90 minutos do dia ao gargalo tecnico.")
            md.append("3. **Medicao Diaria:** criar registros granulares para assegurar o crescimento do indice.")
        else:
            md.append("### PROTOCOLO DE EXPANSAO EXORBITANTE")
            md.append("1. **Aumento de Carga:** incrementar em 5% os tetos de entrega nos sub-indicadores dominados.")
            md.append("2. **Sistematizacao:** codificar a rotina atual em manuais tecnicos replicaveis.")
            md.append("3. **Alocacao Estrategica:** delegar processos repetitivos e blindar o tempo de foco profundo.")

        md_conteudo = "\n".join(md)
        with open(nome_txt, "w", encoding="utf-8") as f:
            f.write(md_conteudo)
        return md_conteudo

    @classmethod
    def estruturar_dataset_graficos(cls, nome_pilar, sub_nomes, notas_norm, ieh):
        return {
            "chartType": "Radar",
            "labels": sub_nomes + ["IEH Consolidado"],
            "datasets": [{
                "label": "Performance do Operador",
                "data": [round(n * 100, 2) for n in notas_norm] + [round(ieh * 100, 2)],
                "backgroundColor": "rgba(109, 40, 217, 0.15)",
                "borderColor": HEX_MAGENTA,
                "borderWidth": 3,
            }],
        }

    @staticmethod
    def gerar_barra_progresso(ieh, tamanho=30):
        preenchido = int(ieh * tamanho)
        return "█" * preenchido + "░" * (tamanho - preenchido)

    @staticmethod
    def buscar_ultimo_ieh(nome_usuario, nome_pilar, nome_csv="historico_matriz_nexus.csv"):
        if not os.path.exists(nome_csv):
            return None
        ultimo = None
        with open(nome_csv, "r", encoding="utf-8") as f:
            for row in csv.DictReader(f):
                if row.get("Nome", "").strip().lower() == nome_usuario.strip().lower() and row.get("Pilar") == nome_pilar:
                    try:
                        ultimo = float(row.get("IEH", 0))
                    except (ValueError, TypeError):
                        continue
        return ultimo

    @classmethod
    def comparar_evolucao(cls, ieh_atual, ieh_anterior):
        if ieh_anterior is None:
            return "Primeiro registro deste pilar na matriz."
        if ieh_anterior == 0:
            return "Evolução iniciada a partir do marco zero."
        variacao = ((ieh_atual - ieh_anterior) / ieh_anterior) * 100
        if variacao > 0:
            return f"CRESCIMENTO DETECTADO: +{variacao:.2f}% em relação ao seu último teste!"
        if variacao < 0:
            return f"DECLÍNIO OPERACIONAL: {variacao:.2f}% em relação ao seu último teste."
        return "ESTABILIDADE: seu índice permaneceu exatamente igual ao anterior."

    @classmethod
    def gerar_pdf_executivo(cls, nome_pdf, dados):
        """Relatório PDF executivo com tabela e gráfico radar vetorial nativo (SpiderChart)."""
        try:
            from reportlab.lib.pagesizes import letter
            from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, KeepTogether
            from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
            from reportlab.lib import colors
            from reportlab.graphics.shapes import Drawing, String
            from reportlab.graphics.charts.spider import SpiderChart
        except ImportError:
            return False

        COR_OBSIDIANA = colors.HexColor(HEX_OBSIDIANA)
        COR_VIOLETA = colors.HexColor(HEX_VIOLETA)
        COR_MAGENTA = colors.HexColor(HEX_MAGENTA)
        COR_TEXTO_MUT = colors.HexColor(HEX_TEXTO_MUT)
        COR_GRAFITE = colors.HexColor(HEX_GRAFITE)

        doc = SimpleDocTemplate(nome_pdf, pagesize=letter, rightMargin=40, leftMargin=40, topMargin=40, bottomMargin=40)
        styles = getSampleStyleSheet()

        style_title = ParagraphStyle(name="TitleNexus", parent=styles["Heading1"], fontName="Helvetica-Bold",
                                     fontSize=22, textColor=COR_VIOLETA, spaceAfter=8, alignment=1)
        style_sub = ParagraphStyle(name="SubNexus", parent=styles["Normal"], fontSize=10,
                                   textColor=COR_TEXTO_MUT, spaceAfter=20, alignment=1)
        style_body = ParagraphStyle(name="BodyNexus", parent=styles["Normal"], fontSize=10,
                                    leading=14, textColor=colors.white)
        style_th = ParagraphStyle(name="THNexus", parent=styles["Normal"], fontSize=10,
                                  fontName="Helvetica-Bold", textColor=colors.white)
        style_sec = ParagraphStyle(name="SecNexus", parent=styles["Heading2"], fontSize=13,
                                   textColor=COR_MAGENTA, spaceBefore=18, spaceAfter=6)

        story = [
            Paragraph("MINDCORE CORE - MATRIZ DE EXPANSÃO", style_title),
            Paragraph(
                f"Relatório Consolidado de Alta Performance Humana e Estabilidade Temporal — Emitido em {dados['data']}",
                style_sub,
            ),
        ]

        dados_tabela = [
            [Paragraph("Diretriz Analítica da Matriz", style_th), Paragraph("Métrica Consolidada", style_th)],
            [Paragraph("<b>Operador do Sistema:</b>", style_body), Paragraph(dados["usuario"], style_body)],
            [Paragraph("<b>Pilar de Excelência:</b>", style_body), Paragraph(dados["pilar"], style_body)],
            [Paragraph("<b>Tempo de Dedicação:</b>", style_body), Paragraph(f"{dados['tempo']} anos", style_body)],
            [Paragraph("<b>Índice de Expansão (IEH):</b>", style_body), Paragraph(f"<b>{dados['ieh']} / 1.0000</b>", style_body)],
            [Paragraph("<b>Classificação Biológica:</b>", style_body), Paragraph(dados["estagio"], style_body)],
        ]

        t = Table(dados_tabela, colWidths=[200, 320])
        t.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (1, 0), COR_VIOLETA),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 8),
            ('TOPPADDING', (0, 0), (-1, -1), 8),
            ('LEFTPADDING', (0, 0), (-1, -1), 10),
            ('ROWBACKGROUNDS', (0, 1), (-1, -1), [COR_GRAFITE, COR_OBSIDIANA]),
            ('GRID', (0, 0), (-1, -1), 0.5, COR_MAGENTA),
        ]))
        story.append(t)

        # ---- Gráfico radar vetorial nativo -------------------------------
        labels = dados["charts"]["labels"]
        valores = dados["charts"]["datasets"][0]["data"]

        story.append(Paragraph("Radar de Performance por Sub-indicador", style_sec))

        d = Drawing(500, 215)
        spider = SpiderChart()
        spider.x = 175
        spider.y = 30
        spider.width = 150
        spider.height = 150
        spider.data = [valores, [100] * len(valores)]
        spider.labels = labels
        spider.strandLabels.format = None
        spider.strands[0].strokeColor = COR_MAGENTA
        spider.strands[0].fillColor = colors.Color(109 / 255, 40 / 255, 217 / 255, 0.35)
        spider.strands[0].strokeWidth = 2
        spider.strands[1].strokeColor = COR_TEXTO_MUT
        spider.strands[1].fillColor = None
        spider.strands[1].strokeWidth = 0.6
        spider.strandLabels.fontName = "Helvetica"
        spider.strandLabels.fontSize = 7
        for i in range(len(labels)):
            spider.labels[i] = labels[i]
        d.add(spider)
        d.add(String(0, 200, "Escala 0–100% do potencial máximo (linha cinza = teto de referência)",
                     fontName="Helvetica", fontSize=8, fillColor=COR_TEXTO_MUT))
        story.append(d)

        # ---- Leitura numérica dos sub-indicadores ------------------------
        linhas_sub = [[Paragraph("Sub-indicador", style_th), Paragraph("% do potencial máximo", style_th)]]
        for nome_sub, valor in zip(labels, valores):
            linhas_sub.append([Paragraph(nome_sub, style_body), Paragraph(f"{valor}%", style_body)])
        t2 = Table(linhas_sub, colWidths=[320, 200])
        t2.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (1, 0), COR_VIOLETA),
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 7),
            ('TOPPADDING', (0, 0), (-1, -1), 7),
            ('LEFTPADDING', (0, 0), (-1, -1), 10),
            ('ROWBACKGROUNDS', (0, 1), (-1, -1), [COR_GRAFITE, COR_OBSIDIANA]),
            ('GRID', (0, 0), (-1, -1), 0.5, COR_MAGENTA),
        ]))
        t2.repeatRows = 1
        story.append(Spacer(1, 6))
        story.append(KeepTogether(t2))

        doc.build(story)
        return True

    @staticmethod
    def buscar_no_historico(termo_busca, tipo_filtro, nome_csv="historico_matriz_nexus.csv"):
        if not os.path.exists(nome_csv):
            print("\n[INFO] Nenhum histórico encontrado ainda.")
            return
        campo = "Nome" if tipo_filtro == "nome" else "Pilar"
        encontrados = []
        with open(nome_csv, "r", encoding="utf-8") as f:
            for row in csv.DictReader(f):
                if termo_busca.strip().lower() in row.get(campo, "").lower():
                    encontrados.append(row)
        print("\n" + "─" * 70)
        if not encontrados:
            print(f" [INFO] Nenhum registro encontrado para '{termo_busca}' em {campo}.")
        else:
            print(f" [RESULTADO] {len(encontrados)} registro(s) encontrado(s):")
            print(f" {'Data/Hora':<20} | {'Nome':<18} | {'Pilar':<42} | IEH")
            print("─" * 70)
            for r in encontrados:
                print(f" {r.get('Data', ''):<20} | {r.get('Nome', ''):<18} | {r.get('Pilar', ''):<42} | {r.get('IEH', '')}")
        print("─" * 70)


def executar_analise(nome_usuario, opcao, valores, silencioso=False):
    """Executa o ciclo completo: cálculo, plano de ação, CSV, PDF e payload de gráficos."""
    nome_pilar, sub_nomes, ieh, notas_norm, tempo_anos, ep, et = MatrizUniversalNexus.processar_pilar_complexo(opcao, valores)
    estagio = GeradorMetasUniversais.classificar_estagio_humano(ieh)
    chart_json = GeradorMetasUniversais.estruturar_dataset_graficos(nome_pilar, sub_nomes, notas_norm, ieh)

    ieh_anterior = GeradorMetasUniversais.buscar_ultimo_ieh(nome_usuario, nome_pilar)
    evolucao = GeradorMetasUniversais.comparar_evolucao(ieh, ieh_anterior)

    data_arquivo = datetime.now().strftime("%Y%m%d%H%M%S")
    dados_registro = {
        "data": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "usuario": nome_usuario, "pilar": nome_pilar,
        "ieh": ieh, "estagio": estagio, "sub_indicadores": valores[:-1], "tempo": tempo_anos, "charts": chart_json,
    }

    DatabaseCloudNexus.conectar_e_persistir(dados_registro)

    nome_md = f"plano_acao_{nome_usuario.lower()}_{data_arquivo}.md"
    GeradorMetasUniversais.gerar_plano_acao_markdown(nome_pilar, sub_nomes, notas_norm, ieh, nome_md)

    nome_pdf = f"relatorio_{nome_usuario.lower()}_{data_arquivo}.pdf"
    pdf_gerado = GeradorMetasUniversais.gerar_pdf_executivo(nome_pdf, dados_registro)

    if not silencioso:
        barra = GeradorMetasUniversais.gerar_barra_progresso(ieh)
        print("\n╔" + "═" * 68 + "╗")
        print("║ ✅ PROCESSAMENTO CONCLUÍDO COM SUCESSO COGNITIVO                    ║")
        print("╚" + "═" * 68 + "╝")
        print(f" 🎯 Pilar: {nome_pilar}")
        print(f" 📈 Eficiência de Pico: {ep * 100:.2f}% | ⏳ Estabilidade Temporal: {et * 100:.2f}%")
        print(f" 🧬 IEH: {ieh:.4f} [{barra}] {ieh * 100:.1f}% do potencial máximo")
        print(f" 🏆 Classificação: {estagio}")
        print(f" 📶 Evolução: {evolucao}")
        print(f" 🛡️  Plano de Ação Semanal (Markdown): '{nome_md}'")
        if pdf_gerado:
            print(f" 📕 Relatório PDF com radar vetorial: '{nome_pdf}'")
        else:
            print(" ⚠️  Biblioteca 'reportlab' não instalada — PDF pulado (pip install reportlab).")
        print("\n 💻 PAYLOAD DOS GRÁFICOS (JSON COMPATÍVEL COM WEB):")
        print(json.dumps(chart_json, indent=2, ensure_ascii=False))

    return {"ieh": ieh, "estagio": estagio, "md": nome_md, "pdf": nome_pdf if pdf_gerado else None, "charts": chart_json}


def limpar_tela():
    """Limpa o terminal sem invocar shell (evita injecao de comando)."""
    print("\033[2J\033[H", end="")


def menu_principal():
    print("╔" + "═" * 68 + "╗")
    print("║            MINDCORE CORE v4.0 - PLATAFORMA INTEGRADA               ║")
    print("╚" + "═" * 68 + "╝")
    nome_usuario = input(" 👤 Digite o identificador do operador: ").strip() or "Individuo_Anonimo"
    limpar_tela()

    while True:
        print("╔" + "═" * 68 + "╗")
        print(f"║ INTERFACE WEB SINCRONIZADA | OPERADOR: {nome_usuario[:15].upper().ljust(15)}                  ║")
        print("╚" + "═" * 68 + "╝")
        for k, cfg in MatrizUniversalNexus.CONFIG_PILARES.items():
            print(f" [{k}] Analisar Pilar: {cfg['nome']}")
        print(" [6] Buscar diagnóstico por NOME")
        print(" [7] Buscar diagnóstico por PILAR")
        print(" [0] Encerrar Sessão no Banco Real")
        print("─" * 70)

        try:
            opcao = int(input(" Selecione uma opção: ") or 0)
        except ValueError:
            continue

        if opcao == 0:
            break

        if opcao in (6, 7):
            termo = input(" 🔍 Digite o termo a buscar: ")
            GeradorMetasUniversais.buscar_no_historico(termo, "nome" if opcao == 6 else "pilar")
            input("\n Pressione [ENTER] para retornar ao painel...")
            limpar_tela()
            continue

        if opcao in MatrizUniversalNexus.CONFIG_PILARES:
            cfg = MatrizUniversalNexus.CONFIG_PILARES[opcao]
            print("\n📥 ENTRADA DE SUB-INDICADORES (valores numéricos):")
            print("─" * 70)
            v1 = float(input(f" 🔹 {cfg['sub_nomes'][0]}: ") or 0)
            v2 = float(input(f" 🔹 {cfg['sub_nomes'][1]}: ") or 0)
            v3 = float(input(f" 🔹 {cfg['sub_nomes'][2]}: ") or 0)
            tempo = float(input(" ⏳ Tempo de Dedicação Ativa (em anos): ") or 0)

            executar_analise(nome_usuario, opcao, [v1, v2, v3, tempo])
            input("\n Pressione [ENTER] para retornar ao painel...")
            limpar_tela()


if __name__ == "__main__":
    menu_principal()
