"""
Project Together — powered by AI: PASSO 8 — Monitorar e Status Report.

O quadro já sabe onde você está: o script LÊ os cartões (planejado x realizado, o que
está em execução, o que foi entregue) e a IA escreve o Status Report — para quem
DECIDE, não para quem executa: veredito primeiro (no rumo / atenção / crítico), número
na frente da opinião, e só o que muda uma decisão.

O Status Report vira um cartão datado na lista Concluído (a sua trilha de relatórios) —
e o texto também fica salvo em _saida/status-report-<data>.txt.

O RITMO (modo CHAT): prompt do Passo 8 (já traz a FOTO do seu quadro) → IA → resposta
([P8]) na Caixa de entrada → rode este passo.
"""
import os
from datetime import date

import entradas
import passos
import quadro
import verificar_okrs
import verificar_projeto
from runner import ok, step, warn
from idioma import T, Tf

N = 8
c, ids, abordagem = passos.abrir(N)

# A SAUDE DO PROJETO ANTES do relatorio, e de proposito: monitorar prazo e custo sem
# olhar o valor prometido e' reportar movimento, nao resultado. E' o MESMO codigo que o
# aluno roda sozinho pelo menu (tecla P, verificar_projeto) — mesmo python para as duas
# necessidades. O diagnostico ja traz o OKR dentro (diag["okr"]), sem ler o quadro 2x.
diag = verificar_projeto.diagnostico(ids)
av = diag["okr"]
print()
print(verificar_projeto.relatorio(diag))
print()

bloco = passos.ler_bloco(ids, N, T("nenhum Status Report"))

secs = entradas.secoes(bloco, ["RESUMO", "ALERTAS", "DECISOES", "DECISÕES",
                               "INCREMENTO", "NAO_CONCLUIDO", "NÃO_CONCLUÍDO",
                               "NAO CONCLUIDO", "META", "FEEDBACK"])
resumo = (secs.get("resumo", "") or "").strip()
alertas = entradas.itens(secs.get("alertas", ""))
decisoes = entradas.itens(secs.get("decisoes", "") or secs.get("decisões", ""))
if not resumo and not alertas and not decisoes:
    raise SystemExit(T("Não achei RESUMO/ALERTAS/DECISÕES no bloco [P8]. Confira o formato "
                     "e cole de novo."))

hoje = date.today().isoformat()

# ── SPRINT REVIEW (só no ÁGIL) — o veredito da Definição de Pronto, item a item ──
# A Review não é uma apresentação: é a inspeção do incremento. E o veredito só tem duas
# respostas — item que atende a TODA a DoD é Incremento; item que não atende volta ao
# Product Backlog para ser repriorizado. Não existe 80% pronto: é essa transparência que
# a DoD existe para criar. Quem move os cartões é o script, a partir do que VOCÊ colou.
n_pronto = n_volta = 0
if abordagem == "AGIL":
    from env import get_int
    from pa_client import list_cards, move_card
    sprint = max(1, get_int(c, "CURRENT_SPRINT", 1))
    incremento = entradas.itens(secs.get("incremento", ""))
    nao_concl = entradas.itens(secs.get("nao_concluido", "") or secs.get("não_concluído", "")
                               or secs.get("nao concluido", ""))
    # Mesma armadilha do ENCERRANDO no Passo 10: se a IA responder a Meta na MESMA linha
    # do rótulo ("META: Parcialmente: 5 de 16 pontos..."), a linha passa dos 60 caracteres
    # e o entradas.secoes não a reconhece como cabeçalho. O regex pega os dois formatos.
    meta_txt = (secs.get("meta", "") or "").strip()
    if not meta_txt:
        import re as _re
        _m = _re.search(r"(?im)^\s*META\s*[:：]\s*(.+)$", bloco)
        meta_txt = _m.group(1).strip() if _m else ""
    feedback = entradas.itens(secs.get("feedback", ""))

    na_sprint = quadro.itens_de_trabalho(ids["EXECUCAO"])
    por_cod = quadro.cartoes_por_codigo(na_sprint)
    por_nome = {entradas._sem_acento(cd.get("titulo", "")): cd for cd in na_sprint}

    def _achar(nome):
        return (por_cod.get(quadro.codigo_do_item(nome))
                or por_nome.get(entradas._sem_acento(nome)))

    def _mover(lista_itens, destino, marcar_concluido):
        movidos, nao_achados = 0, []
        for it in lista_itens:
            nome = (it.get("_", "") or "").strip()
            cd = _achar(nome)
            if not cd:
                nao_achados.append(nome)
                continue
            try:
                move_card(cd["id"], ids[destino])
                if marcar_concluido:
                    from pa_client import update_card
                    update_card(cd["id"], concluido=True)
                movidos += 1
            except Exception as e:
                warn(Tf('não consegui mover "{0}": {1}', nome[:34], e))
        return movidos, nao_achados

    n_pronto, faltou_p = _mover(incremento, "PRONTO", True)
    n_volta, faltou_v = _mover(nao_concl, "ESCOPO", False)
    if n_pronto or n_volta:
        ok(Tf("Sprint Review da Sprint {0}: {1} item(ns) atingiram a Definição de Pronto e "
              "foram para o Incremento · {2} voltaram ao Product Backlog para serem "
              "repriorizados.", sprint, n_pronto, n_volta))
    for nome in (faltou_p + faltou_v):
        warn(Tf('"{0}" não está no Sprint Backlog — não movi. Use o código (B1, B2…) ou o '
                'título exato do cartão.', nome[:44]))

    # o registro da Review, com a Meta e o feedback que muda o backlog
    linhas = [Tf("Sprint Review — Sprint {0} · {1}", sprint, hoje), ""]
    if meta_txt:
        linhas += [T("A META DA SPRINT FOI ATINGIDA?"), meta_txt, ""]
    linhas += [Tf("INCREMENTO ({0} item(ns) pela Definição de Pronto):", n_pronto)]
    linhas += [f"  ✅ {(it.get('_','') or '')}" for it in incremento] or [T("  (nenhum)")]
    if nao_concl:
        linhas += ["", T("NÃO CONCLUÍDO (volta ao Product Backlog):")]
        for it in nao_concl:
            linhas.append(f"  ↩️ {it.get('_','')}")
            if it.get("faltou"):
                linhas.append(Tf("       faltou: {0}", it['faltou']))
    if feedback:
        linhas += ["", T("FEEDBACK DAS PARTES INTERESSADAS:")]
        for f in feedback:
            linhas.append(f"  • {f.get('_','')}")
            if f.get("muda no backlog"):
                linhas.append(Tf("       muda no backlog: {0}", f['muda no backlog']))
    passos.escrever_cartoes(ids, "CONCLUIDO", [(
        Tf("🔎 Sprint Review — Sprint {0} · {1}", sprint, hoje),
        "\n".join(linhas), None)], log=step)
    if feedback:
        ok(Tf("{0} ponto(s) de feedback registrados. A Review existe para ADAPTAR o backlog: "
              "leve cada um ao Passo 9 (repriorização e refinamento).", len(feedback)))

