"""LLM 管理服务：Provider / Model / ModelSettings 的查询与 CRUD。"""

from __future__ import annotations

from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.utils import apply_keyword_filter, apply_order, paginate
from app.models.llm import Model, ModelCategoryKey, ModelSettings, Provider
from app.schemas.common import ApiResponse, PaginatedData, paginated_response
from app.schemas.llm import (
    ModelCreate,
    ModelRead,
    ModelSettingsUpdate,
    ModelUpdate,
    ProviderCreate,
    ProviderRead,
    ProviderUpdate,
)
from app.services.common import (
    create_and_refresh,
    delete_if_exists,
    entity_already_exists,
    entity_not_found,
    ensure_not_exists,
    flush_and_refresh,
    get_or_404,
    patch_model,
    require_entity,
)


async def list_providers_paginated(
    db: AsyncSession,
    *,
    q: str | None,
    order: str | None,
    is_desc: bool,
    page: int,
    page_size: int,
    allow_fields: set[str],
) -> ApiResponse[PaginatedData[ProviderRead]]:
    """分页查询供应商。"""
    stmt = select(Provider)
    stmt = apply_keyword_filter(stmt, q=q, fields=[Provider.name, Provider.description])
    stmt = apply_order(
        stmt,
        model=Provider,
        order=order,
        is_desc=is_desc,
        allow_fields=allow_fields,
        default="created_at",
    )
    items, total = await paginate(db, stmt=stmt, page=page, page_size=page_size)
    return paginated_response(
        [ProviderRead.model_validate(x) for x in items],
        page=page,
        page_size=page_size,
        total=total,
    )


async def create_provider(
    db: AsyncSession,
    *,
    body: ProviderCreate,
) -> Provider:
    """创建供应商。"""
    await ensure_not_exists(
        db,
        Provider,
        body.id,
        detail=entity_already_exists("Provider"),
        status_code=400,
    )
    return await create_and_refresh(
        db,
        Provider(
            id=body.id,
            name=body.name,
            base_url=body.base_url,
            api_key=body.api_key,
            api_secret=body.api_secret,
            description=body.description,
            status=body.status,
            created_by=body.created_by,
        ),
    )


async def get_provider(
    db: AsyncSession,
    *,
    provider_id: str,
) -> Provider:
    """获取供应商。"""
    return await get_or_404(db, Provider, provider_id, detail=entity_not_found("Provider"))


async def update_provider(
    db: AsyncSession,
    *,
    provider_id: str,
    body: ProviderUpdate,
) -> Provider:
    """更新供应商。"""
    provider = await get_or_404(db, Provider, provider_id, detail=entity_not_found("Provider"))
    patch_model(provider, body.model_dump(exclude_unset=True))
    return await flush_and_refresh(db, provider)


async def delete_provider(
    db: AsyncSession,
    *,
    provider_id: str,
) -> None:
    """删除供应商。"""
    await delete_if_exists(db, Provider, provider_id)


async def list_models_paginated(
    db: AsyncSession,
    *,
    provider_id: str | None,
    category: ModelCategoryKey | None,
    q: str | None,
    order: str | None,
    is_desc: bool,
    page: int,
    page_size: int,
    allow_fields: set[str],
) -> ApiResponse[PaginatedData[ModelRead]]:
    """分页查询模型。"""
    stmt = select(Model)
    if provider_id is not None:
        stmt = stmt.where(Model.provider_id == provider_id)
    if category is not None:
        stmt = stmt.where(Model.category == category)
    stmt = apply_keyword_filter(stmt, q=q, fields=[Model.name, Model.description])
    stmt = apply_order(
        stmt,
        model=Model,
        order=order,
        is_desc=is_desc,
        allow_fields=allow_fields,
        default="created_at",
    )
    items, total = await paginate(db, stmt=stmt, page=page, page_size=page_size)
    return paginated_response(
        [ModelRead.model_validate(x) for x in items],
        page=page,
        page_size=page_size,
        total=total,
    )


async def create_model(
    db: AsyncSession,
    *,
    body: ModelCreate,
) -> Model:
    """创建模型。"""
    await ensure_not_exists(
        db,
        Model,
        body.id,
        detail=entity_already_exists("Model"),
        status_code=400,
    )
    await require_entity(db, Provider, body.provider_id, detail=entity_not_found("Provider"), status_code=400)
    if body.is_default:
        await db.execute(update(Model).where(Model.category == body.category).values(is_default=False))
        await db.flush()
    return await create_and_refresh(
        db,
        Model(
            id=body.id,
            name=body.name,
            category=body.category,
            provider_id=body.provider_id,
            params=body.params,
            description=body.description,
            is_default=body.is_default,
            created_by=body.created_by,
        ),
    )


async def get_model(
    db: AsyncSession,
    *,
    model_id: str,
) -> Model:
    """获取模型。"""
    return await get_or_404(db, Model, model_id, detail=entity_not_found("Model"))


async def update_model(
    db: AsyncSession,
    *,
    model_id: str,
    body: ModelUpdate,
) -> Model:
    """更新模型。"""
    model = await get_or_404(db, Model, model_id, detail=entity_not_found("Model"))
    update_data = body.model_dump(exclude_unset=True)
    if "provider_id" in update_data:
        await require_entity(
            db,
            Provider,
            update_data["provider_id"],
            detail=entity_not_found("Provider"),
            status_code=400,
        )
    if update_data.get("is_default") is True:
        target_category = update_data.get("category", model.category)
        await db.execute(update(Model).where(Model.category == target_category).values(is_default=False))
        await db.flush()
    patch_model(model, update_data)
    return await flush_and_refresh(db, model)


async def delete_model(
    db: AsyncSession,
    *,
    model_id: str,
) -> None:
    """删除模型。"""
    await delete_if_exists(db, Model, model_id)


async def get_or_create_settings(
    db: AsyncSession,
) -> ModelSettings:
    """获取或创建单例设置。"""
    settings = await db.get(ModelSettings, 1)
    if settings is None:
        settings = await create_and_refresh(db, ModelSettings(id=1))
    return settings


async def get_model_settings(
    db: AsyncSession,
) -> ModelSettings:
    """获取模型全局设置。"""
    return await get_or_create_settings(db)


async def update_model_settings(
    db: AsyncSession,
    *,
    body: ModelSettingsUpdate,
) -> ModelSettings:
    """更新模型全局设置。"""
    settings = await get_or_create_settings(db)
    patch_model(settings, body.model_dump())
    return await flush_and_refresh(db, settings)
