import re
import math
from dataclasses import dataclass
from num2words import num2words
from langchain_openai import ChatOpenAI
from langchain_oci import ChatOCIGenAI
#from langchain_google_genai import ChatGoogleGenerativeAI
import math

from app.common.timed import timed
from dotenv import load_dotenv
import os
load_dotenv()

def sentence_confidence(words):
    probs = [w["probability"] for w in words if w["probability"] > 0]
    if not probs:
        return 0.0
    log_mean = sum(math.log(p) for p in probs) / len(probs)
    return round(math.exp(log_mean), 4)

"""llm = ChatOpenAI(
            model="openai/gpt-oss-20b",
            api_key="fake-key",
            base_url="http://10.153.34.154/gpt-oss-20b/v1",
            temperature=0.0,
            top_p=0.1,
            reasoning_effort="low",
        )"""
        
llm = ChatOCIGenAI(
            model_id=os.getenv("OCI_ENDPOINT_ID", ""),
            service_endpoint=os.getenv("OCI_ENDPOINT", ""),
            compartment_id=os.getenv("OCI_COMPARTMENT_ID", ""),
            auth_file_location=os.getenv("OCI_AUTH_FILE_LOCATION", "./config"),
            model_kwargs={"temperature": 0.0,
                        "top_p": 0.1,
                        "reasoning_effort":"MINIMAL"}
        )


