"""
Discount rule management endpoints.
"""

import math
from typing import Annotated
from uuid import UUID

from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.auth_deps import get_current_user, require_permission
from app.core.dependencies import get_db
from app.core.exceptions import ForbiddenException
from app.core.pagination import PaginationParams
from app.core.permissions import PermissionCode
from app.core.responses import PaginatedResponse, SuccessResponse
from app.models.user import User
from app.repositories.lab_repository import LabRepository
from app.schemas.billing import (
    DiscountRuleCreate,
    DiscountRuleResponse,
    DiscountRuleUpdate,
)
from app.services.discount_service import DiscountService

router = APIRouter(prefix="/discounts", tags=["Discounts & Billing Rules"])
_discount_service = DiscountService()


async def _resolve_lab_id(
    db: AsyncSession,
    user: User,
    requested_lab_id: UUID | None,
) -> UUID:
    """Resolve and authorize the target branch lab_id."""
    if user.is_superadmin:
        if requested_lab_id:
            return requested_lab_id
        if user.lab_id:
            return user.lab_id
        return await LabRepository().get_default_lab_id(db)

    if not user.lab_id:
        return await LabRepository().get_default_lab_id(db)

    if requested_lab_id and requested_lab_id != user.lab_id:
        raise ForbiddenException("Access denied to another lab branch.")

    return user.lab_id


@router.get(
    "",
    response_model=PaginatedResponse[DiscountRuleResponse],
    status_code=status.HTTP_200_OK,
    summary="List discount rules",
    description="Retrieve paginated discount rules for a lab branch.",
    dependencies=[Depends(require_permission(PermissionCode.DISCOUNT_READ))],
)
async def list_discounts(
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
    pagination: Annotated[PaginationParams, Depends()],
    lab_id: UUID | None = Query(None, description="Filter by lab branch ID"),
    is_active: bool | None = Query(None, description="Filter by active status"),
    q: str | None = Query(None, description="Search by rule name or code"),
) -> PaginatedResponse[DiscountRuleResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, lab_id)
    items, total = await _discount_service.list_discount_rules(
        db,
        lab_id=target_lab_id,
        is_active=is_active,
        search=q,
        page=pagination.page,
        limit=pagination.limit,
    )
    pages = math.ceil(total / pagination.limit) if total > 0 else 1
    return PaginatedResponse(
        data=[DiscountRuleResponse.model_validate(i) for i in items],
        meta={
            "page": pagination.page,
            "limit": pagination.limit,
            "total": total,
            "pages": pages,
        },
    )


@router.post(
    "",
    response_model=SuccessResponse[DiscountRuleResponse],
    status_code=status.HTTP_201_CREATED,
    summary="Create discount rule",
    description="Configure a new branch discount rule (percentage or fixed).",
    dependencies=[Depends(require_permission(PermissionCode.DISCOUNT_WRITE))],
)
async def create_discount(
    data: DiscountRuleCreate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
    lab_id: UUID | None = Query(None, description="Target branch lab ID"),
) -> SuccessResponse[DiscountRuleResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, lab_id)
    rule = await _discount_service.create_discount_rule(db, target_lab_id, data, actor=current_user)
    return SuccessResponse(
        data=DiscountRuleResponse.model_validate(rule),
        message="Discount rule created successfully.",
    )


@router.get(
    "/{rule_id}",
    response_model=SuccessResponse[DiscountRuleResponse],
    status_code=status.HTTP_200_OK,
    summary="Get discount rule",
    description="Retrieve details of a specific discount rule.",
    dependencies=[Depends(require_permission(PermissionCode.DISCOUNT_READ))],
)
async def get_discount(
    rule_id: UUID,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[DiscountRuleResponse]:
    target_lab_id = None if current_user.is_superadmin else current_user.lab_id
    rule = await _discount_service.get_discount_rule(db, rule_id, lab_id=target_lab_id)
    return SuccessResponse(data=DiscountRuleResponse.model_validate(rule))


@router.patch(
    "/{rule_id}",
    response_model=SuccessResponse[DiscountRuleResponse],
    status_code=status.HTTP_200_OK,
    summary="Update discount rule",
    description="Update an existing discount rule.",
    dependencies=[Depends(require_permission(PermissionCode.DISCOUNT_WRITE))],
)
async def update_discount(
    rule_id: UUID,
    data: DiscountRuleUpdate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[DiscountRuleResponse]:
    target_lab_id = current_user.lab_id or await LabRepository().get_default_lab_id(db)
    rule = await _discount_service.update_discount_rule(db, rule_id, target_lab_id, data, actor=current_user)
    return SuccessResponse(
        data=DiscountRuleResponse.model_validate(rule),
        message="Discount rule updated successfully.",
    )


@router.delete(
    "/{rule_id}",
    response_model=SuccessResponse[dict[str, str]],
    status_code=status.HTTP_200_OK,
    summary="Delete discount rule",
    description="Soft delete a discount rule from a branch.",
    dependencies=[Depends(require_permission(PermissionCode.DISCOUNT_WRITE))],
)
async def delete_discount(
    rule_id: UUID,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[dict[str, str]]:
    target_lab_id = current_user.lab_id or await LabRepository().get_default_lab_id(db)
    await _discount_service.delete_discount_rule(db, rule_id, target_lab_id, actor=current_user)
    return SuccessResponse(
        data={"id": str(rule_id)},
        message="Discount rule deleted successfully.",
    )
