# -*- coding: utf-8 -*-
"""业务层 · 任务状态机（抢单 / 投标 / 交付 / 中标 / 验收）。

业务层只处理业务逻辑；不感知 HTTP 之外的框架细节。依赖基础设施层
Repository（经 Database 门面），不反向依赖接口层。
"""
from __future__ import annotations

from fastapi import HTTPException

from ..infrastructure.repositories import Database


class TaskService:
    """统一任务状态流转：grab/bid/deliver/win/review。"""

    def __init__(self, db: Database):
        self.db = db

    async def grab(self, task_id: str, actor: dict) -> dict:
        """抢单：仅 published + grab 模式可抢，抢后置 in_progress。"""
        task = await self.db.tasks.get(task_id)
        if task is None or task["status"] != "published" or task["mode"] != "grab":
            raise HTTPException(status_code=400, detail="任务不可抢单")
        return await self.db.tasks.set_status(task_id, "in_progress")

    async def bid(self, task_id: str, actor: dict, quote: int, plan: str) -> dict:
        """投标：仅 published + bid 模式可投。"""
        task = await self.db.tasks.get(task_id)
        if task is None or task["status"] != "published" or task["mode"] != "bid":
            raise HTTPException(status_code=400, detail="任务不可投标")
        return await self.db.bids.create(
            task_id, actor["id"], actor.get("nickname") or actor["username"],
            quote, plan,
        )

    async def deliver(self, task_id: str, actor: dict) -> dict:
        """交付：任务存在且处于进行中（in_progress）才可交付 → delivered。

        补齐原实现「无任何状态预检」的缺陷，防随意交付。
        """
        task = await self.db.tasks.get(task_id)
        if task is None:
            raise HTTPException(status_code=404, detail="Task not found")
        if task["status"] != "in_progress":
            raise HTTPException(status_code=400, detail="任务未在进行中，无法交付")
        return await self.db.tasks.set_status(task_id, "delivered")

    async def enterprise_submit(self, task_id: str) -> dict:
        """企业提交审核：pending 任务 → published。"""
        return await self.db.tasks.set_status(task_id, "published")

    async def win_bid(self, task_id: str, bid_id: str) -> dict:
        """企业评标中标：bid → win，task → in_progress（双状态联动）。"""
        bid = await self.db.bids.get(bid_id)
        if bid is None or bid["task_id"] != task_id:
            raise HTTPException(status_code=404, detail="竞标不存在")
        await self.db.bids.set_status(bid_id, "win")
        return await self.db.tasks.set_status(task_id, "in_progress")

    async def review(self, task_id: str, accept: bool) -> dict:
        """企业验收：accept → completed；reject → in_progress。"""
        target = "completed" if accept else "in_progress"
        return await self.db.tasks.set_status(task_id, target)
