from app.domain.contas.parsers.invoice_to_text import get_vas_product_names, to_text


def _build_lines(text: str) -> list[str]:
    return text.splitlines()


def test_sva_renderiza_acao_por_item() -> None:
    """SVA: header "Itens Eventuais | cobrados a parte" (a seção "SVA Detalhe Total"
    é impressa sob esse rótulo); estrategico -> 'falar sobre'; avulso -> 'cancelar'."""
    data = {
        "11999990000": {
            "SVA Detalhe Total": [
                {"desc": "Aluguel de Filme 1", "value": 19.90, "period": "02/05/26"},
                {
                    "desc": "YouTube Premium Mensal",
                    "value": 24.90,
                    "period": "02/05/26",
                    "estrategico": True,
                },
            ],
        }
    }

    lines = _build_lines(to_text(data))

    # header "cobrados a parte", sem "| ação=... | avulso"
    assert "Itens Eventuais | cobrados a parte" in lines
    assert "SVA Detalhe Total" not in to_text(data)

    avulso = next(l for l in lines if "Aluguel de Filme 1" in l)
    estrategico = next(l for l in lines if "YouTube Premium Mensal" in l)

    assert avulso.endswith("| ação=cancelar")
    # Item estratégico no SVA: ação "falar sobre" + marcador "type=estrategico".
    assert "| ação=falar sobre" in estrategico
    assert estrategico.endswith("| type=estrategico")


def test_itens_eventuais_cobrados_a_parte_acao_por_item() -> None:
    """Itens Eventuais: header "cobrados a parte" + ação por item (avulso ->
    'cancelar'; estratégico -> 'falar sobre' + 'type=estrategico')."""
    data = {
        "11999990000": {
            "Itens Eventuais": [
                {"desc": "Serviço Avulso X", "value": 9.90, "period": "02/05/26"},
                {
                    "desc": "Max Mensal",
                    "value": 34.90,
                    "period": "02/05/26",
                    "estrategico": True,
                },
            ],
        }
    }

    lines = _build_lines(to_text(data))

    assert "Itens Eventuais | cobrados a parte" in lines
    assert "Itens Eventuais | ação=cancelar | avulso" not in lines

    avulso = next(l for l in lines if "Serviço Avulso X" in l)
    estrategico = next(l for l in lines if "Max Mensal" in l)

    assert avulso.endswith("| ação=cancelar")
    assert "| ação=falar sobre" in estrategico
    assert estrategico.endswith("| type=estrategico")


def test_sva_e_itens_eventuais_mesclam_num_unico_cabecalho() -> None:
    """Linha com as DUAS seções ("SVA Detalhe Total" e "Itens Eventuais"): um único
    cabeçalho "Itens Eventuais", na posição da primeira delas, com os itens das duas
    embaixo. A ação por item continua vindo da seção de ORIGEM."""
    data = {
        "11999990000": {
            "SVA Detalhe Total": [
                {"desc": "Tamboro Mensal", "value": 14.99, "period": "01/11/25"},
            ],
            "Mensalidades Adicionais": [{"desc": "Plugin 5G Plus", "value": 5.00}],
            "Itens Eventuais": [
                {"desc": "Serviço Avulso X", "value": 9.90, "period": "02/05/26"},
                {"desc": "CRÉDITO: PAGAMENTO", "value": -20.00},
            ],
        }
    }

    full = to_text(data)
    lines = _build_lines(full)

    assert lines.count("Itens Eventuais | cobrados a parte") == 1
    assert "SVA Detalhe Total" not in full
    # Posição: o bloco mesclado fica onde a PRIMEIRA das duas seções aparecia,
    # antes de "Mensalidades Adicionais".
    assert [l for l in lines if not l[:1].isspace() and l] == [
        "LINHA 11999990000",
        "Itens Eventuais | cobrados a parte",
        "Mensalidades Adicionais",
        "multiplas_linhas = false",
    ]
    assert "  Tamboro Mensal | valor=14.99 | data=01/11/25 | ação=cancelar" in lines
    assert "  Serviço Avulso X | valor=9.90 | data=02/05/26 | ação=cancelar" in lines
    assert "  CRÉDITO: PAGAMENTO | valor=-20.00 | ação=cancelar" in lines

    # No modo enxuto o cabeçalho mesclado é só o rótulo (sem "| cobrados a parte").
    lean_lines = _build_lines(to_text(data, lean=True))
    assert lean_lines.count("Itens Eventuais") == 1
    assert "  Tamboro Mensal | valor=14.99 | data=01/11/25" in lean_lines
    assert "  Serviço Avulso X | valor=9.90 | data=02/05/26" in lean_lines


