from pathlib import Path
from urllib.request import urlretrieve

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import FeatureUnion, Pipeline

ARQUIVO = Path("compras_classificacao.csv")
SAIDA = Path("compras_classificadas.xlsx")
URL_EXEMPLO = "https://cortex360.com.br/quick-start/files/compras_classificacao.csv"
LIMIAR_CONFIANCA = 0.60

if not ARQUIVO.exists():
    urlretrieve(URL_EXEMPLO, ARQUIVO)

base = pd.read_csv(ARQUIVO)
treino = base[base["Tipo"] == "Treinamento"].copy()
novas = base[base["Tipo"] == "Nova"].copy()

X = treino["Descricao"].astype(str)
y = treino["Categoria"].astype(str)

X_treino, X_teste, y_treino, y_teste = train_test_split(
    X, y, test_size=0.25, random_state=42, stratify=y
)


def criar_modelo():
    texto = FeatureUnion(
        [
            ("palavras", TfidfVectorizer(
                ngram_range=(1, 2), strip_accents="unicode",
                sublinear_tf=True, min_df=1,
            )),
            ("trechos", TfidfVectorizer(
                analyzer="char_wb", ngram_range=(3, 5),
                strip_accents="unicode", sublinear_tf=True, min_df=2,
            )),
        ],
        transformer_weights={"palavras": 0.5, "trechos": 1.5},
    )
    return Pipeline([
        ("texto", texto),
        ("classificador", LogisticRegression(
            max_iter=4000, C=4, random_state=42,
        )),
    ])


# Primeiro medimos o modelo em dados reservados para teste.
modelo = criar_modelo()
modelo.fit(X_treino, y_treino)
previsoes_teste = modelo.predict(X_teste)
acuracia = accuracy_score(y_teste, previsoes_teste)
print(f"Acurácia no conjunto didático de teste: {acuracia:.1%}")

# Depois da validação, treinamos novamente usando toda a base conhecida.
modelo = criar_modelo()
modelo.fit(X, y)

descricoes = novas["Descricao"].astype(str)
previsoes = modelo.predict(descricoes)
probabilidades = modelo.predict_proba(descricoes)
confiancas = probabilidades.max(axis=1)

resultado = novas[["ID_Compra", "Descricao"]].copy()
resultado["Categoria_Prevista"] = previsoes
resultado["Confianca"] = confiancas
resultado["Decisao"] = [
    "Automático" if valor >= LIMIAR_CONFIANCA else "Revisar categoria"
    for valor in confiancas
]

resultado.to_excel(SAIDA, index=False)

print("\nClassificações:")
print(resultado.to_string(index=False))
print(f"\nArquivo gerado: {SAIDA.resolve()}")
print("Confiança abaixo de 60% segue para revisão humana.")
