# -*- coding: utf-8 -*-
"""
Agile Together — CONSOLIDAR as respostas de DUAS IAs (o mesmo gesto do Project Together).

POR QUE ISTO EXISTE (Eduardo, 31/08/2026, rodando o passo 2 no quadro 358)
    "Quando fui rodar a opcao 2 do menu — Meta do produto — achei que geraria valor
     ter uma opcao para consolidacao das respostas de duas IAs da mesma forma que
     temos no Project Together."

  Ele esta' certo, e no Agile o problema e' ate' mais agudo: a Caixa de entrada e'
  lida por `entradas.secoes`, que fecha uma secao quando o cabecalho seguinte aparece.
  Colar DUAS respostas uma embaixo da outra nao da' erro — a segunda simplesmente
  SOBRESCREVE a primeira, em silencio. O aluno acha que comparou duas IAs e o que
  entrou no quadro foi a ultima.

  Aqui as duas sao lidas SEPARADAS, e o que sai e' um prompt pronto que faz a sua IA
  comparar as duas e propor UMA. A regra de ouro nao muda: a IA propoe, VOCE decide —
  e o que mais importa nao e' a resposta pronta, e' ver ONDE elas divergem.

COMO USAR (voce nao edita arquivo nenhum)
  1. Rode um passo (ex.: 2. Meta do Produto) e pegue o prompt pronto.
  2. Cole o MESMO prompt em DUAS IAs diferentes (ou na mesma, duas vezes).
  3. Cole AS DUAS respostas no cartao "0. Caixa de entrada", uma embaixo da outra —
     sem apagar os cabecalhos (META DO PRODUTO:, HISTORIAS:, ...). E' o cabecalho
     REPETIDO que diz "aqui comeca a segunda resposta".
  4. Escolha a tecla C no menu. Ela monta o prompt de consolidacao com as duas
     respostas dentro e o poe na sua area de transferencia.
  5. Cole esse prompt em qualquer IA (pode ser uma terceira, como voto de desempate).
  6. Copie a resposta INTEIRA, cole na Caixa de entrada NO LUGAR das duas de antes e
     rode o passo normal — ele le a versao consolidada e segue.

O QUE ELE NAO FAZ
  Nao chama IA nenhuma por conta propria — o curso e' agnostico de IA: quem compara e'
  a SUA IA, quem decide e' voce. E nao mexe no seu backlog, nas suas Sprints nem nos
  seus eventos: a unica escrita que ele pode fazer no quadro e' a que TODO passo faz,
  garantir que o cartao da Caixa de entrada exista e esteja no lugar certo.
"""
import os
import re
import sys
from idioma import T, Tf, escolher

try:
    sys.stdout.reconfigure(encoding="utf-8", errors="replace")
except Exception:
    pass

import caixa
import entradas
from runner import header, ok, done, warn, copiar

AQUI = os.path.dirname(os.path.abspath(__file__))
_SAIDA = os.path.join(AQUI, "_saida")

# ─────────────────────────────────────────────────────────────────────────────
# Os cabecalhos que o curso pede a IA — a lista fechada contra a qual procuramos
# repeticao. Sao os mesmos rotulos que cada passo passa a `caixa.ler` (por isso
# esta tabela cita o passo: se um passo ganhar um rotulo novo, ele entra aqui).
# Sem lista fechada, qualquer linha terminada em ":" viraria "cabecalho" e uma
# resposta bem escrita passaria por duas.
# ─────────────────────────────────────────────────────────────────────────────
ROTULOS = [
    "META DO PRODUTO", "HISTORIAS",            # 2. Meta do Produto + Product Backlog
    "REFINAMENTO",                             # 3. Refinar o backlog
    "RENOMEAR", "ADICIONAR",                   # 4. Revisar o backlog
    "TAREFAS",                                 # 5. Decompor um item em tarefas
    "META DA SPRINT", "SELECIONADOS",          # 6. Sprint Planning
    "FOCO DE HOJE", "NOVAS TAREFAS", "IMPEDIMENTO",   # 7. Daily Scrum
    "RESUMO", "FEEDBACK",                      # 8. Sprint Review
    "DEU CERTO", "PROBLEMAS", "ACOES",         # 9. Sprint Retrospective
]

