# Cortex360 Quick Start — scikit-learn + Contabilidade
# Instale antes:
# pip install pandas openpyxl scikit-learn

from pathlib import Path
import numpy as np
import pandas as pd
from sklearn.ensemble import IsolationForest

entrada = Path("lancamentos_contabeis.xlsx")
saida = Path("lancamentos_analisados.xlsx")

if not entrada.exists():
    raise FileNotFoundError(
        "Baixe lancamentos_contabeis.xlsx na página do Quick Start "
        "e coloque o arquivo na mesma pasta deste script."
    )

# 1. Ler os lançamentos contábeis.
df = pd.read_excel(entrada, sheet_name="Lancamentos")
df["Data"] = pd.to_datetime(df["Data"])

# 2. Criar características que ajudam o modelo a entender o contexto.
df["Valor"] = df["Débito"].where(df["Débito"] > 0, df["Crédito"])
df["Dia_Mes"] = df["Data"].dt.day

# Compara o valor do lançamento com a mediana da própria conta contábil.
df["Mediana_Conta"] = df.groupby("Conta")["Valor"].transform("median")
df["Razao_Conta"] = df["Valor"] / df["Mediana_Conta"].replace(0, np.nan)

# 3. Transformar campos categóricos em colunas numéricas.
categorias = pd.get_dummies(
    df[["Conta", "Centro de Custo", "Natureza"]],
    dtype=float,
)

X = pd.concat(
    [
        df[["Valor", "Dia_Mes", "Razao_Conta"]].reset_index(drop=True),
        categorias.reset_index(drop=True),
    ],
    axis=1,
)

# 4. Treinar o detector de anomalias.
# Neste conjunto didático, aproximadamente 5% dos registros foram
# construídos para representar comportamentos atípicos.
modelo = IsolationForest(
    contamination=0.05,
    random_state=42,
)

df["Predicao"] = modelo.fit_predict(X)
df["Score_Anomalia"] = -modelo.decision_function(X)
df["Status"] = np.where(df["Predicao"] == -1, "Revisar", "Normal")

# 5. Organizar o resultado.
resultado = df.drop(columns=["Predicao"]).sort_values(
    ["Status", "Score_Anomalia"],
    ascending=[False, False],
)

resultado.to_excel(saida, index=False)

revisar = resultado[resultado["Status"] == "Revisar"]

print(f"{len(revisar)} lançamentos foram priorizados para revisão.\n")
print(
    revisar[
        ["Data", "Lançamento", "Conta", "Centro de Custo", "Valor", "Score_Anomalia", "Status"]
    ].to_string(index=False)
)
print(f"\nArquivo gerado: {saida.resolve()}")
print("\nImportante: anomalia não significa erro ou fraude; significa somente que o lançamento merece revisão humana.")