corpo = [Tf("📊 STATUS REPORT — {0}", hoje), "",
         verificar_projeto.resumo(diag), verificar_okrs.resumo(av), ""]
if resumo:
    corpo += [T("RESUMO:"), resumo, ""]
if alertas:
    corpo.append(T("ALERTAS:"))
    for a in alertas:
        corpo.append(f"• {a.get('_','')}")
        if a.get("evidencia"):
            corpo.append(Tf("    evidência: {0}", a['evidencia']))
        if a.get("impacto se nao agir"):
            corpo.append(Tf("    impacto se não agir: {0}", a['impacto se nao agir']))
    corpo.append("")
if decisoes:
    corpo.append(T("DECISÕES QUE PRECISO:"))
    for d in decisoes:
        corpo.append(f"• {d.get('_','')}")
        det = " · ".join(f"{passos.rotulo_de_campo(k)}: {d[k]}"
                         for k in ("de quem", "ate", "opcoes") if d.get(k))
        if det:
            corpo.append(f"    {det}")
texto = "\n".join(corpo).strip()

# 1) cartão datado na lista Concluído (a trilha de relatórios)
passos.escrever_cartoes(ids, "CONCLUIDO",
                        [(f"📊 Status Report — {hoje}", texto, None)], log=step)
ok(Tf("Status Report de {0} no quadro (lista Concluído): {1} alerta(s), {2} decisão(ões).", hoje, len(alertas), len(decisoes)))

# 2) cópia em _saida (útil para enviar por e-mail a quem decide)
saida = os.path.join(os.path.dirname(os.path.abspath(__file__)), "_saida")
os.makedirs(saida, exist_ok=True)
caminho = os.path.join(saida, f"status-report-{hoje}.txt")
with open(caminho, "w", encoding="utf-8") as f:
    f.write(texto + "\n")
step(Tf("cópia salva em _saida/status-report-{0}.txt", hoje))

# Artefato do Passo 8: o Status Report estruturado (.docx), lido do quadro.
try:
    import artefatos
    cam, _av = artefatos.gerar_status_report(ids, abordagem=abordagem, log=step)
    if cam:
        ok(T("Status Report gerado em _saida/documentos/ (.docx) — o retrato estruturado do "
           "quadro (veredito, EAP, atividades por status e pontos de atenção)."))
except Exception as e:
    warn(Tf("não consegui gerar o Status Report (.docx) agora: {0}", e))

if abordagem == "AGIL":
    resumo = Tf("Sprint Review da Sprint {0}: {1} no Incremento, {2} de volta ao backlog "
                "· Status Report de {3}.", sprint, n_pronto, n_volta, hoje)
    conclusao = Tf("Passo 8 concluído — a Sprint Review da Sprint {0} está no quadro: o "
                   "que ficou pronto virou Incremento, o que não ficou voltou ao Product "
                   "Backlog. Agora feche a Sprint no Passo 10 (Retrospectiva) — é ele que "
                   "avança o contador e te devolve ao Passo 5, na Sprint seguinte.", sprint)
else:
    resumo = Tf("Status Report de {0}: {1} alerta(s), {2} decisão(ões).",
                hoje, len(alertas), len(decisoes))
    conclusao = T("Passo 8 concluído — o Status Report está no quadro e em _saida. "
                  "Monitorar é rotina: rode este passo sempre que precisar reportar.")

passos.finalizar(N, ids, resumo=resumo, mensagem_conclusao=conclusao)
