from pathlib import Path
from app.odoo_delivery_task_reconciliation import reconcile_odoo_delivery_done


class _Mappings:
    def __init__(self, rows):
        self._rows = rows

    def all(self):
        return list(self._rows)

    def first(self):
        return self._rows[0] if self._rows else None


class _Result:
    def __init__(self, *, rows=None, scalar_value=None):
        self._rows = rows or []
        self._scalar = scalar_value

    def mappings(self):
        return _Mappings(self._rows)

    def scalar(self):
        return self._scalar


class _FakeConn:
    def __init__(self):
        self.calls = []

    def execute(self, statement, params=None):
        sql = str(statement)
        params = dict(params or {})
        self.calls.append((sql, params))
        if "FROM tasks" in sql and "FOR UPDATE" in sql:
            return _Result(rows=[
                {"id": "task-validation", "action_code": "VALIDATE_PHYSICAL_ORDER", "status": "pending"},
                {"id": "task-shipment", "action_code": "CREATE_SHIPMENT", "status": "pending"},
            ])
        if "UPDATE tasks" in sql:
            return _Result(scalar_value=params.get("task_id"))
        return _Result()


def test_odoo_done_maps_to_shipped_stage():
    src = Path("app/odoo_service.py").read_text()
    done_branch = src[src.index('if outgoing and all'):src.index('if any(state == "assigned"', src.index('if outgoing and all'))]
    assert '"physical_status": "shipped"' in done_branch
    assert '"stage": "SHIPPED"' in done_branch


def test_odoo_done_auto_completes_stale_physical_and_shipment_tasks():
    conn = _FakeConn()
    result = reconcile_odoo_delivery_done(
        conn,
        "opp-1",
        evidence={
            "sale_order": {"id": 318, "name": "S00318"},
            "pickings": [{"name": "WH/OUT/00338", "state": "done"}],
        },
    )

    assert result["odoo_done_pickings"] == ["WH/OUT/00338"]
    assert {row["action_code"] for row in result["completed_tasks"]} == {
        "VALIDATE_PHYSICAL_ORDER",
        "CREATE_SHIPMENT",
    }
    update_calls = [(sql, params) for sql, params in conn.calls if "UPDATE tasks" in sql]
    assert len(update_calls) == 2
    assert all("status = 'done'" in sql for sql, _ in update_calls)
    event_calls = [(sql, params) for sql, params in conn.calls if "INSERT INTO task_events" in sql]
    assert len(event_calls) == 2
    assert all("task_auto_completed" in sql for sql, _ in event_calls)


def test_all_odoo_done_paths_call_task_reconciliation():
    odoo_src = Path("app/odoo_service.py").read_text()
    reconciliation_src = Path("app/reconciliation_service.py").read_text()
    assert 'payload["task_reconciliation"] = reconcile_odoo_delivery_done' in odoo_src
    assert 'actor="reconciliation_odoo_sync"' in reconciliation_src