_MAPA = {entradas._sem_acento(r): r for r in ROTULOS}


def _cabecalho_da_linha(linha):
    """O rotulo canonico que esta linha abre, ou None.

    UMA DIFERENCA PROPOSITAL em relacao a `entradas.secoes`: la' o cabecalho so' vale
    se a linha tiver menos de 60 caracteres, porque la' qualquer palavra seguida de
    ":" e' candidata e o limite e' o que impede uma frase de virar secao. Aqui a lista
    de rotulos e' FECHADA (ROTULOS) — o que vem antes do ":" tem de ser exatamente um
    deles — entao o limite so' faria mal. E faria: uma "META DO PRODUTO: <frase longa>"
    bem escrita passa de 60 com folga, e as duas metas do Eduardo (quadro 358,
    31/08/2026) passavam. E' o mesmo motivo pelo qual `caixa.valor()` existe."""
    if ":" not in linha:
        return None
    chave = entradas._sem_acento(re.sub(r"[:：].*$", "", linha))
    return _MAPA.get(chave)


def respostas(bruto):
    """As respostas SEPARADAS que estao coladas na Caixa de entrada.

    Cada uma vira {rotulo: texto}. O corte e' o cabecalho REPETIDO: quando aparece
    um rotulo que a resposta corrente ja' tem, e' porque comecou a proxima resposta.
    E' o unico sinal confiavel — a IA nao escreve "sou a resposta 2", e pedir ao
    aluno para marcar isso seria trabalho que a maquina pode fazer."""
    atual, todas, rotulo, buf = {}, [], None, []

    def _fechar():
        if rotulo is not None:
            atual[rotulo] = "\n".join(buf).strip()

    for linha in entradas._linhas(bruto):
        novo = _cabecalho_da_linha(linha)
        if not novo:
            buf.append(linha)
            continue
        _fechar()
        if novo in atual:                    # rotulo repetido = comecou outra resposta
            todas.append(atual)
            atual = {}
        rotulo, buf = novo, []
        resto = linha.split(":", 1)[1].strip()
        if resto:
            buf.append(resto)
    _fechar()
    if atual:
        todas.append(atual)
    return todas


def contestados(todas):
    """{rotulo: [variantes]} — so' dos rotulos respondidos por MAIS DE UMA resposta.

    Um rotulo que so' uma delas trouxe nao e' divergencia: e' um bloco que a outra
    IA esqueceu. Ele entra no prompt assim mesmo (ver `montar_prompt`), mas nao e'
    o que dispara a consolidacao."""
    out = {}
    for r in ROTULOS:
        variantes = [a[r] for a in todas if a.get(r, "").strip()]
        if len(variantes) >= 2:
            out[r] = variantes
    return out