target_plans = {"TIM_BLACK_C_LIGHT":{
    "plano": "\"TIM Black Cê Light\"",
    "beneficios_001": "tem as principais redes sociais sem consumir seus gigas, e ainda ganha o Deezer pra ouvir suas músicas",
    "beneficios_002": "não consome seus gigas quando usar as principais redes sociais, tem acesso ao wifi nos aviões da gol e da latân e tem também o pacote chile de roaming internacional",
    "beneficios_todos": """ligações e SMS ilimitados. Instagram, Facebook, X e mensagens de texto no Whatsapp sem consumir seus gigas. Acesso ao wifi nos aviões da gol e da latân. Pacote Chile de roaming internacional.""",
    "dependentes": "Não há dependentes",
    "forma_pagamento": "Fatura",
    "comunicacao_whatsapp": "troca de mensagens é ilimitada, mas áudio e vídeo consomes seus Gigas",
    "comunicacao_ligacoes_voz": "Ilimitadas",
    "comunicacao_sms": "Ilimitados",
    "wifi_no_aviao": "TIM no Avião",
    "roaming_internacional": "Pacote Chile",
    "servicos_valor_agregado": """ "Aya Audiobooks Premium", "Bancah Premium" mais Jornais", "EXA Segurança Premium", "Aya Ensinah Premium", "EXA Cloud", Busuu, "Fluid Premium" """,
    "nao_consome_dos_gigas": "Instagram, Facebook, X",
    "aplicativos_inclusos": "Não há",
    "aplicativos_a_escolher": "Não há"
},
"TIM_BLACK_A":{
    "plano": "\"TIM Black AH\"", 
    "beneficios_001": "tem as principais redes sociais sem consumir seus gigas, e ainda ganha o Deezer pra ouvir suas músicas",
    "beneficios_002": "tem o aplicativo de músicas Deezer incluído na mensalidade, não consome seus gigas quando usar as principais redes sociais, tem acesso ao wifi nos aviões da gol e da latân e tem também o pacote américas de roaming internacional",
    "beneficios_todos": """aplicativo Deezer. Ligações e SMS ilimitados. Instagram, Facebook e X ilimitados. Além disso, acesso ao wifi nos aviões da gol e latân, juntamente com o pacote Américas de roaming internacional.""",    
    "categoria_plano": "pós pago",
    "dependentes": "Não há dependentes",
    "forma_pagamento": "Fatura",
    "comunicacao_whatsapp": "ilimitado para texto, audio, video",
    "comunicacao_ligacoes_voz": "Ilimitadas",
    "comunicacao_sms": "Ilimitados",
    "wifi_no_aviao": "TIM no Avião",
    "roaming_internacional": "Pacote Américas",
    "servicos_valor_agregado": """ "Aya Audiobooks Premium", "Bancah Premium mais Jornais", "EXA Segurança Premium", "Aya Ensinah Premium", "EXA Cloud", Busuu, "Fluid Premium", "Fit Me App", "It Game" """,
    "nao_consome_dos_gigas": "Instagram, Facebook, X",
    "aplicativos_inclusos": "Deezer",
    "aplicativos_a_escolher": "Não há"
},
"TIM_BLACK_C_HERO":{
    "plano": "\"Tim Black Cê Hero\"", 
    "beneficios_001": "tem as principais redes sociais sem consumir seus gigas, podendo escolher um aplicativo de streaming entre: Deezer, Disney plus, Max, Prime video e Youtube premium",
    "beneficios_002": "não consome seus gigas quando usar as principais redes sociais, tem acesso ao wifi nos aviões da gol e da latân e tem também o pacote américas de roaming internacional.",
    "beneficios_todos": """Escolher um aplicativo entre: Deezer, Disney plus, Max, Prime video e Youtube premium. Ligações e SMS ilimitados. Instagram, Facebook e X ilimitados. Além disso, acesso ao wifi nos aviões da gol e latân, juntamente com o pacote Américas de roaming internacional.""",    
    "categoria_plano": "pós pago",
    "dependentes": "Não há dependentes",
    "forma_pagamento": "Fatura",
    "comunicacao_whatsapp": "ilimitado para texto, audio, video",
    "comunicacao_ligacoes_voz": "Ilimitadas",
    "comunicacao_sms": "Ilimitados",
    "wifi_no_aviao": "TIM no Avião",
    "roaming_internacional": "Pacote Américas",
    "servicos_valor_agregado": """ "Aya Audiobooks Premium", "Bancah Premium mais Jornais", "EXA Segurança Premium", "Aya Ensinah Premium", "EXA Cloud", Busuu, "Fluid Premium", "Fit Me App", "It Game" """,
    "nao_consome_dos_gigas": "Instagram, Facebook, X",
    "aplicativos_inclusos": "A escolher",
    "aplicativos_a_escolher": "Deezer, Disney plus, Max, Prime video, Youtube premium"
}

}
@timed("normalize_name")
def normalize_name(name):
    x = f"""Normalize o nome abaixo: capitalize e acentue conforme o padrão brasileiro.
Nomes estrangeiros não devem ser acentuados. Retorne APENAS o nome, nada mais.
Exemplos:

fabio assuncao muller → Fábio Assunção Muller
fatima schmidt → Fátima Schmidt
romulo aragao → Rômulo Aragão
angela maria → Ângela Maria
hortencia → Hortência
EMANUELA → Emanuela
jose dos santos → José dos Santos
lucio fernandez → Lúcio Fernandez
GONCALVES → Gonçalves
JOAO PAULO → João Paulo
---
Nome: {name}
Resultado:"""
    result = llm.invoke(x)
    #print("Texto:",result.content)
    #print("Metadata:",result.usage_metadata)
    #print("*"*100)
    return result.content

def get_gender(mailing):
    mailing['SEXO'] = llm.invoke("Retorne APENAS as letras M ou F de acordo com o nome se o sexo é masculino ou feminimo não use ' ou ` retorne apenas uma letra, sendo M ou F:" + mailing['NOME_CLIENTE_COMPLETO']).content
    mailing['TRATAMENTO'] = "O senhor" if mailing['SEXO'] == "M" else "A senhora"
    return mailing

