"""Commit Minion — one job: `commitAsset` on BASF (spec §2.4).

Consumes: fastlane.docs.accepted     (emitted by webhook when BASF says docs are OK)
Produces: fastlane.tank.allocate.completed  (PENDING — awaiting BASF support approval)
DLQ     : fastlane.asset.commit.dlq

Spec §2.4 rules enforced here:
  - locationList is MANDATORY: must include "1" (non-DG) or "2" (DG) + site code.
  - commitAsset does NOT increase incrementalVersion.
  - After commit, status → "waiting for approval".
  - BASF support then approves/rejects → triggers §5.1 webhook → status_listener.
"""
from __future__ import annotations

import asyncio

from app.config import get_settings
from app.logger import get_logger
from app.schemas import AllocationStatus, TankAllocationStatusEvent
from app.services.fastlane_client import FastlaneApiError, FastlaneClient
from minions._runner import emit, envelope_key, run_minion

log = get_logger("commit-minion")
_client = FastlaneClient()


async def handle(event: dict) -> None:
    s        = get_settings()
    asset_id = int(event["fastlane_asset_id"])
    inc      = int(event.get("incremental_version") or 1)

    # §2.4: locationList MANDATORY — must include "1" (non-DG) or "2" (DG)
    is_dg       = bool(event.get("is_dangerous_goods", False))
    location_list = (
        event.get("location_list")
        or FastlaneClient.default_location_list(is_dg)
    )
    # Guard: ensure "1" or "2" is present (spec §2.4 hard requirement)
    if "1" not in location_list and "2" not in location_list:
        location_list = ["2" if is_dg else "1"] + list(location_list)

    log.info(
        "commitAsset asset=%s v=%s locationList=%s",
        asset_id, inc, location_list,
    )

    try:
        await _client.commit_asset(
            asset_id            = asset_id,
            incremental_version = inc,
            location_list       = location_list,
        )
    except FastlaneApiError as exc:
        log.error("commitAsset FAIL asset=%s: [%s] %s", asset_id, exc.code, exc.message)
        raise RuntimeError(f"BASF commitAsset failed: {exc}") from exc

    # §2.4: commitAsset does NOT increase incrementalVersion — keep inc as-is
    log.info(
        "commitAsset OK asset=%s v=%s — status: waiting for BASF support approval",
        asset_id, inc,
    )

    # Emit PENDING (not REGISTERED — BASF support must approve via §5.1 webhook)
    status_event = TankAllocationStatusEvent(
        event_type          = s.topic_allocate_completed,
        job_id              = event.get("job_id"),
        tank_id             = event.get("tank_id"),
        licence_number      = event.get("licence_number"),
        status              = AllocationStatus.PENDING,
        fastlane_id         = asset_id,
        incremental_version = inc,       # unchanged per §2.4
        message             = "Submitted for BASF support review — awaiting approval",
    )
    await emit(
        s.topic_allocate_completed,
        envelope_key(event),
        status_event.model_dump(mode="json"),
    )


async def main() -> None:
    s = get_settings()
    await run_minion(
        name="commit-minion",
        topic=s.topic_docs_accepted,
        group_id=s.consumer_group_commit,
        handler=handle,
        dlq_topic=s.topic_commit_dlq,
    )


if __name__ == "__main__":
    asyncio.run(main())
