"""
Projects API - Core Module

包含项目核心 CRUD 相关的 API 路由。
"""

import logging
import uuid
from typing import Optional

from fastapi import APIRouter, BackgroundTasks, Query, Request, Depends
from pydantic import TypeAdapter

from src.models.schemas import (
    ResponseModel,
    CreateProjectRequest, UpdateProjectRequest,
    InitializeProjectRequest,
)
from src.auth.dependencies import get_current_user
from src.auth.models import UserAuth
from src.services.project_service import project_manager
from src.services.project_initialization_service import run_initialization_pipeline
from src.services.script_project_initialization_service import run_script_project_initialization
from src.services.script_to_canvas_service import convert_script_project_to_canvas
from src.utils.errors import ErrorCode, AppException

logger = logging.getLogger(__name__)

router = APIRouter(tags=["projects"])


def _check_project_access(project_id: str, user_id: str) -> Optional:
    """检查用户是否有权限访问项目"""
    project = project_manager.get_project(project_id, user_id=user_id)
    return project


def _progress_callback(project_id: str):
    def _cb(step: str, percentage: int, message: str, details: Optional[dict] = None):
        try:
            project_manager.update_project(
                project_id,
                {
                    "progress": {
                        "current_step": step,
                        "percentage": percentage,
                        "message": message,
                        "details": details or {},
                    }
                },
            )
        except Exception as e:
            logger.error("Failed to update progress: %s", e)
    return _cb


# --- 项目管理 ---
async def _create_initializing_project(
    request: InitializeProjectRequest,
    current_user: UserAuth,
    background_tasks: BackgroundTasks,
    project_type: str,
):
    project = project_manager.create_project(
        name=request.name,
        description="正在从小说初始化...",
        type=project_type,
        chapters=[],
        assets=[],
        status="initializing",
        user_id=current_user.id
    )
    progress_cb = _progress_callback(project.id)
    if project_type == "script":
        background_tasks.add_task(
            run_script_project_initialization,
            project.id,
            request.novel_text,
            progress_cb,
            current_user.id,
            request.model,
            request.provider,
        )
    else:
        background_tasks.add_task(
            run_initialization_pipeline,
            project.id,
            request.novel_text,
            request.style,
            progress_cb,
            current_user.id,
        )
    return project


@router.post("/projects/initialize-from-novel", response_model=ResponseModel)
@router.post("/projects/init-from-novel", response_model=ResponseModel)
@router.post("/projects/initialize-canvas-from-novel", response_model=ResponseModel)
async def initialize_canvas_project_from_novel(
    request: InitializeProjectRequest,
    background_tasks: BackgroundTasks,
    current_user: UserAuth = Depends(get_current_user)
):
    """
    使用多智能体管道从小说文本初始化项目（后台任务）
    步骤: 1. 立即创建项目（草稿） 2. 触发后台任务进行完整初始化
    """
    try:
        project = await _create_initializing_project(request, current_user, background_tasks, "canvas")
        return ResponseModel(data=project)
    except Exception as e:
        logger.error("Error initializing project: %s", e, exc_info=True)
        raise AppException(
                message=str(e),
                code=ErrorCode.INTERNAL_ERROR,
                status_code=500
            )


@router.post("/projects/initialize-script-from-novel", response_model=ResponseModel)
async def initialize_script_project_from_novel(
    request: InitializeProjectRequest,
    background_tasks: BackgroundTasks,
    current_user: UserAuth = Depends(get_current_user)
):
    """使用多 Agent 改编流程从小说文本初始化剧本项目。"""
    try:
        project = await _create_initializing_project(request, current_user, background_tasks, "script")
        return ResponseModel(data=project)
    except Exception as e:
        logger.error("Error initializing script project: %s", e, exc_info=True)
        raise AppException(
                message=str(e),
                code=ErrorCode.INTERNAL_ERROR,
                status_code=500
            )

@router.post("/projects", response_model=ResponseModel)
async def create_project(
    request: CreateProjectRequest,
    current_user: UserAuth = Depends(get_current_user)
):
    """Create a new project"""
    try:
        project = project_manager.create_project(
            name=request.name,
            description=request.description,
            type=request.type,
            chapters=request.chapters,
            assets=request.assets,
            user_id=current_user.id
        )
        return ResponseModel(data=project)
    except Exception as e:
        logger.error(f"Error creating project: {e}", exc_info=True)
        raise AppException(
                message=str(e),
                code=ErrorCode.INTERNAL_ERROR,
                status_code=500
            )