def money_to_words(value: float) -> str:
    if value is None:
        return ""

    reais = int(value)
    centavos = int(round((value - reais) * 100))

    partes = []
    if reais > 0:
        partes.append(f"{num2words(reais, lang='pt_BR')} real" if reais == 1 else f"{num2words(reais, lang='pt_BR')} reais")
    if centavos > 0:
        partes.append(f"{num2words(centavos, lang='pt_BR')} centavo" if centavos == 1 else f"{num2words(centavos, lang='pt_BR')} centavos")

    return " e ".join(partes) if partes else "zero real"

def calculate_data_bonus(mailing: dict) -> float | None:
    gb = eval(mailing['BONUS_DESTINO'])
    if mailing['PLANO_DESTINO'] == "TIM_BLACK_A":
        gb += 15
    if mailing['PLANO_DESTINO'] == "TIM_BLACK_C_LIGHT":
        gb += 20

    return gb

def process_plan(plan: dict, mailing: dict, plan_type: str = "actual") -> dict:

    plan.pop("preco_reais", None)
    plan.pop("dados_GB", None)
    if plan_type == "actual":
        valor = mailing.get("MEDIA_RECARGA_2")
        fidelization = mailing.get("FIDELIZACAO") or {}
        if valor:
            plan["valor_pago_ultimos_3_meses"] = money_to_words(valor)
        else:
            plan["valor_pago_ultimos_3_meses"] = "Não informado"
        
        plan["plano"] = f"\"{mailing["PLANO_ORIGEM"].strip().title()}\""

        plan["data_expirar_fidelizacao"] = fidelization.get("final_date")
        plan["meses_restantes_fidelizacao"] = fidelization.get("expiration")
        plan["valor_plano_sem_fidelização"] = money_to_words(mailing["VALOR_PLANO_CORE"])

        plan["gb_plano_atual"] = num2words(float(mailing.get("DADOS_CORE").replace(',','.').replace('GB','')), lang='pt_BR')

    elif plan_type == "target":
        bruto = mailing.get("VLR_PLANO_DESTINO", 0) or 0
        final = mailing.get("VLR_FINAL_PLANO_DEST", 0) or 0
        desconto = round(bruto - final, 2)
        plan['plano'] = plan['plano'].title()
        
        if mailing.get("MEDIA_RECARGA_2"):
            plan['quanto_pago_a_mais'] = money_to_words(abs(math.ceil(final - mailing.get("MEDIA_RECARGA_2"))))
        else:
            plan['quanto_pago_a_mais'] = "Não informado"

        dados_gb = calculate_data_bonus(mailing)

        gb_atual = float(mailing.get("DADOS_CORE").replace(',','.').replace('GB',''))
        gb_alvo_diferenca = dados_gb - gb_atual

        plan.update({
            "valor_plano_bruto": money_to_words(bruto),
            "valor_desconto": money_to_words(desconto),
            "valor_plano_final": money_to_words(final),
            "diferenca_reajuste_fidelizacao": money_to_words(mailing.get("VLR_FINAL_PLANO_DEST", 0) - mailing.get("VALOR_PLANO_CORE", 0)),
            "dados_GB": num2words(dados_gb, lang='pt_BR'),
            "gb_alvo_diferenca": num2words(gb_alvo_diferenca, lang='pt_BR'),
            "preço_por_dia": f"{money_to_words(round(final/30, 2))}"
        })

    else:
        raise ValueError("Tipo de plano inválido. Use 'actual' ou 'target'.")
    #print(plan)
    return plan

def process_mailing(mailing: dict, campos_desejados=None) -> dict:
    """
    Filtra e padroniza os dados do mailing conforme as chaves relevantes.
    """
    if campos_desejados is None:
        campos_desejados = [
            "NOME_CLIENTE_COMPLETO", "NUM_CPF_CNPJ_CLIENTE", "NUM_TELEFONE",
            "DT_NASCIMENTO", "PLANO_ORIGEM", "FLG_TRIPLE_A_OP", "TIPO_MAILING",
            "DAT_NASCIMENTO", "NOME_MAE", "SEXO", "TRATAMENTO", "BONUS_DESTINO",
            "ELEGIBILIDADE", "PROTOCOLO", "cliente_alvo_primeiro_nome"
        ]

    mailing["cliente_alvo_primeiro_nome"] = mailing["NOME_CLIENTE_COMPLETO"].split(" ")[0]
    mailing["NUM_CPF_CNPJ_CLIENTE"] = mailing.get("NUM_CPF_CNPJ_CLIENTE", "")[-3:]
    return {k: v for k, v in mailing.items() if k in campos_desejados}

