"""Small active Web mutation ports for ARR2.0."""

from __future__ import annotations

import threading
from dataclasses import dataclass
from datetime import date
from typing import Any, Dict, Protocol

from arr_web.contracts import PortalError
from monthly_reports.service import MonthlyReportService, RunRequest


class UploadCoordinator(Protocol):
    def submit(self, original_filename: str, payload: bytes) -> Dict[str, Any]:
        ...


class DailyPriceReviewCoordinator(Protocol):
    def get_price_review(self, job_id: str, limit: int, offset: int) -> Dict[str, Any]:
        ...

    def update_price_review_item(
        self,
        job_id: str,
        item_id: int,
        case_id: str,
        revision: int,
        real_price: str,
        actor_username: str,
    ) -> Dict[str, Any]:
        ...

    def finalize_price_review(
        self,
        job_id: str,
        case_id: str,
        revision: int,
        actor_username: str,
    ) -> Dict[str, Any]:
        ...

    def cancel_price_review(
        self,
        job_id: str,
        case_id: str,
        revision: int,
        actor_username: str,
    ) -> Dict[str, Any]:
        ...


class MonthlyCoordinator(Protocol):
    def generate(self, month_key: str, as_of_date: date) -> Dict[str, Any]:
        ...


class UnavailableUploadCoordinator:
    def submit(self, original_filename: str, payload: bytes) -> Dict[str, Any]:
        raise PortalError(
            "PROCESSING_GATEWAY_UNAVAILABLE",
            "文件接收服务尚未完成生产接线",
            503,
        )


class UnavailableDailyPriceReviewCoordinator:
    @staticmethod
    def _raise() -> None:
        raise PortalError("PROCESSING_GATEWAY_UNAVAILABLE", "人工价格复核服务暂不可用", 503)

    def get_price_review(self, job_id: str, limit: int, offset: int) -> Dict[str, Any]:
        self._raise()

    def update_price_review_item(
        self, job_id: str, item_id: int, case_id: str, revision: int, real_price: str, actor_username: str
    ) -> Dict[str, Any]:
        self._raise()

    def finalize_price_review(
        self, job_id: str, case_id: str, revision: int, actor_username: str
    ) -> Dict[str, Any]:
        self._raise()

    def cancel_price_review(
        self, job_id: str, case_id: str, revision: int, actor_username: str
    ) -> Dict[str, Any]:
        self._raise()


class UnavailableMonthlyCoordinator:
    def generate(self, month_key: str, as_of_date: date) -> Dict[str, Any]:
        raise PortalError(
            "MONTHLY_GENERATOR_UNAVAILABLE",
            "月报生成服务暂不可用",
            503,
        )


@dataclass
class ProgramMonthlyCoordinator:
    """Run the deterministic monthly database program."""

    service: MonthlyReportService

    def __post_init__(self) -> None:
        self._lock = threading.Lock()

    def generate(self, month_key: str, as_of_date: date) -> Dict[str, Any]:
        year, month = (int(part) for part in month_key.split("-"))
        request = RunRequest(year, month, as_of_date)
        try:
            request.validate()
        except Exception:
            raise PortalError("MONTHLY_REQUEST_INVALID", "月报日期范围无效") from None
        if not self._lock.acquire(blocking=False):
            raise PortalError("MONTHLY_ALREADY_RUNNING", "该服务正在生成月报", 409)
        try:
            result = self.service.run(request)
        finally:
            self._lock.release()
        payload = result.to_dict()
        if result.status != "success":
            error = payload.get("errors", [{}])[0]
            code = str(error.get("code") or "MONTHLY_GENERATION_FAILED")
            raise PortalError(code, "月报生成未完成", 422)
        return payload