@router.get("/projects", response_model=ResponseModel)
async def list_projects(
    request: Request,
    page: int = Query(1, ge=1, description="页码,从1开始"),
    page_size: int = Query(20, ge=1, le=100, description="每页数量,最大100"),
    sort: Optional[str] = Query(None, description="排序字段,格式: field:asc 或 field:desc"),
    filter: Optional[str] = Query(None, description="过滤条件,JSON格式"),
    current_user: UserAuth = Depends(get_current_user)
):
    """
    List all projects with pagination support.

    Args:
        page: 页码,从1开始
        page_size: 每页数量 (1-100, 默认: 20)
        sort: 排序字段,格式: "field:asc" 或 "field:desc"
        filter: 过滤条件,JSON格式

    Returns:
        分页的项目列表
    """
    try:
        from src.models.schemas import PaginationParams
        from src.utils.pagination import Paginator

        # 创建分页参数
        pagination_params = PaginationParams(
            page=page,
            page_size=page_size,
            sort=sort,
            filter=filter
        )

        # 计算偏移量
        offset = pagination_params.get_offset()
        limit = pagination_params.get_limit()

        # 获取当前用户ID，只返回该用户的项目
        user_id = current_user.id if current_user else None

        # 获取项目列表（按用户过滤）
        projects = project_manager.list_projects(limit=limit, offset=offset, user_id=user_id)

        # 获取总数（按用户过滤）
        total = project_manager.count_projects(user_id=user_id)

        # 创建分页器
        paginator = Paginator(
            items=projects,
            total=total,
            page=page,
            page_size=page_size
        )

        # 返回分页响应
        return paginator.to_response(request)

    except Exception as e:
        raise AppException(
                message=str(e),
                code=ErrorCode.INTERNAL_ERROR,
                status_code=500
            )

@router.get("/projects/{project_id}", response_model=ResponseModel)
async def get_project(
    project_id: str,
    include_assets: bool = Query(default=True, description="Whether to include assets in the response"),
    include_referenced_assets: bool = Query(default=False, description="Whether to include only referenced assets (if include_assets is False)"),
    current_user: UserAuth = Depends(get_current_user)
):
    """Get project details"""
    project = project_manager.get_project(
        project_id,
        include_assets=include_assets,
        include_referenced_assets=include_referenced_assets,
        user_id=current_user.id
    )
    if not project:
        raise AppException(
                message="Project not found or access denied",
                code=ErrorCode.NOT_FOUND,
                status_code=404
            )
    return ResponseModel(data=project)

@router.put("/projects/{project_id}", response_model=ResponseModel)
async def update_project(
    project_id: str,
    request: UpdateProjectRequest,
    current_user: UserAuth = Depends(get_current_user)
):
    """Update a project"""
    try:
        # First check if project exists and belongs to user
        existing = project_manager.get_project(project_id, user_id=current_user.id)
        if not existing:
            raise AppException(
                message="Project not found or access denied",
                code=ErrorCode.NOT_FOUND,
                status_code=404
            )

        update_data = request.model_dump(exclude_unset=True)
        updated_project = project_manager.update_project(project_id, update_data)
        if not updated_project:
            raise AppException(
                message="Project not found",
                code=ErrorCode.NOT_FOUND,
                status_code=404
            )
        return ResponseModel(data=updated_project)
    except Exception as e:
        raise AppException(
                message=str(e),
                code=ErrorCode.INTERNAL_ERROR,
                status_code=500
            )

@router.delete("/projects/{project_id}", response_model=ResponseModel)
async def delete_project(
    project_id: str,
    current_user: UserAuth = Depends(get_current_user)
):
    """Delete a project"""
    try:
        # First check if project exists and belongs to user
        existing = project_manager.get_project(project_id, user_id=current_user.id)
        if not existing:
            raise AppException(
                message="Project not found or access denied",
                code=ErrorCode.NOT_FOUND,
                status_code=404
            )

        project_manager.delete_project(project_id)
        return ResponseModel(data={"id": project_id, "deleted": True})
    except Exception as e:
        raise AppException(
                message=str(e),
                code=ErrorCode.INTERNAL_ERROR,
                status_code=500
            )


@router.post("/projects/{project_id}/convert-to-canvas", response_model=ResponseModel)
async def convert_project_to_canvas(
    project_id: str,
    background_tasks: BackgroundTasks,
    current_user: UserAuth = Depends(get_current_user)
):
    """将剧本项目转换为独立的画布项目。"""
    try:
        source_project = project_manager.get_project(project_id, user_id=current_user.id)
        if not source_project:
            raise AppException(
                message="Project not found or access denied",
                code=ErrorCode.NOT_FOUND,
                status_code=404
            )
        if source_project.type != "script":
            raise AppException(
                message="Only script projects can be converted to canvas projects",
                code=ErrorCode.INVALID_PARAMETER,
                status_code=400
            )

        chapters = [
            {
                "id": episode.id,
                "title": episode.title,
                "order": episode.order,
                "content": episode.content,
                "summary": episode.desc,
                "status": episode.status,
            }
            for episode in (source_project.episodes or [])
        ]

        target_project = project_manager.create_project(
            name=f"{source_project.name} - 画布",
            description="正在从剧本项目生成画布...",
            type="canvas",
            chapters=chapters,
            assets=[],
            status="initializing",
            user_id=current_user.id
        )
        progress_cb = _progress_callback(target_project.id)
        background_tasks.add_task(
            convert_script_project_to_canvas,
            source_project.id,
            target_project.id,
            progress_cb,
            current_user.id,
        )
        return ResponseModel(data=target_project)
    except AppException:
        raise
    except Exception as e:
        logger.error("Error converting project to canvas: %s", e, exc_info=True)
        raise AppException(
                message=str(e),
                code=ErrorCode.INTERNAL_ERROR,
                status_code=500
            )
