"""/api/team — the ADMIN → Team page backend (M7). Thin HTTP layer over
services/team_admin (04 "no inline permission logic in routers"): the
worker roster + append-only rate edits + activate/deactivate + the
project-scoped billout rate-override rules. Every rule (the
can_manage_team gate, append-only term history, XOR override validation)
lives in the service; this file only shapes requests and translates
ServiceError -> the structured ApiError triple."""

from __future__ import annotations

import uuid

from fastapi import APIRouter
from pydantic import BaseModel

from app.routers.deps import ActorDep, ApiError, SessionDep
from app.services import team_admin
from app.services.errors import ServiceError

router = APIRouter()


def _run(fn, *args, **kwargs):
    try:
        return fn(*args, **kwargs)
    except ServiceError as exc:
        raise ApiError(exc.status, exc.code, exc.summary, exc.detail) from exc


class AddWorkerBody(BaseModel):
    name: str
    email: str
    cost_rate: str | None = None
    billout_rate: str | None = None
    currency: str | None = None
    consolidate_as: str | None = None
    notes: str | None = None
    can_manage_imports: bool = False


class UpdateWorkerBody(BaseModel):
    """PATCH semantics: only the SET fields reach the service, so a
    manager-render form that omits billout_rate can never clobber the
    owner's stored rate (T-TEAM-06)."""

    name: str | None = None
    email: str | None = None
    cost_rate: str | None = None
    billout_rate: str | None = None
    currency: str | None = None
    consolidate_as: str | None = None
    notes: str | None = None
    can_manage_imports: bool | None = None


class OverrideCreateBody(BaseModel):
    project_id: str
    worker_party_id: str | None = None
    override_rate: str | None = None
    override_pct: str | None = None
    currency: str | None = None
    notes: str | None = None


class OverrideUpdateBody(BaseModel):
    override_rate: str | None = None
    override_pct: str | None = None
    currency: str | None = None
    notes: str | None = None


@router.get("/api/team")
def list_team(session: SessionDep, actor: ActorDep) -> dict:
    return _run(team_admin.list_workers, session, actor)


@router.post("/api/team/workers")
def add_worker(session: SessionDep, actor: ActorDep, body: AddWorkerBody) -> dict:
    return _run(team_admin.add_worker, session, actor, body.model_dump())


@router.patch("/api/team/workers/{party_id}")
def update_worker(
    session: SessionDep, actor: ActorDep, party_id: uuid.UUID, body: UpdateWorkerBody
) -> dict:
    patch = {k: getattr(body, k) for k in body.model_fields_set}
    return _run(team_admin.update_worker, session, actor, party_id, patch)


@router.post("/api/team/workers/{party_id}/deactivate")
def deactivate_worker(session: SessionDep, actor: ActorDep, party_id: uuid.UUID) -> dict:
    return _run(team_admin.set_active, session, actor, party_id, active=False)


@router.post("/api/team/workers/{party_id}/reactivate")
def reactivate_worker(session: SessionDep, actor: ActorDep, party_id: uuid.UUID) -> dict:
    return _run(team_admin.set_active, session, actor, party_id, active=True)


@router.post("/api/team/rate-overrides")
def create_override(session: SessionDep, actor: ActorDep, body: OverrideCreateBody) -> dict:
    return _run(team_admin.create_rate_override, session, actor, body.model_dump())


@router.patch("/api/team/rate-overrides/{override_id}")
def update_override(
    session: SessionDep, actor: ActorDep, override_id: uuid.UUID, body: OverrideUpdateBody
) -> dict:
    return _run(team_admin.update_rate_override, session, actor, override_id, body.model_dump())


@router.delete("/api/team/rate-overrides/{override_id}")
def delete_override(session: SessionDep, actor: ActorDep, override_id: uuid.UUID) -> dict:
    return _run(team_admin.delete_rate_override, session, actor, override_id)