def test_lean_enxuga_para_o_intent() -> None:
    """``lean=True`` (formato do intent classifier): mantém LINHA/seção, o NOME dos
    itens e ``valor``/``data`` por item (para desambiguar cobranças duplicadas);
    descarta Fatura Resumo, Planos, Outros Valores e os demais campos por-item
    (ação/type/franquia/consumo). Item ``Incluído`` e período em faixa não geram
    valor/data."""
    data = {
        "Fatura Resumo": [{"desc": "total geral", "value": 207.43}],
        "1199999999": {
            "Planos": {"TIM Black A 8.0": {"valor_final": 104.99}},
            "Outros Valores": [{"desc": "juros: (VENC 10/11)", "value": 0.26}],
            "SVA Detalhe Total": [
                {"desc": "Tamboro Mensal", "value": 14.99, "period": "01/11/25"},
                {"desc": "Youtube Premium", "value": 10.0, "estrategico": True},
            ],
            "Serviços Bundle Inclusos": [
                {"desc": "Minutos Locais e DDD com 41", "value": "Incluído",
                 "period": "19/05 a 18/06", "franchise": "Ilimitado",
                 "consumption": "43m30s"},
            ],
        },
    }

    lean = to_text(data, lean=True)
    lines = _build_lines(lean)

    # Estrutura + nome + valor/data por item (data só p/ período de data única).
    assert "LINHA 1199999999" in lines
    assert "  Tamboro Mensal | valor=14.99 | data=01/11/25" in lines
    # Estratégico sem período: valor sim, data não.
    assert "  Youtube Premium | valor=10.00" in lines
    # Bundle "Incluído" com período em faixa: só o nome (sem valor/data).
    assert "  Minutos Locais e DDD com 41" in lines
    assert "multiplas_linhas = false" in lines
    # Cabeçalho de seção é só o nome (sem "| ação=… | classe") no modo enxuto.
    assert "Benefícios do Plano" in lines
    assert "ação=" not in lean
    assert "| bundle" not in lean
    # valor/data por item agora PRESENTES (distinguem cobranças duplicadas).
    assert "valor=14.99" in lean
    assert "data=01/11/25" in lean
    # "Incluído" nunca vira valor=; período em faixa nunca vira data=.
    assert "valor=Incluído" not in lean
    assert "data=19/05" not in lean
    # Descartado: resumo, planos, outros valores e os demais campos por-item.
    assert "Fatura Resumo" not in lean
    assert "Planos" not in lean
    assert "Outros Valores" not in lean
    assert "TIM Black A 8.0" not in lean
    assert "type=estrategico" not in lean
    assert "franquia=" not in lean
    assert "consumo=" not in lean

    # O formato completo (default) SEGUE com tudo — orquestrador inalterado.
    full = to_text(data)
    assert "Fatura Resumo" in full
    assert "Planos" in full
    assert "valor=14.99" in full


def test_get_vas_product_names_ordem_e_filtra_nao_vas() -> None:
    """Só VAS, na ordem avulso -> estrategico -> bundle; plano e não-VAS ficam de
    fora. `classe` é a fonte; item com só `estrategico=True` (seção sem classe) cai
    no fallback estratégico."""
    data = {
        "Fatura Resumo": [{"desc": "total geral", "value": 100.0}],
        "vocalized_msisdn": {"11999990000": "um um ..."},
        "11999990000": {
            "Planos": {"TIM Black A 8.0": {"valor_final": 100.0}},
            "SVA Detalhe Total": [
                {"desc": "Focus Mensal", "value": 14.99, "classe": "avulso"},
                {"desc": "Netflix", "value": 39.9, "classe": "estrategico",
                 "estrategico": True},
            ],
            "Itens Eventuais": [
                {"desc": "Tamboro Mensal", "value": 9.9, "classe": "avulso"},
            ],
            "Serviços Bundle Inclusos": [
                {"desc": "HBO Bundle", "classe": "bundle"},
            ],
            # seção sem `classe`, só a flag -> fallback estratégico.
            "Cobranças de Terceiros": [
                {"desc": "Globoplay", "value": 19.9, "estrategico": True},
            ],
            "Descontos": [{"desc": "Desconto Fidelidade", "value": -10.0}],
        },
    }

    result = get_vas_product_names(data)

    assert result == "Focus Mensal, Tamboro Mensal, Netflix, Globoplay, HBO Bundle"
    # plano e seção não-VAS não entram.
    assert "TIM Black" not in result
    assert "Desconto" not in result


def test_get_vas_product_names_deduplica_entre_linhas() -> None:
    """Mesmo produto em duas linhas (MSISDN) aparece 1×, na primeira ocorrência."""
    data = {
        "11999990000": {"SVA Detalhe Total": [{"desc": "Focus Mensal", "classe": "avulso"}]},
        "11888880000": {"SVA Detalhe Total": [{"desc": "Focus Mensal", "classe": "avulso"}]},
    }

    assert get_vas_product_names(data) == "Focus Mensal"


def test_get_vas_product_names_sem_vas_retorna_vazio() -> None:
    assert get_vas_product_names({}) == ""
    assert get_vas_product_names(
        {"11999990000": {"Descontos": [{"desc": "X", "value": -1.0}]}}
    ) == ""
