"""
Reconcile ordre draft sync lifecycle.

Promotes sync_status based on known economic references on ordre_drafts:
- pending/failed + economic_order_number -> exported
- exported + economic_invoice_number -> posted
"""

import logging
from typing import Any, Dict, List

from app.core.database import execute_query, get_db_connection, release_db_connection
from app.services.economic_service import get_economic_service
from psycopg2.extras import RealDictCursor

logger = logging.getLogger(__name__)


async def reconcile_ordre_drafts_sync_status(apply_changes: bool = True) -> Dict[str, Any]:
    """Reconcile ordre_drafts sync statuses and optionally persist changes."""

    drafts = execute_query(
        """
        SELECT id, sync_status, economic_order_number, economic_invoice_number
        FROM ordre_drafts
        ORDER BY id ASC
        """,
        (),
    ) or []

    changes: List[Dict[str, Any]] = []
    invoice_status_cache: Dict[str, str] = {}
    economic_service = get_economic_service()

    for draft in drafts:
        current = (draft.get("sync_status") or "pending").strip().lower()
        target = current

        if current in {"pending", "failed"} and draft.get("economic_order_number"):
            target = "exported"
        if target == "exported" and draft.get("economic_invoice_number"):
            target = "posted"

        invoice_number = str(draft.get("economic_invoice_number") or "").strip()
        if invoice_number:
            if invoice_number not in invoice_status_cache:
                invoice_status_cache[invoice_number] = await economic_service.get_invoice_lifecycle_status(invoice_number)
            lifecycle = invoice_status_cache[invoice_number]
            if lifecycle == "paid":
                target = "paid"
            elif lifecycle in {"booked", "unpaid"} and target in {"pending", "failed", "exported"}:
                target = "posted"

        if target != current:
            changes.append(
                {
                    "draft_id": draft.get("id"),
                    "from": current,
                    "to": target,
                    "economic_invoice_number": invoice_number or None,
                }
            )

    if apply_changes and changes:
        conn = get_db_connection()
        try:
            with conn.cursor(cursor_factory=RealDictCursor) as cursor:
                for change in changes:
                    cursor.execute(
                        """
                        UPDATE ordre_drafts
                        SET sync_status = %s,
                            last_sync_at = CURRENT_TIMESTAMP,
                            updated_at = CURRENT_TIMESTAMP,
                            last_exported_at = CASE
                                WHEN %s IN ('exported', 'posted', 'paid') THEN CURRENT_TIMESTAMP
                                ELSE last_exported_at
                            END
                        WHERE id = %s
                        """,
                        (change["to"], change["to"], change["draft_id"]),
                    )
                    cursor.execute(
                        """
                        INSERT INTO ordre_draft_sync_events (
                            draft_id,
                            event_type,
                            from_status,
                            to_status,
                            event_payload,
                            created_by_user_id
                        ) VALUES (%s, %s, %s, %s, %s::jsonb, NULL)
                        """,
                        (
                            change["draft_id"],
                            "sync_status_reconcile",
                            change["from"],
                            change["to"],
                            '{"source":"reconcile_job"}',
                        ),
                    )
            conn.commit()
        except Exception:
            conn.rollback()
            raise
        finally:
            release_db_connection(conn)

    logger.info(
        "✅ Reconciled ordre draft sync status: %s changes (%s)",
        len(changes),
        "applied" if apply_changes else "preview",
    )

    return {
        "status": "applied" if apply_changes else "preview",
        "change_count": len(changes),
        "changes": changes,
    }
