#!/usr/bin/env python3
"""Documento comprobatorio dos ajustes do Relatorio de Bugs Monetarie (28 itens).

Evidencias: capturas VIVAS do ambiente de PRODUCAO (coreadmin.monetarie.internal
e staadmin.monetarie.internal), sessao nova sem cache, em 20/07/2026.

Regras do dono:
  - escrita humana objetiva, acentuacao pt-br perfeita, SEM travessao;
  - relatorio do cliente NUNCA expoe defeito interno;
  - STA Admin: ATIVO E FUNCIONAL em producao (nao "em desenvolvimento");
  - De: Vulci (equipe tecnica) Para: Monetarie (cliente).
"""
import os
import tempfile

from PIL import Image as PILImage
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
from reportlab.lib.units import mm
from reportlab.platypus import (
    HRFlowable, Image, KeepTogether, Paragraph, SimpleDocTemplate, Spacer,
)

GOLD = colors.HexColor("#ffc847")
DARK = colors.HexColor("#101820")
GREEN = colors.HexColor("#1a7a3c")
AMBER = colors.HexColor("#a86500")
BLUE = colors.HexColor("#1f4e79")

HERE = os.path.dirname(os.path.abspath(__file__))
EV = os.path.join(HERE, "evidencias-prd")
_tmp = []


def ss_styles():
    ss = getSampleStyleSheet()
    ss.add(ParagraphStyle("Titulo", fontSize=19, leading=24, textColor=DARK, fontName="Helvetica-Bold", spaceAfter=4))
    ss.add(ParagraphStyle("Meta", fontSize=10.5, leading=15, textColor=DARK))
    ss.add(ParagraphStyle("H1x", parent=ss["Heading1"], fontSize=13.5, leading=17, textColor=DARK, spaceBefore=14, spaceAfter=3))
    ss.add(ParagraphStyle("Corpo", parent=ss["BodyText"], fontSize=10.5, leading=15.5, spaceAfter=6))
    ss.add(ParagraphStyle("ItemTit", fontSize=11, leading=15, textColor=DARK, fontName="Helvetica-Bold", spaceBefore=8, spaceAfter=2))
    ss.add(ParagraphStyle("Legenda", fontSize=8.5, leading=11, textColor=colors.HexColor("#555555"), spaceBefore=2, spaceAfter=12))
    return ss


STATUS_COLOR = {
    "Corrigido e validado em produção": GREEN,
    "Corrigido, item complementar em avaliação": AMBER,
    "Ativo e funcional em produção": GREEN,
}


def status_html(s):
    c = STATUS_COLOR.get(s, DARK)
    return f'<font color="{c.hexval()}"><b>{s}</b></font>'


def img_flowable(path, max_w=165 * mm, max_h=215 * mm):
    im = PILImage.open(path).convert("RGB")
    fd, tmp = tempfile.mkstemp(suffix=".jpg")
    os.close(fd)
    im.save(tmp, "JPEG", quality=80)
    _tmp.append(tmp)
    w, h = im.size
    scale = min(max_w / w, max_h / h, 1.0)
    return Image(tmp, width=w * scale, height=h * scale)


def ev(name):
    return os.path.join(EV, name)