# ── O prompt de consolidacao (o "juiz") ──────────────────────────────────────
# Ele pede a saida JA' no formato que a Caixa de entrada le: a comparacao primeiro
# (texto livre, que o parser ignora por nao ter cabecalho conhecido) e depois os
# blocos com os MESMOS cabecalhos em MAIUSCULAS. Assim a resposta consolidada volta
# para a caixa e o passo normal a le sem nenhum passo extra.
_CABECALHO = """CONSOLIDAR AS RESPOSTAS DE DUAS IAs

Recebi, para a mesma pergunta do meu projeto, MAIS DE UMA resposta — cada uma de uma
IA diferente. Quero UMA resposta consolidada: a melhor de cada, sem inventar nada que
nenhuma delas disse.

A regra de ouro do meu curso e' "a IA propoe, eu decido". Por isso o que mais me importa
NAO e' so' a resposta pronta — e' enxergar ONDE as IAs divergem, porque e' ai' que eu
preciso pensar e decidir.

Contexto: e' um ciclo de Scrum de 3 Sprints. O backlog inteiro e' ordenado contra a Meta
do Produto; item que nao ajuda a chegar nela nao e' prioridade.

Devolva DUAS coisas, nesta ordem:

1) COMPARACAO (texto livre e curto — NAO use os cabecalhos em MAIUSCULAS aqui):
   - Concordam: o que as duas dizem igual (posso confiar).
   - Divergem: onde se contradizem — e qual voce recomenda, e por que.
   - Falta nas duas: o que nenhuma trouxe e deveria estar la'.

2) RESPOSTA CONSOLIDADA: comece numa linha NOVA com o cabecalho em MAIUSCULAS (o MESMO
   das respostas abaixo, ex.: HISTORIAS:) e escreva a versao final EXATAMENTE no mesmo
   formato — mesmos campos, mesma pontuacao, um item por linha comecando com "•".
   Um unico bloco por cabecalho, e sem repetir item que diga a mesma coisa com outras
   palavras: onde as duas propuseram o mesmo, escolha a formulacao mais clara e some
   os itens que so' uma trouxe, se eles servirem a Meta do Produto.

   ATENCAO AO TAMANHO — consolidar NAO e' somar:
   - Bloco que e' uma LISTA (HISTORIAS, TAREFAS, SELECIONADOS, ACOES...): pode crescer,
     porque a uniao sem duplicatas e' o resultado certo.
   - Bloco que e' UMA FRASE (META DO PRODUTO, META DA SPRINT, FOCO DE HOJE): tem de
     voltar como UMA FRASE. ESCOLHA a melhor ou reescreva do zero — nunca emende as
     duas com virgulas. A versao final nao pode ficar mais longa que a MAIOR das duas,
     e ela vira o titulo de um cartao: 250 caracteres e' o teto absoluto, e uma meta
     que se decora tem bem menos que isso.

Escreva TODA a comparacao primeiro e, so' depois, os blocos consolidados:
e' nesse formato que o meu curso le a resposta.

════════════════════════════════════════════════════════════
"""

_CABECALHO_EN = """CONSOLIDATE THE ANSWERS OF TWO AIs

For the same question about my project I received MORE THAN ONE answer — each from a
different AI. I want ONE consolidated answer: the best of each, without inventing
anything neither of them said.

The golden rule of my course is "the AI proposes, I decide". So what matters most to me
is NOT just the finished answer — it is seeing WHERE the AIs disagree, because that is
where I have to think and decide.

Context: this is a Scrum cycle of 3 Sprints. The whole backlog is ordered against the
Product Goal; an item that does not help reach it is not a priority.

Give me back TWO things, in this order:

1) COMPARISON (free, short text — do NOT use the CAPITALISED headings here):
   - They agree: what both say the same way (I can trust it).
   - They differ: where they contradict each other — and which one you recommend, and why.
   - Missing in both: what neither brought and should have been there.

2) CONSOLIDATED ANSWER: start on a NEW line with the heading in CAPITALS (the SAME one
   as in the answers below, e.g. STORIES:) and write the final version in EXACTLY the
   same format — same fields, same punctuation, one item per line starting with "•".
   One single block per heading, and no repeating an item that says the same thing in
   other words: where both proposed the same, choose the clearest wording and add the
   items only one of them brought, if they serve the Product Goal.

   MIND THE LENGTH — consolidating is NOT adding up:
   - A block that is a LIST (STORIES, TASKS, SELECTED, ACTIONS...): it may grow,
     because the union without duplicates is the right result.
   - A block that is ONE SENTENCE (PRODUCT GOAL, SPRINT GOAL, FOCUS TODAY): it has to
     come back as ONE SENTENCE. CHOOSE the better one or rewrite it from scratch — never
     splice the two with commas. The final version cannot be longer than the LONGER of
     the two, and it becomes the title of a card: 250 characters is the hard ceiling,
     and a goal you can memorise is far shorter than that.

Write ALL the comparison first and only then the consolidated blocks:
that is the format my course reads the answer in.
"""

# O idioma do pacote (tabela paralela — e' um prompt, nao uma frase).
_CABECALHO = escolher(_CABECALHO, _CABECALHO_EN)


_REGUA = "════════════════════════════════════════════════════════════"


def _bloco(rotulo, variantes):
    linhas = [f"{rotulo} — {len(variantes)} respostas para comparar:", ""]
    for i, v in enumerate(variantes):
        linhas.append(Tf("--- Resposta {0} ---", chr(65 + i)))
        linhas.append((v or "").strip())
        linhas.append("")
    return "\n".join(linhas)


