"""
Admin API - Tasks Routes

包含任务管理相关的 API 路由。
"""

import logging
from typing import Optional, List

from fastapi import APIRouter, Depends, Query, Request

from src.auth.dependencies import require_admin
from src.auth.models import UserAuth
from src.models.schemas import ResponseModel
from src.models.admin_schemas import SystemSettingUpdateRequest
from src.services.admin_service import admin_service
from src.utils.pagination import Paginator
from src.utils.errors import ErrorCode, AppException

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/tasks", tags=["admin-tasks"])


@router.get("", response_model=ResponseModel)
async def list_tasks(
    request: Request,
    page: int = Query(1, ge=1, description="Page number, starting from 1"),
    page_size: int = Query(20, ge=1, le=100, description="Items per page"),
    sort: Optional[str] = Query(None, description="Sort field, format: field:asc or field:desc"),
    filter: Optional[str] = Query(None, description="Filter conditions, JSON format"),
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    List all tasks with pagination

    Supports filtering by status, type, provider, user_id, and project_id.
    Requires admin privileges.
    """
    try:
        # Parse filters
        filters = {}
        if filter:
            import json
            try:
                filters = json.loads(filter)
            except json.JSONDecodeError:
                pass

        # Parse sort
        sort_by = "created_at"
        sort_order = "desc"
        if sort:
            parts = sort.split(":")
            if len(parts) == 2:
                sort_by = parts[0]
                sort_order = parts[1]

        items, total = await admin_service.list_tasks(
            page=page,
            page_size=page_size,
            filters=filters if filters else None,
            sort_by=sort_by,
            sort_order=sort_order,
        )

        paginator = Paginator(
            items=[item.model_dump() for item in items],
            total=total,
            page=page,
            page_size=page_size,
        )

        return paginator.to_response(request)
    except Exception as e:
        logger.error(f"Error listing tasks: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )


@router.get("/stats", response_model=ResponseModel)
async def get_task_stats(
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    Get task statistics

    Returns counts by status, type, provider, and success rate.
    Requires admin privileges.
    """
    try:
        stats = await admin_service.get_task_stats()
        return ResponseModel(data=stats.model_dump())
    except Exception as e:
        logger.error(f"Error getting task stats: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )


@router.get("/queue", response_model=ResponseModel)
async def get_task_queue_status(
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    Get task queue status

    Returns queue length, processing count, and worker status.
    Requires admin privileges.
    """
    try:
        status = await admin_service.get_task_queue_status()
        return ResponseModel(data=status.model_dump())
    except Exception as e:
        logger.error(f"Error getting task queue status: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )


@router.get("/{task_id}", response_model=ResponseModel)
async def get_task_detail(
    task_id: str,
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    Get task detail by ID

    Returns detailed task information including user and project details.
    Requires admin privileges.
    """
    try:
        task = await admin_service.get_task_detail(task_id)
        if not task:
            raise AppException(
                code=ErrorCode.NOT_FOUND,
                message="Task not found",
                status_code=404
            )
        return ResponseModel(data=task.model_dump())
    except AppException:
        raise
    except Exception as e:
        logger.error(f"Error getting task detail: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )


@router.post("/{task_id}/retry", response_model=ResponseModel)
async def retry_task(
    task_id: str,
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    Retry a failed task

    Requires admin privileges.
    """
    try:
        task = await admin_service.retry_task(task_id)
        if not task:
            raise AppException(
                code=ErrorCode.NOT_FOUND,
                message="Task not found or cannot be retried",
                status_code=404
            )

        return ResponseModel(
            data={
                "id": task_id,
                "status": task.status,
                "message": "Task queued for retry",
                "retry_count": task.retry_count,
            }
        )
    except AppException:
        raise
    except Exception as e:
        logger.error(f"Error retrying task: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )


@router.delete("/{task_id}", response_model=ResponseModel)
async def delete_task(
    task_id: str,
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    Delete a task

    Requires admin privileges.
    """
    try:
        success = await admin_service.delete_task(task_id)
        if not success:
            raise AppException(
                code=ErrorCode.NOT_FOUND,
                message="Task not found",
                status_code=404
            )

        return ResponseModel(
            data={
                "id": task_id,
                "deleted": True,
                "message": "Task deleted successfully",
            }
        )
    except AppException:
        raise
    except Exception as e:
        logger.error(f"Error deleting task: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )


@router.post("/batch-retry", response_model=ResponseModel)
async def batch_retry_tasks(
    task_ids: List[str],
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    Batch retry failed tasks

    Requires admin privileges.
    """
    try:
        from sqlmodel import Session, select
        from src.config.database import engine
        from src.models.entities import TaskDB
        from datetime import datetime

        retried = []
        failed = []

        with Session(engine) as session:
            for task_id in task_ids:
                task = session.get(TaskDB, task_id)
                if not task:
                    failed.append({"id": task_id, "reason": "Task not found"})
                    continue

                if task.status not in ["failed", "timeout"]:
                    failed.append({"id": task_id, "reason": f"Cannot retry task with status: {task.status}"})
                    continue

                task.status = "pending"
                task.retry_count = 0
                task.error = None
                task.updated_at = datetime.now().timestamp()
                session.add(task)
                retried.append(task_id)

            session.commit()

        return ResponseModel(
            data={
                "retried": retried,
                "failed": failed,
                "total": len(task_ids),
                "success_count": len(retried),
                "message": f"Successfully queued {len(retried)} tasks for retry",
            }
        )
    except Exception as e:
        logger.error(f"Error batch retrying tasks: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )


@router.post("/batch-cancel", response_model=ResponseModel)
async def batch_cancel_tasks(
    task_ids: List[str],
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    Batch cancel pending/processing tasks

    Requires admin privileges.
    """
    try:
        from sqlmodel import Session, select
        from src.config.database import engine
        from src.models.entities import TaskDB
        from datetime import datetime

        cancelled = []
        failed = []

        with Session(engine) as session:
            for task_id in task_ids:
                task = session.get(TaskDB, task_id)
                if not task:
                    failed.append({"id": task_id, "reason": "Task not found"})
                    continue

                if task.status not in ["pending", "processing"]:
                    failed.append({"id": task_id, "reason": f"Cannot cancel task with status: {task.status}"})
                    continue

                task.status = "cancelled"
                task.updated_at = datetime.now().timestamp()
                session.add(task)
                cancelled.append(task_id)

            session.commit()

        return ResponseModel(
            data={
                "cancelled": cancelled,
                "failed": failed,
                "total": len(task_ids),
                "success_count": len(cancelled),
                "message": f"Successfully cancelled {len(cancelled)} tasks",
            }
        )
    except Exception as e:
        logger.error(f"Error batch cancelling tasks: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )


@router.post("/batch-delete", response_model=ResponseModel)
async def batch_delete_tasks(
    task_ids: List[str],
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    Batch delete tasks

    Requires admin privileges.
    """
    try:
        from sqlmodel import Session, select
        from src.config.database import engine
        from src.models.entities import TaskDB

        deleted = []
        failed = []

        with Session(engine) as session:
            for task_id in task_ids:
                task = session.get(TaskDB, task_id)
                if not task:
                    failed.append({"id": task_id, "reason": "Task not found"})
                    continue

                session.delete(task)
                deleted.append(task_id)

            session.commit()

        return ResponseModel(
            data={
                "deleted": deleted,
                "failed": failed,
                "total": len(task_ids),
                "success_count": len(deleted),
                "message": f"Successfully deleted {len(deleted)} tasks",
            }
        )
    except Exception as e:
        logger.error(f"Error batch deleting tasks: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )


@router.post("/cleanup-completed", response_model=ResponseModel)
async def cleanup_completed_tasks(
    days: int = Query(30, ge=1, le=365, description="清理多少天前的已完成任务"),
    current_user: UserAuth = Depends(require_admin),
) -> ResponseModel:
    """
    Cleanup completed tasks older than specified days

    Requires admin privileges.
    """
    try:
        from sqlmodel import Session, select
        from src.config.database import engine
        from src.models.entities import TaskDB
        import time
        from datetime import datetime

        cutoff_timestamp = time.time() - (days * 24 * 60 * 60)

        with Session(engine) as session:
            # Find completed tasks older than cutoff
            old_tasks = session.exec(
                select(TaskDB).where(
                    TaskDB.status == "success",
                    TaskDB.completed_at < cutoff_timestamp
                )
            ).all()

            deleted_count = 0
            for task in old_tasks:
                session.delete(task)
                deleted_count += 1

            session.commit()

        return ResponseModel(
            data={
                "deleted_count": deleted_count,
                "days": days,
                "cutoff_date": datetime.fromtimestamp(cutoff_timestamp).isoformat(),
                "message": f"Successfully deleted {deleted_count} completed tasks older than {days} days",
            }
        )
    except Exception as e:
        logger.error(f"Error cleaning up completed tasks: {e}")
        raise AppException(
            code=ErrorCode.INTERNAL_ERROR,
            message=str(e),
            status_code=500
        )
