#!/usr/bin/env python3
"""Guarded repair for a validated reconstructed review whose blocked task stayed terminal.

Dry-run by default. It only reactivates a task when:
- the opportunity exists and its explicit reconstructed review is validated;
- the central decision still matches the blocked action;
- no pending task for that action exists;
- a skipped/ignored materialized task for that action exists;
- for physical validation, no validation link already exists.
"""
from __future__ import annotations

import argparse
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
if str(ROOT) not in sys.path:
    sys.path.insert(0, str(ROOT))

from sqlalchemy import text

from app.db import engine
from app.opportunity_action_task_materializer import ensure_pending_task_for_next_action
from app.opportunity_next_action_service import get_opportunity_next_action
from app.work_center_action_policy import canonical_action_code, reconstructed_review_status


def inspect(opportunity_id: str) -> dict:
    with engine.begin() as conn:
        row = conn.execute(text("""
            SELECT id::text, title, stage, metadata,
                   metadata #>> '{reconstructed_review,blocked_action_code}' AS blocked_action
            FROM opportunities
            WHERE id = CAST(:id AS UUID)
        """), {"id": opportunity_id}).mappings().first()
        if not row:
            raise SystemExit("Oportunidade não encontrada.")
        tasks = conn.execute(text("""
            SELECT id::text, action_code, status, idempotency_key, metadata
            FROM tasks
            WHERE opportunity_id = CAST(:id AS UUID)
              AND action_code IN ('VALIDATE_PHYSICAL_ORDER','CREATE_SHIPMENT','SEND_INVOICE','PREPARE_ORDER')
            ORDER BY created_at DESC
        """), {"id": opportunity_id}).mappings().all()
        physical = conn.execute(text("""
            SELECT id::text FROM operation_links
            WHERE opportunity_id = CAST(:id AS UUID)
              AND system='odoo' AND external_type='physical_validation'
              AND status='validated'
            LIMIT 1
        """), {"id": opportunity_id}).scalar()
    decision = get_opportunity_next_action(opportunity_id)
    return {"opportunity": dict(row), "tasks": [dict(t) for t in tasks], "physical_validated": bool(physical), "decision": decision}


def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("--opportunity-id", required=True)
    ap.add_argument("--apply", action="store_true")
    args = ap.parse_args()

    data = inspect(args.opportunity_id)
    opp = data["opportunity"]
    review = reconstructed_review_status(opp.get("metadata"))
    blocked = canonical_action_code(opp.get("blocked_action"))
    decision_code = canonical_action_code(data["decision"].get("action_code"))
    pending = [t for t in data["tasks"] if canonical_action_code(t.get("action_code")) == decision_code and str(t.get("status")) == "pending"]
    terminal = [t for t in data["tasks"] if canonical_action_code(t.get("action_code")) == decision_code and str(t.get("status")) in {"skipped", "ignored"}]

    print(f"Opportunity: {opp.get('title')} ({opp.get('stage')})")
    print(f"Review: {review}")
    print(f"Blocked action: {blocked or '-'}")
    print(f"Central decision: {decision_code}")
    print(f"Pending same action: {len(pending)}")
    print(f"Terminal same action: {len(terminal)}")

    if review != "validated":
        raise SystemExit("ABORTADO: revisão não está validated.")
    if not blocked or decision_code != blocked:
        raise SystemExit("ABORTADO: decisão central não coincide com a ação desbloqueada.")
    if pending:
        print("OK: já existe task pendente; nenhuma alteração.")
        return 0
    if not terminal:
        raise SystemExit("ABORTADO: não existe task materializada terminal para reativar.")
    if decision_code == "VALIDATE_PHYSICAL_ORDER" and data["physical_validated"]:
        raise SystemExit("ABORTADO: já existe validação física confirmada.")

    print(f"SAFE: reativar {terminal[0]['id']} ({terminal[0]['status']})")
    if not args.apply:
        print("Dry-run only. Use --apply.")
        return 0

    result = ensure_pending_task_for_next_action(
        args.opportunity_id,
        data["decision"],
        source="manual_v132_2_reactivation_repair",
        actor="operator",
        reactivate_skipped=True,
    )
    print("Resultado:", result)
    if not result.get("reactivated") and result.get("reason") != "pending_exists":
        return 2
    return 0

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