def montar_prompt(disputados, todas):
    """O prompt inteiro. Alem dos rotulos disputados, leva os que UMA SO' das IAs
    trouxe — marcados como tal: eles fazem parte da mesma resposta, e escondê-los
    faria a IA consolidar um bloco pela metade."""
    partes = [_CABECALHO]
    for rotulo, variantes in disputados.items():
        partes.append(_bloco(rotulo, variantes))
        partes.append(_REGUA)
    sozinhos = [(r, a[r]) for r in ROTULOS for a in todas
                if a.get(r, "").strip() and r not in disputados]
    for rotulo, texto in sozinhos:
        partes.append(Tf("{0} — so' UMA das respostas trouxe este bloco (mantenha-o na versao "
                         "final):\n \n {1}\n", rotulo, texto.strip()))
        partes.append(_REGUA)
    return "\n".join(partes).strip() + "\n"


def _salvar(prompt):
    os.makedirs(_SAIDA, exist_ok=True)
    caminho = os.path.join(_SAIDA, "prompt-consolidar.txt")
    with open(caminho, "w", encoding="utf-8") as f:
        f.write(prompt)
    return caminho


def _como_colar_duas():
    print(T('  Como colar duas respostas no cartao "0. Caixa de entrada":'))
    print(T("    1. rode um passo (ex.: 2. Meta do Produto) e pegue o prompt;"))
    print(T("    2. cole o MESMO prompt em duas IAs diferentes;"))
    print(T("    3. cole as DUAS respostas no cartao, uma embaixo da outra, SEM apagar"))
    print(T("       os cabecalhos (META DO PRODUTO:, HISTORIAS: ...);"))
    print(T("    4. escolha a tecla C de novo."))


def main():
    header(T("Consolidar as respostas de duas IAs"))
    bruto = caixa.texto()

    if not bruto:
        done(T("A sua Caixa de entrada esta' vazia."))
        print(T("  Nao ha' o que comparar ainda.\n"))
        _como_colar_duas()
        return

    todas = respostas(bruto)
    disputados = contestados(todas)

    if not disputados:
        rotulos = sorted({r for a in todas for r in a if a[r].strip()})
        done(T("Encontrei resposta na caixa, mas nenhuma para COMPARAR ainda."))
        if rotulos:
            print(Tf("  Blocos presentes: {0}.", ', '.join(rotulos)))
            print(T("  Cada um aparece uma vez so' — entao nao ha' duas respostas concorrentes.\n"))
        else:
            warn(T("nao reconheci nenhum cabecalho do curso no que esta' colado la'."))
            print(T("  Os cabecalhos que eu procuro sao os que o proprio passo pede "
                  "(ex.: HISTORIAS:).\n"))
        _como_colar_duas()
        return

    quais = ", ".join(f"{r} ({len(v)} respostas)" for r, v in disputados.items())
    ok(Tf("encontrei bloco(s) com mais de uma resposta: {0}", quais))
    prompt = montar_prompt(disputados, todas)
    caminho = _salvar(prompt)

    print()
    if copiar(prompt):
        done(T("O prompt de consolidacao JA' ESTA' na sua area de transferencia."))
        print(T("  Cole numa IA (Ctrl+V) — pode ser ate' uma terceira, para desempatar."))
    else:
        done(T("O prompt de consolidacao esta' pronto."))
        print(Tf("  Abra o arquivo e copie TUDO (Ctrl+A, Ctrl+C): {0}", caminho))

    print(T("\n  Quando a IA responder:"))
    print(T("    1. leia a COMPARACAO (concordam · divergem · falta nas duas) — e' o"))
    print(T("       ponto onde VOCE decide;"))
    print(T("    2. copie a resposta INTEIRA dela;"))
    print(Tf('    3. cole no cartao "{0}" NO LUGAR das duas de antes', caixa.CARTAO))
    print(T("       (selecione tudo e cole por cima);"))
    print(T("    4. rode o passo normal — ele le a versao consolidada e segue."))
    print(Tf('\n  (Copia de seguranca do prompt em: {0})', caminho))


if __name__ == "__main__":
    try:
        main()
    except (KeyboardInterrupt, EOFError):
        print(T("\n(consolidacao cancelada — nada foi alterado no seu quadro.)"))
