#!/usr/bin/env python3
"""
Alinea el estado de los presupuestos con el de su oportunidad de CRM.

El CRM se cierra como "perdido" o "sin respuesta", pero eso no marcaba el
presupuesto ligado → quedaban en "Enviado" para siempre y las estadísticas
mentían. Este script (backfill de lo viejo; de acá en más lo hace la app sola)
manda a RECHAZADO los presupuestos ABIERTOS cuya oportunidad está cerrada en
negativo. "Sin respuesta" también es una pérdida → rechazado + motivo
"sin_respuesta".

Reglas (conservadoras):
- Solo toca presupuestos en estado `borrador` o `enviado` y SIN pedido.
  Nunca pisa aprobados, convertidos ni ya cerrados.
- Idempotente: una vez rechazados, dejan de matchear.

Uso (desde el server):
  PB_URL=http://localhost:8102 PB_ADMIN_EMAIL=... PB_ADMIN_PASSWORD=... \
    python3 backend/scripts/backfill_presupuestos_perdidos.py          # dry-run
    python3 backend/scripts/backfill_presupuestos_perdidos.py --apply  # escribe
"""
import json
import os
import sys
from datetime import datetime

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from create_collections import auth_admin, req  # noqa: E402

# CRM cerrado en negativo → estado de presupuesto (+ motivo de cierre).
CIERRE = {
    "perdido": ("rechazado", ""),
    "sin_respuesta": ("rechazado", "sin_respuesta"),
}
ABIERTOS = ("borrador", "enviado")


def main() -> int:
    apply = "--apply" in sys.argv
    base = os.environ.get("PB_URL", "http://localhost:8102")
    token = auth_admin()

    code, opp = req("GET", "/api/collections/crm_oportunidades/records?perPage=500&fields=id,estado,presupuesto", token=token)
    code2, pres = req("GET", "/api/collections/presupuestos/records?perPage=500&fields=id,codigo,estado,pedido", token=token)
    if code != 200 or code2 != 200:
        print(f"FATAL: no pude leer datos: {code}/{code2}", file=sys.stderr)
        return 1
    opp = opp.get("items", [])
    by_id = {p["id"]: p for p in pres.get("items", [])}

    stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
    backup = f"/tmp/presupuestos-backfill-backup-{stamp}.json"
    with open(backup, "w", encoding="utf-8") as fh:
        json.dump(pres.get("items", []), fh, ensure_ascii=False, indent=1)
    print(f"Backup de {len(by_id)} presupuestos → {backup}")

    objetivos = []  # (presup, nuevo_estado, motivo, crm_estado)
    for o in opp:
        crm_estado = o.get("estado")
        pid = o.get("presupuesto")
        if crm_estado not in CIERRE or not pid:
            continue
        p = by_id.get(pid)
        if not p:
            continue
        if p.get("pedido"):
            continue
        if p.get("estado") not in ABIERTOS:
            continue
        nuevo, motivo = CIERRE[crm_estado]
        objetivos.append((p, nuevo, motivo, crm_estado))

    print(f"\nPresupuestos a rechazar: {len(objetivos)}")
    from collections import Counter
    print("  por motivo CRM:", dict(Counter(t[3] for t in objetivos)))
    for p, nuevo, motivo, crm in objetivos[:15]:
        print(f"  {p['codigo']}: {p['estado']} → {nuevo}" + (f" (motivo {motivo})" if motivo else "") + f"   [CRM {crm}]")
    if len(objetivos) > 15:
        print(f"  … y {len(objetivos) - 15} más")

    if not apply:
        print("\nDRY-RUN. Nada se escribió. Correr con --apply para aplicar.")
        return 0

    fallos = 0
    for p, nuevo, motivo, _crm in objetivos:
        body = {"estado": nuevo}
        if motivo:
            body["cierre_motivo"] = motivo
        code, data = req("PATCH", f"/api/collections/presupuestos/records/{p['id']}", token=token, body=body)
        if code != 200:
            fallos += 1
            print(f"  ERROR {p['codigo']}: {code} {data}", file=sys.stderr)

    print(f"\nOK ({base}): {len(objetivos) - fallos} rechazados, {fallos} fallos.")
    print(f"Backup en {backup}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