def get_plan(plan: str):
    return target_plans[plan]

def start_message_argumentation(variaveis: dict) -> str:
    meses_restantes = variaveis.get("meses_restantes_fidelizacao")
    quanto_pago = variaveis.get("quanto_pago_a_mais_int")

    # Definição do texto base conforme regras
    if meses_restantes is not None and meses_restantes <= 2:
        
        if quanto_pago is not None and quanto_pago <= 20:
            template = """[cliente_alvo_primeiro_nome]! Você tem hoje um plano controle com [gb_plano_atual] gigas de internet. Em pouco tempo, mais exatamente em [um_mes_ou_dois_meses], acaba o período promocional que você possui e ele será reajustado para [valor_plano_sem_fidelização], que é o valor integral do seu plano sem os descontos. Para que você não tenha que pagar este reajuste sem receber novas vantagens, a TIM aprovou sua migração para o plano TIM Black, onde, ao invés dos [gb_plano_atual] gigas de hoje você terá [dados_GB] Gigas pra usar a internet à vontade e também [beneficios_001]. Este novo plano tem o valor de [valor_plano_final] por mês, sem aumento por doze meses. Uma pequena diferença de [quanto_pago_a_mais] comparando o valor reajustado do seu plano, com muito mais benefícios. Vamos mudar seu plano e aproveitar essa super promoção?"""
        else:
            template = """[cliente_alvo_primeiro_nome]! Você tem hoje um plano controle com [gb_plano_atual] gigas de internet. Em pouco tempo, mais exatamente em [um_mes_ou_dois_meses], acaba o período promocional que você possui e ele será reajustado para [valor_plano_sem_fidelização], que é o valor integral do seu plano sem os descontos. Para que você não tenha que pagar este reajuste sem receber novas vantagens, a TIM aprovou sua migração para o plano TIM Black, onde, ao invés dos [gb_plano_atual] gigas de hoje você terá [dados_GB] Gigas pra usar a internet à vontade e também [beneficios_001]. Este novo plano tem o valor de [valor_plano_final] por mês, sem aumento por doze meses. Vamos mudar seu plano e aproveitar essa super promoção?"""

    else:
        if quanto_pago is not None and quanto_pago <= 20:
            template = """[cliente_alvo_primeiro_nome], tenho uma novidade ótima pra você. O plano Black com [gb_alvo_diferenca] gigas a mais para você navegar sem preocupação pagando quase a mesma coisa, [quanto_pago_a_mais] a mais no total de [valor_plano_final] mensais. Vamos aproveitar essa condição?"""
        else:
            template = """[cliente_alvo_primeiro_nome], tenho uma novidade ótima pra você. O plano Black com [gb_alvo_diferenca] gigas a mais para você navegar sem preocupação juntamente com outros benefícios por cerca de [preco_por_dia] por dia, no total de [valor_plano_final] mensais. Vamos aproveitar essa condição?"""

    # Tratamento especial para "um mês / dois meses"
    if meses_restantes in [0,1]:
        variaveis["um_mes_ou_dois_meses"] = "um mês"
    elif meses_restantes == 2:
        variaveis["um_mes_ou_dois_meses"] = "dois meses"
    else:
        variaveis["um_mes_ou_dois_meses"] = ""

    # Função de substituição automática
    def substituir(match):
        chave = match.group(1)
        return str(variaveis.get(chave, ""))

    mensagem_final = re.sub(r"\[([^\]]+)\]", substituir, template)

    return mensagem_final
