"""
Scene Slot Bundle API.
[AC-SCENE-SLOT-01] 场景-槽位映射配置管理接口
"""

import logging
from typing import Annotated, Any

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

from app.core.database import get_session
from app.core.exceptions import MissingTenantIdException
from app.core.tenant import get_tenant_id
from app.models.entities import SceneSlotBundleCreate, SceneSlotBundleUpdate
from app.services.scene_slot_bundle_service import SceneSlotBundleService

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/admin/scene-slot-bundles", tags=["SceneSlotBundle"])


def get_current_tenant_id() -> str:
    """Get current tenant ID from context."""
    tenant_id = get_tenant_id()
    if not tenant_id:
        raise MissingTenantIdException()
    return tenant_id


def _bundle_to_dict(bundle: Any) -> dict[str, Any]:
    """Convert bundle to dict"""
    return {
        "id": str(bundle.id),
        "tenant_id": str(bundle.tenant_id),
        "scene_key": bundle.scene_key,
        "scene_name": bundle.scene_name,
        "description": bundle.description,
        "required_slots": bundle.required_slots,
        "optional_slots": bundle.optional_slots,
        "slot_priority": bundle.slot_priority,
        "completion_threshold": bundle.completion_threshold,
        "ask_back_order": bundle.ask_back_order,
        "status": bundle.status,
        "version": bundle.version,
        "created_at": bundle.created_at.isoformat() if bundle.created_at else None,
        "updated_at": bundle.updated_at.isoformat() if bundle.updated_at else None,
    }


@router.get(
    "",
    operation_id="listSceneSlotBundles",
    summary="List scene slot bundles",
    description="获取场景槽位包列表",
)
async def list_scene_slot_bundles(
    tenant_id: Annotated[str, Depends(get_current_tenant_id)],
    session: Annotated[AsyncSession, Depends(get_session)],
    status: Annotated[str | None, Query(
        description="按状态过滤: draft/active/deprecated"
    )] = None,
) -> JSONResponse:
    """
    列出场景槽位包
    """
    logger.info(
        f"Listing scene slot bundles: tenant={tenant_id}, status={status}"
    )
    
    service = SceneSlotBundleService(session)
    bundles = await service.list_bundles(tenant_id, status)
    
    return JSONResponse(
        content=[_bundle_to_dict(b) for b in bundles]
    )


@router.post(
    "",
    operation_id="createSceneSlotBundle",
    summary="Create scene slot bundle",
    description="[AC-SCENE-SLOT-01] 创建新的场景槽位包",
    status_code=201,
)
async def create_scene_slot_bundle(
    tenant_id: Annotated[str, Depends(get_current_tenant_id)],
    session: Annotated[AsyncSession, Depends(get_session)],
    bundle_create: SceneSlotBundleCreate,
) -> JSONResponse:
    """
    [AC-SCENE-SLOT-01] 创建场景槽位包
    """
    logger.info(
        f"[AC-SCENE-SLOT-01] Creating scene slot bundle: "
        f"tenant={tenant_id}, scene_key={bundle_create.scene_key}"
    )
    
    service = SceneSlotBundleService(session)
    
    try:
        bundle = await service.create_bundle(tenant_id, bundle_create)
        await session.commit()
    except ValueError as e:
        return JSONResponse(
            status_code=400,
            content={
                "error_code": "VALIDATION_ERROR",
                "message": str(e),
            }
        )
    
    return JSONResponse(
        status_code=201,
        content=_bundle_to_dict(bundle)
    )


@router.get(
    "/by-scene/{scene_key}",
    operation_id="getSceneSlotBundleBySceneKey",
    summary="Get scene slot bundle by scene key",
    description="根据场景标识获取槽位包",
)
async def get_scene_slot_bundle_by_scene_key(
    tenant_id: Annotated[str, Depends(get_current_tenant_id)],
    session: Annotated[AsyncSession, Depends(get_session)],
    scene_key: str,
) -> JSONResponse:
    """
    根据场景标识获取槽位包
    """
    logger.info(
        f"Getting scene slot bundle by scene_key: tenant={tenant_id}, scene_key={scene_key}"
    )
    
    service = SceneSlotBundleService(session)
    bundle = await service.get_bundle_by_scene_key(tenant_id, scene_key)
    
    if not bundle:
        return JSONResponse(
            status_code=404,
            content={
                "error_code": "NOT_FOUND",
                "message": f"Scene slot bundle with scene_key '{scene_key}' not found",
            }
        )
    
    return JSONResponse(content=_bundle_to_dict(bundle))


@router.get(
    "/{id}",
    operation_id="getSceneSlotBundle",
    summary="Get scene slot bundle by ID",
    description="获取单个场景槽位包详情（含槽位详情）",
)
async def get_scene_slot_bundle(
    tenant_id: Annotated[str, Depends(get_current_tenant_id)],
    session: Annotated[AsyncSession, Depends(get_session)],
    id: str,
) -> JSONResponse:
    """
    获取单个场景槽位包详情
    """
    logger.info(
        f"Getting scene slot bundle: tenant={tenant_id}, id={id}"
    )
    
    service = SceneSlotBundleService(session)
    bundle = await service.get_bundle_with_slot_details(tenant_id, id)
    
    if not bundle:
        return JSONResponse(
            status_code=404,
            content={
                "error_code": "NOT_FOUND",
                "message": f"Scene slot bundle {id} not found",
            }
        )
    
    return JSONResponse(content=bundle)


@router.put(
    "/{id}",
    operation_id="updateSceneSlotBundle",
    summary="Update scene slot bundle",
    description="更新场景槽位包",
)
async def update_scene_slot_bundle(
    tenant_id: Annotated[str, Depends(get_current_tenant_id)],
    session: Annotated[AsyncSession, Depends(get_session)],
    id: str,
    bundle_update: SceneSlotBundleUpdate,
) -> JSONResponse:
    """
    更新场景槽位包
    """
    logger.info(
        f"Updating scene slot bundle: tenant={tenant_id}, id={id}"
    )
    
    service = SceneSlotBundleService(session)
    
    try:
        bundle = await service.update_bundle(tenant_id, id, bundle_update)
    except ValueError as e:
        return JSONResponse(
            status_code=400,
            content={
                "error_code": "VALIDATION_ERROR",
                "message": str(e),
            }
        )
    
    if not bundle:
        return JSONResponse(
            status_code=404,
            content={
                "error_code": "NOT_FOUND",
                "message": f"Scene slot bundle {id} not found",
            }
        )
    
    await session.commit()
    
    return JSONResponse(content=_bundle_to_dict(bundle))


@router.delete(
    "/{id}",
    operation_id="deleteSceneSlotBundle",
    summary="Delete scene slot bundle",
    description="[AC-SCENE-SLOT-01] 删除场景槽位包",
    status_code=204,
)
async def delete_scene_slot_bundle(
    tenant_id: Annotated[str, Depends(get_current_tenant_id)],
    session: Annotated[AsyncSession, Depends(get_session)],
    id: str,
) -> JSONResponse:
    """
    [AC-SCENE-SLOT-01] 删除场景槽位包
    """
    logger.info(
        f"[AC-SCENE-SLOT-01] Deleting scene slot bundle: tenant={tenant_id}, id={id}"
    )
    
    service = SceneSlotBundleService(session)
    success = await service.delete_bundle(tenant_id, id)
    
    if not success:
        return JSONResponse(
            status_code=404,
            content={
                "error_code": "NOT_FOUND",
                "message": f"Scene slot bundle not found: {id}",
            }
        )
    
    await session.commit()
    
    return JSONResponse(status_code=204, content=None)