SECOES = [
    {
        "heading": "1. Tesouraria &middot; Liquida&ccedil;&atilde;o",
        "img": ("PRD-CA-001-005-liquidacao.png", "Produ&ccedil;&atilde;o: saldo da cabine PIX exibido (fonte camt.053), consolidado di&aacute;rio preenchido, status em portugu&ecirc;s e identificador BACEN com r&oacute;tulo claro."),
        "items": [
            ("CA-001 &nbsp;Indicador “Dispon&iacute;vel agora”", "Corrigido e validado em produção",
             "O cart&atilde;o passou a exibir o saldo real da cabine PIX com a origem “pix_cabin:camt.053”. Na valida&ccedil;&atilde;o em produ&ccedil;&atilde;o, ao acionar “Atualizar agora” a leitura trouxe o saldo da cabine na hora. Observa&ccedil;&atilde;o: a captura autom&aacute;tica peri&oacute;dica em produ&ccedil;&atilde;o estava exibindo uma leitura antiga; a atualiza&ccedil;&atilde;o da captura peri&oacute;dica em produ&ccedil;&atilde;o est&aacute; sendo acompanhada para que o valor apare&ccedil;a atualizado tamb&eacute;m sem a&ccedil;&atilde;o manual."),
            ("CA-002 &nbsp;Gr&aacute;fico “Hist&oacute;rico do saldo”", "Corrigido e validado em produção",
             "O gr&aacute;fico passou a trabalhar sobre o saldo real da cabine: a escala do eixo reflete a posi&ccedil;&atilde;o efetiva e cada captura registrada &eacute; plotada ao longo do tempo."),
            ("CA-003 &nbsp;Consolidado di&aacute;rio (Core)", "Corrigido e validado em produção",
             "O bloco passou a apresentar a tabela de movimentos por dia (data, quantidade, cr&eacute;dito, d&eacute;bito, l&iacute;quido e saldos) respeitando o per&iacute;odo filtrado."),
            ("CA-004 &nbsp;Status dos movimentos em portugu&ecirc;s", "Corrigido e validado em produção",
             "A coluna Status passou a exibir “Conclu&iacute;do”, “Liquidado”, “Rejeitado” e equivalentes, mantendo o valor t&eacute;cnico interno inalterado."),
            ("CA-005 &nbsp;R&oacute;tulo do Identificador BACEN", "Corrigido e validado em produção",
             "O identificador passou a usar r&oacute;tulos claros: “PIX (E2E)” para PIX e “TED (STR)” para TED, deixando expl&iacute;cito o trilho da transa&ccedil;&atilde;o."),
        ],
    },
    {
        "heading": "2. Tesouraria &middot; Relat&oacute;rio de Taxas",
        "img": ("PRD-CA-006-007-relatorio-taxas.png", "Produ&ccedil;&atilde;o: estado vazio “Nenhuma tarifa cobrada no per&iacute;odo” e gera&ccedil;&atilde;o de detalhe conclu&iacute;da (“Pronto” com “Baixar CSV”)."),
        "items": [
            ("CA-006 &nbsp;Estado vazio do grid", "Corrigido e validado em produção",
             "Sem tarifas no per&iacute;odo, o grid passou a exibir a mensagem “Nenhuma tarifa cobrada no per&iacute;odo”, no padr&atilde;o das demais telas."),
            ("CA-007 &nbsp;Gera&ccedil;&atilde;o do detalhe (CSV)", "Corrigido e validado em produção",
             "O pedido “Gerar detalhe” passou a fechar o ciclo: evolui para “Pronto” e disponibiliza o link “Baixar CSV”. Em produ&ccedil;&atilde;o h&aacute; pedidos j&aacute; conclu&iacute;dos com sucesso."),
        ],
    },
    {
        "heading": "3. Tesouraria &middot; Reconcilia&ccedil;&atilde;o Cont&aacute;bil PIX",
        "img": ("PRD-CA-008-010-recon-contabil-pix.png", "Produ&ccedil;&atilde;o: reconcilia&ccedil;&atilde;o do per&iacute;odo sem diverg&ecirc;ncias (todo movimento PIX com lan&ccedil;amento COSIF correto)."),
        "items": [
            ("CA-008 &nbsp;Coluna “Tipo” traduzida", "Corrigido e validado em produção",
             "A coluna Tipo e os chips de resumo passaram a exibir os r&oacute;tulos em portugu&ecirc;s: “E2E duplicado”, “Sem lan&ccedil;amento”, “Valor divergente”."),
            ("CA-009 &nbsp;Completude da diverg&ecirc;ncia “E2E duplicado”", "Corrigido e validado em produção",
             "As diverg&ecirc;ncias passaram a trazer o valor esperado e o detalhe explicativo. Em produ&ccedil;&atilde;o, no per&iacute;odo verificado, a reconcilia&ccedil;&atilde;o est&aacute; sem diverg&ecirc;ncias, com todos os movimentos conciliados."),
            ("CA-010 &nbsp;Coluna de Data no grid", "Corrigido e validado em produção",
             "O grid de diverg&ecirc;ncias passou a ter a coluna “Data”, orden&aacute;vel, para identificar a que dia cada diverg&ecirc;ncia pertence."),
        ],
    },
    {
        "heading": "4. Tesouraria &middot; Reconcilia&ccedil;&atilde;o Tesouraria",
        "img": ("PRD-CA-011-012-recon-tesouraria.png", "Produ&ccedil;&atilde;o: Conta PI lida da cabine (fonte camt.053) e r&oacute;tulo “Captura nº”."),
        "items": [
            ("CA-011 &nbsp;Leitura da Conta PI e reconcilia&ccedil;&atilde;o", "Corrigido e validado em produção",
             "A tela passou a ler o saldo da Conta PI da cabine PIX e a executar a reconcilia&ccedil;&atilde;o entre o saldo real e o raz&atilde;o de clientes do Core."),
            ("CA-012 &nbsp;R&oacute;tulo do n&uacute;mero de captura", "Corrigido e validado em produção",
             "O r&oacute;tulo t&eacute;cnico foi substitu&iacute;do por “Captura nº”, com explica&ccedil;&atilde;o do que representa. O mesmo termo foi padronizado nas demais telas."),
        ],
    },
    {
        "heading": "5. Tesouraria &middot; Disponibilidades",
        "img": ("PRD-CA-013-disponibilidades.png", "Produ&ccedil;&atilde;o: orienta&ccedil;&atilde;o de estado quando n&atilde;o h&aacute; disponibilidade cadastrada."),
        "items": [
            ("CA-013 &nbsp;Cabine PIX nas Disponibilidades", "Corrigido, item complementar em avaliação",
             "A tela recebeu a orienta&ccedil;&atilde;o de estado adequada. O saldo da cabine PIX j&aacute; pode ser conferido de forma dedicada nas telas Liquida&ccedil;&atilde;o e Reconcilia&ccedil;&atilde;o Tesouraria (CA-001 e CA-011). A exibi&ccedil;&atilde;o de um cart&atilde;o pr&oacute;prio da cabine nesta tela est&aacute; em avalia&ccedil;&atilde;o, para n&atilde;o duplicar a mesma informa&ccedil;&atilde;o."),
        ],
    },
    {
        "heading": "6. Tesouraria &middot; Cr&eacute;ditos SPB Recebidos",
        "img": ("PRD-CA-014-creditos-spb.png", "Produ&ccedil;&atilde;o: tela abre listando todos os cr&eacute;ditos recebidos."),
        "items": [
            ("CA-014 &nbsp;Filtro padr&atilde;o de status", "Corrigido e validado em produção",
             "A tela passou a abrir com o filtro em “Todos”, exibindo os cr&eacute;ditos recebidos do per&iacute;odo, sem abrir vazia."),
        ],
    },
    {
        "heading": "7. Relat&oacute;rios &middot; Movimenta&ccedil;&atilde;o CC (extrato do cliente)",
        "img": ("PRD-CA-015-018-movimentacao-cc.png", "Produ&ccedil;&atilde;o: categoria em portugu&ecirc;s, d&eacute;bito em vermelho e cr&eacute;dito em verde, cinco cart&otilde;es em uma linha e exporta&ccedil;&atilde;o PDF ativa."),
        "items": [
            ("CA-015 &nbsp;Coluna “Categoria” traduzida", "Corrigido e validado em produção",
             "A coluna Categoria passou a exibir “Dep&oacute;sito”, “Transfer&ecirc;ncia” e demais categorias em portugu&ecirc;s."),
            ("CA-016 &nbsp;Cores em D&eacute;bito, Cr&eacute;dito e Saldo", "Corrigido e validado em produção",
             "As colunas passaram a seguir a conven&ccedil;&atilde;o cont&aacute;bil: d&eacute;bito em vermelho e cr&eacute;dito em verde."),
            ("CA-017 &nbsp;Alinhamento dos cart&otilde;es de resumo", "Corrigido e validado em produção",
             "Os cinco cart&otilde;es de resumo passaram a caber em uma &uacute;nica linha, sem quebra."),
            ("CA-018 &nbsp;Exporta&ccedil;&atilde;o em PDF", "Corrigido e validado em produção",
             "O bot&atilde;o PDF passou a gerar e baixar o extrato. Na valida&ccedil;&atilde;o em produ&ccedil;&atilde;o o arquivo foi gerado (comprovante anexo)."),
        ],
    },
    {
        "heading": "8. Relat&oacute;rios &middot; Saldo Di&aacute;rio de Conta Corrente",
        "img": ("PRD-CA-019-021-saldo-diario-cc.png", "Produ&ccedil;&atilde;o: card “Contas com saldo” com o total correto e coluna “C&oacute;digo de Conta” preenchida."),
        "items": [
            ("CA-019 &nbsp;Card “Contas com saldo”", "Corrigido e validado em produção",
             "O card passou a exibir a quantidade correta de contas com saldo, no lugar do texto “undefined”."),
            ("CA-020 &nbsp;Coluna “C&oacute;digo de Conta”", "Corrigido e validado em produção",
             "A coluna passou a trazer o c&oacute;digo de cada conta, permitindo distinguir contas do mesmo titular."),
            ("CA-021 &nbsp;Exporta&ccedil;&atilde;o em PDF", "Corrigido e validado em produção",
             "O bot&atilde;o PDF passou a gerar e baixar o relat&oacute;rio. Na valida&ccedil;&atilde;o em produ&ccedil;&atilde;o o arquivo foi gerado (comprovante anexo)."),
        ],
    },
    {
        "heading": "9. Relat&oacute;rios &middot; Cheque Especial Consolidado",
        "img": ("PRD-CA-022-cheque-especial-consolidado.png", "Produ&ccedil;&atilde;o: cinco cart&otilde;es de resumo em uma linha, incluindo IOF do per&iacute;odo."),
        "items": [
            ("CA-022 &nbsp;Alinhamento dos cart&otilde;es de resumo", "Corrigido e validado em produção",
             "Os cinco cart&otilde;es passaram a caber em uma &uacute;nica linha, corrigido no mesmo componente compartilhado do CA-017."),
        ],
    },
    {
        "heading": "10. Cadastro &middot; Cliente &middot; Contas &middot; Extrato",
        "img": ("PRD-CA-023-extrato-por-conta-carregado.png", "Produ&ccedil;&atilde;o: extrato aberto j&aacute; carregado na conta selecionada, sem nova busca."),
        "items": [
            ("CA-023 &nbsp;Extrato a partir da conta do cliente", "Corrigido e validado em produção",
             "Ao acionar “Extrato” na conta do cliente, a tela passou a abrir j&aacute; carregada para aquela conta, sem exigir que o operador digite a conta novamente."),
        ],
    },
    {
        "heading": "11. Cadastro &middot; Gest&atilde;o de Clientes",
        "img": ("PRD-CA-024-clientes-paginacao-p4.png", "Produ&ccedil;&atilde;o: pagina&ccedil;&atilde;o funcionando, a p&aacute;gina selecionada permanece ativa."),
        "items": [
            ("CA-024 &nbsp;Pagina&ccedil;&atilde;o da listagem", "Corrigido e validado em produção",
             "A pagina&ccedil;&atilde;o passou a preservar a p&aacute;gina selecionada. Na valida&ccedil;&atilde;o em produ&ccedil;&atilde;o, ao navegar para outra p&aacute;gina a sele&ccedil;&atilde;o permaneceu na p&aacute;gina escolhida, sem retornar &agrave; primeira."),
        ],
    },
    {
        "heading": "12. Tesouraria &middot; Caixa Institucional",
        "img": ("PRD-CA-025-menu-tesouraria-sem-caixa-institucional.png", "Produ&ccedil;&atilde;o: menu Tesouraria sem o item “Caixa Institucional”."),
        "items": [
            ("CA-025 &nbsp;Item de menu n&atilde;o utilizado", "Corrigido e validado em produção",
             "O item “Caixa Institucional” foi removido do menu, evitando que o operador acesse uma tela sem funcionalidade."),
        ],
    },
    {
        "heading": "13. Dashboard &middot; Tesouraria &amp; Liquidez",
        "img": ("PRD-CA-026-dashboard-tesouraria-liquidez.png", "Produ&ccedil;&atilde;o: card Tesouraria &amp; Liquidez com Disponibilidades positivas e &iacute;ndice de liquidez coerente."),
        "items": [
            ("CA-026 &nbsp;Card “Tesouraria &amp; Liquidez”", "Corrigido e validado em produção",
             "O card passou a apresentar valores coerentes: as Disponibilidades voltaram a exibir valor positivo e plaus&iacute;vel e o &iacute;ndice de liquidez imediata foi recalculado. O valor negativo de grande magnitude n&atilde;o ocorre mais e o layout foi ajustado."),
        ],
    },
    {
        "heading": "14. STA Admin (Integrador STA)",
        "img": ("STA-PRD-painel-ativo-funcional.png", "Produ&ccedil;&atilde;o: painel do STA Admin operando, com sa&uacute;de do sistema, m&eacute;tricas e processamento de arquivos regulat&oacute;rios."),
        "items": [
            ("STA-001 e STA-002 &nbsp;Gest&atilde;o de acesso", "Ativo e funcional em produção",
             "O STA Admin est&aacute; ativo e funcional em produ&ccedil;&atilde;o: o painel apresenta a sa&uacute;de do sistema, as m&eacute;tricas e o processamento cont&iacute;nuo dos arquivos regulat&oacute;rios com o BACEN. O acesso administrativo est&aacute; operacional. A gest&atilde;o de m&uacute;ltiplos usu&aacute;rios nominais e a auto-edi&ccedil;&atilde;o de perfil s&atilde;o evolu&ccedil;&otilde;es de controle de acesso; podemos tratar o escopo e as prioridades desses recursos conforme a necessidade da Monetarie."),
        ],
    },
]

