from __future__ import annotations

from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session

from app.api.deps import (
    CurrentUserContext,
    get_current_user,
    get_db,
    require_platform_admin_user,
)
from app.schemas.expense_application_memory import (
    ExpenseApplicationMemoryListRead,
    ExpenseApplicationMemoryRead,
    ExpenseApplicationMemoryRevokedRead,
    ExpenseApplicationOrganizationMemoryCreate,
    ExpenseApplicationOrganizationMemoryRevoke,
    ExpenseApplicationOrganizationMemoryUpdate,
)
from app.services.expense_application_memory import ExpenseApplicationMemoryService
from app.services.expense_application_memory_admin import (
    ExpenseApplicationOrganizationMemoryService,
    OrganizationMemoryConflictError,
    OrganizationMemoryNotFoundError,
)

router = APIRouter(prefix="/expense-application-memories")
DbSession = Annotated[Session, Depends(get_db)]
CurrentUser = Annotated[CurrentUserContext, Depends(get_current_user)]
PlatformAdminUser = Annotated[
    CurrentUserContext,
    Depends(require_platform_admin_user),
]


@router.get(
    "/me",
    response_model=ExpenseApplicationMemoryListRead,
    summary="读取当前登录人的费用申请记忆",
)
def list_my_expense_application_memories(
    db: DbSession,
    current_user: CurrentUser,
) -> ExpenseApplicationMemoryListRead:
    return ExpenseApplicationMemoryService(db).list_current_user_memories(current_user)


@router.get(
    "/organization",
    response_model=ExpenseApplicationMemoryListRead,
    summary="读取当前租户的企业与部门费用记忆",
)
def list_organization_expense_application_memories(
    db: DbSession,
    current_user: PlatformAdminUser,
) -> ExpenseApplicationMemoryListRead:
    return ExpenseApplicationOrganizationMemoryService(db).list_organization_memories(
        current_user
    )


@router.post(
    "/organization",
    response_model=ExpenseApplicationMemoryRead,
    status_code=status.HTTP_201_CREATED,
    summary="创建企业或部门费用记忆",
)
def create_organization_expense_application_memory(
    payload: ExpenseApplicationOrganizationMemoryCreate,
    db: DbSession,
    current_user: PlatformAdminUser,
) -> ExpenseApplicationMemoryRead:
    try:
        return ExpenseApplicationOrganizationMemoryService(
            db
        ).create_organization_memory(payload, current_user)
    except OrganizationMemoryConflictError as error:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=str(error),
        ) from error
    except ValueError as error:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
            detail=str(error),
        ) from error


@router.put(
    "/organization/{memory_id}",
    response_model=ExpenseApplicationMemoryRead,
    summary="换代更新企业或部门费用记忆",
)
def update_organization_expense_application_memory(
    memory_id: str,
    payload: ExpenseApplicationOrganizationMemoryUpdate,
    db: DbSession,
    current_user: PlatformAdminUser,
) -> ExpenseApplicationMemoryRead:
    try:
        return ExpenseApplicationOrganizationMemoryService(
            db
        ).update_organization_memory(memory_id, payload, current_user)
    except OrganizationMemoryNotFoundError as error:
        raise _organization_memory_not_found() from error
    except OrganizationMemoryConflictError as error:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=str(error),
        ) from error
    except ValueError as error:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
            detail=str(error),
        ) from error


@router.post(
    "/organization/{memory_id}/revoke",
    response_model=ExpenseApplicationMemoryRevokedRead,
    summary="撤销企业或部门费用记忆",
)
def revoke_organization_expense_application_memory(
    memory_id: str,
    payload: ExpenseApplicationOrganizationMemoryRevoke,
    db: DbSession,
    current_user: PlatformAdminUser,
) -> ExpenseApplicationMemoryRevokedRead:
    try:
        return ExpenseApplicationOrganizationMemoryService(
            db
        ).revoke_organization_memory(memory_id, payload, current_user)
    except OrganizationMemoryNotFoundError as error:
        raise _organization_memory_not_found() from error
    except OrganizationMemoryConflictError as error:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=str(error),
        ) from error
    except ValueError as error:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
            detail=str(error),
        ) from error


@router.delete(
    "/{memory_id}",
    response_model=ExpenseApplicationMemoryRevokedRead,
    summary="撤销当前登录人的费用申请记忆",
)
def revoke_my_expense_application_memory(
    memory_id: str,
    db: DbSession,
    current_user: CurrentUser,
) -> ExpenseApplicationMemoryRevokedRead:
    result = ExpenseApplicationMemoryService(db).revoke_current_user_memory(
        memory_id,
        current_user,
    )
    if result is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="未找到可撤销的个人费用申请记忆。",
        )
    return result


def _organization_memory_not_found() -> HTTPException:
    return HTTPException(
        status_code=status.HTTP_404_NOT_FOUND,
        detail="未找到当前租户内可管理的组织费用记忆。",
    )
