#!/usr/bin/env python3
"""Read-only audit for Odoo status consistency on ClientFlow opportunities.

Reports opportunities that are in advanced operational stages but lack a linked
Odoo sale order or a recently synced physical_status operation link.
"""
from __future__ import annotations

from datetime import datetime, timezone
from pathlib import Path
import json

from sqlalchemy import text

from app.db import engine

ADVANCED_STAGES = (
    "ODOO_ORDER_CREATED", "IN_PRODUCTION", "ORDER_PREPARATION", "READY_TO_SHIP",
    "INVOICED", "SHIPMENT_CREATED", "SHIPPED", "TRACKING_SENT", "DELIVERED", "WON",
)


def main() -> int:
    with engine.begin() as conn:
        rows = conn.execute(text("""
            SELECT
                o.id::text AS opportunity_id,
                o.title,
                o.customer_name,
                o.customer_email,
                o.status,
                o.stage,
                sale.external_name AS odoo_sale,
                sale.status AS sale_status,
                phys.status AS physical_status,
                phys.last_synced_at AS physical_last_synced_at,
                inv.external_name AS invoice_number
            FROM opportunities o
            LEFT JOIN operation_links sale
              ON sale.opportunity_id = o.id
             AND sale.system = 'odoo'
             AND sale.external_type = 'sale_order'
            LEFT JOIN operation_links phys
              ON phys.opportunity_id = o.id
             AND phys.system = 'odoo'
             AND phys.external_type = 'physical_status'
            LEFT JOIN operation_links inv
              ON inv.opportunity_id = o.id
             AND inv.system = 'jasmin'
             AND inv.external_type = 'invoice'
            WHERE COALESCE(o.status, '') IN ('open','won','closed','done','completed')
              AND (
                    COALESCE(o.stage, '') = ANY(CAST(:advanced AS text[]))
                 OR inv.id IS NOT NULL
              )
            ORDER BY o.updated_at DESC
            LIMIT 200
        """), {"advanced": list(ADVANCED_STAGES)}).mappings().all()

    missing_sale = [dict(r) for r in rows if not r.get("odoo_sale")]
    missing_physical = [dict(r) for r in rows if r.get("odoo_sale") and not r.get("physical_status")]

    report = {
        "generated_at": datetime.now(timezone.utc).isoformat(),
        "checked": len(rows),
        "missing_sale_order": missing_sale[:50],
        "missing_physical_status": missing_physical[:50],
    }
    out_dir = Path("audit_reports")
    out_dir.mkdir(exist_ok=True)
    out_path = out_dir / "odoo_opportunity_sync_audit.json"
    out_path.write_text(json.dumps(report, ensure_ascii=False, indent=2, default=str))

    print("ClientFlow Odoo opportunity sync audit")
    print("=" * 80)
    print("checked:", len(rows))
    print("missing_sale_order:", len(missing_sale))
    print("missing_physical_status:", len(missing_physical))
    print("JSON:", out_path)
    if missing_sale:
        print("\nExamples missing sale order:")
        for r in missing_sale[:10]:
            print(f"- {r['opportunity_id']} | {r.get('title')} | stage={r.get('stage')} | invoice={r.get('invoice_number')}")
    if missing_physical:
        print("\nExamples missing physical status:")
        for r in missing_physical[:10]:
            print(f"- {r['opportunity_id']} | {r.get('title')} | sale={r.get('odoo_sale')} | stage={r.get('stage')}")
    return 1 if missing_sale or missing_physical else 0


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