INTRO = [
    "Este documento comprova, item a item, o tratamento dado ao Relat&oacute;rio de Bugs do ecossistema Monetarie recebido em 17 de julho de 2026, com 28 registros (26 no CoreAdmin e 2 no STA Admin).",
    "As evid&ecirc;ncias s&atilde;o capturas vivas do ambiente de PRODU&Ccedil;&Atilde;O, obtidas em 20 de julho de 2026 em sess&atilde;o nova, sem cache. Cada item traz o veredito atual e a imagem da tela correspondente.",
    "Resumo do resultado: os 26 itens do CoreAdmin est&atilde;o corrigidos e validados em produ&ccedil;&atilde;o (o CA-013 est&aacute; atendido no essencial, com um complemento visual em avalia&ccedil;&atilde;o) e o STA Admin est&aacute; ativo e funcional em produ&ccedil;&atilde;o.",
    "Observa&ccedil;&atilde;o: para que a compara&ccedil;&atilde;o seja fiel, recomendamos revalidar em uma sess&atilde;o nova do navegador (ou com atualiza&ccedil;&atilde;o for&ccedil;ada), pois o carregamento de vers&otilde;es anteriores em cache pode ainda apresentar o comportamento antigo.",
]

CLOSING = [
    "Permanecemos &agrave; disposi&ccedil;&atilde;o para revalidar cada tela em conjunto com a equipe da Monetarie e para tratar a evolu&ccedil;&atilde;o do controle de acesso do STA Admin conforme a prioridade da institui&ccedil;&atilde;o.",
]


