"""v4.9.24: reconciliation process review must be explainable and actionable."""

import sys
import types
from pathlib import Path

if "sqlalchemy" not in sys.modules:
    sqlalchemy = types.ModuleType("sqlalchemy")
    sqlalchemy.text = lambda sql: sql
    sys.modules["sqlalchemy"] = sqlalchemy

if "app.db" not in sys.modules:
    app_db = types.ModuleType("app.db")
    app_db.engine = object()
    sys.modules["app.db"] = app_db

if "app.action_catalog" not in sys.modules:
    action_catalog = types.ModuleType("app.action_catalog")
    action_catalog.get_action_config = lambda code: {"route": "rever", "action": code, "action_required": True, "safe_to_post": False}
    sys.modules["app.action_catalog"] = action_catalog

from app import reconciliation_service as svc

ROOT = Path(__file__).resolve().parents[1]


def read(path: str) -> str:
    return (ROOT / path).read_text(encoding="utf-8")


def _item(id_, external_type, number, date, amount):
    return {
        "id": id_,
        "source_system": "jasmin" if external_type.startswith("jasmin") else "odoo",
        "external_type": external_type,
        "title": f"{external_type} · {number}",
        "customer_name": "ACZCO BRAGA ENERGY, LDA",
        "customer_tax_id": "517249200",
        "document_number": number,
        "document_date": date,
        "amount": amount,
        "currency": "EUR",
        "payload": {"record": {"name": number, "invoice_status": "to invoice"}} if external_type == "odoo_sale_order" else {},
        "operation_suggestions": [],
    }


def test_process_candidates_explain_reasons_and_risks(monkeypatch):
    monkeypatch.setattr(
        svc,
        "list_reconciliation_items",
        lambda *, status, limit, days: [
            _item("quote-154", "jasmin_quotation", "ORC.ORC2026.154", "2026-06-03", "638.60"),
            _item("sale-279", "odoo_sale_order", "S00279", "2026-06-05", "638.60"),
        ],
    )

    candidates = svc.list_reconciliation_process_candidates(status="open", days=7, limit=10)

    assert len(candidates) == 1
    candidate = candidates[0]
    assert candidate["review_status"] == "needs_review"
    assert "cliente fiscal por NIF exato" in candidate["reasons"]
    assert "valor igual entre documentos" in candidate["reasons"]
    assert "datas próximas" in candidate["reasons"]
    assert "venda Odoo sem fatura Jasmin associada" in candidate["risks"]


def test_process_candidates_flag_conflict_when_amounts_differ(monkeypatch):
    monkeypatch.setattr(
        svc,
        "list_reconciliation_items",
        lambda *, status, limit, days: [
            _item("quote-154", "jasmin_quotation", "ORC.ORC2026.154", "2026-06-03", "638.60"),
            _item("invoice-80", "jasmin_invoice", "FA2026.80", "2026-06-05", "190.00"),
        ],
    )

    candidates = svc.list_reconciliation_process_candidates(status="open", days=7, limit=10)

    assert len(candidates) == 2  # different amounts keep separate purchase anchors
    assert all("reasons" in candidate and "risks" in candidate for candidate in candidates)


def test_v4924_schema_and_ui_have_decisions_review_and_history_actions():
    service = read("app/reconciliation_service.py")
    page = read("app/admin_ui/pages/reconciliation.py")
    styles = read("app/admin_ui/styles.py")

    assert "CREATE TABLE IF NOT EXISTS reconciliation_decisions" in service
    assert "def _candidate_reasons_and_risks" in service
    assert "reasons" in service and "risks" in service and "review_status" in service
    assert "/reconciliation/processes/needs-review" in page
    assert "/reconciliation/processes/historical" in page
    assert "Motivos" in page and "Riscos" in page
    assert "cf-reconcile-explain" in styles