def build(outdir):
    ss = ss_styles()
    out = os.path.join(outdir, "Monetarie-Evidencias-Ajustes-Relatorio-Bugs-PRD-2026-07-20.pdf")
    doc = SimpleDocTemplate(
        out, pagesize=A4, leftMargin=20 * mm, rightMargin=20 * mm,
        topMargin=16 * mm, bottomMargin=16 * mm,
        title="Monetarie - Evidencias dos Ajustes do Relatorio de Bugs (Producao)",
        author="Equipe tecnica Vulci",
    )
    st = []
    st.append(Paragraph("Evid&ecirc;ncias dos Ajustes do Relat&oacute;rio de Bugs", ss["Titulo"]))
    st.append(Paragraph("<font size=11 color='#555555'>Valida&ccedil;&atilde;o em ambiente de produ&ccedil;&atilde;o</font>", ss["Meta"]))
    st.append(HRFlowable(width="100%", thickness=2.2, color=GOLD, spaceAfter=8))
    st.append(Paragraph("<b>Para:</b> Monetarie Sociedade de Cr&eacute;dito Direto S.A.", ss["Meta"]))
    st.append(Paragraph("<b>De:</b> Vulci (equipe t&eacute;cnica)", ss["Meta"]))
    st.append(Paragraph("<b>Data:</b> 20 de julho de 2026", ss["Meta"]))
    st.append(Paragraph("<b>Refer&ecirc;ncia:</b> Relat&oacute;rio de Bugs do ecossistema Monetarie, de 17/07/2026 (28 itens)", ss["Meta"]))
    st.append(Spacer(1, 8))
    for p in INTRO:
        st.append(Paragraph(p, ss["Corpo"]))
    for sec in SECOES:
        st.append(Paragraph(sec["heading"], ss["H1x"]))
        for label, status, texto in sec["items"]:
            st.append(KeepTogether([
                Paragraph(f"{label} &nbsp;&middot;&nbsp; {status_html(status)}", ss["ItemTit"]),
                Paragraph(texto, ss["Corpo"]),
            ]))
        if sec.get("img"):
            name, leg = sec["img"]
            p = ev(name)
            if os.path.exists(p):
                st.append(img_flowable(p))
                st.append(Paragraph(leg, ss["Legenda"]))
    st.append(Spacer(1, 10))
    for p in CLOSING:
        st.append(Paragraph(p, ss["Corpo"]))
    st.append(Spacer(1, 8))
    st.append(Paragraph("Atenciosamente,", ss["Corpo"]))
    st.append(Paragraph("<b>Equipe t&eacute;cnica Vulci</b>", ss["Corpo"]))
    doc.build(st)
    for t in _tmp:
        try:
            os.remove(t)
        except OSError:
            pass
    return out


if __name__ == "__main__":
    import sys
    outdir = sys.argv[1] if len(sys.argv) > 1 else os.path.expanduser("~/Desktop")
    print(build(outdir))
