"""
OSS 上传路由

流程（对用户透明，由 SDK 自动完成）：
1. SDK 调用 POST /api/oss-upload/init      → 获取 OSS 凭证
2. SDK 通过 oss2 上传文件到 OSS
3. SDK 调用 POST /api/oss-upload/complete   → 通知服务器记录上传完成
4. SDK 查询 GET  /api/oss-upload/status/:id → 确认完成状态
"""
import logging
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from sqlalchemy.orm import Session

from token_middleware import get_current_user
from token_auth import AuthenticatedUser
from database import get_db
from database_oss import OSSUploadTask
from oss_service import oss_upload_service

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/oss-upload", tags=["OSS 上传"])


# ---------- 请求模型 ----------

class OSSInitRequest(BaseModel):
    dataset_id: str = Field(..., description="数据集ID")
    file_name: str = Field(..., description="目标文件名")


class OSSCompleteRequest(BaseModel):
    task_id: int = Field(..., description="任务ID")


# ---------- 接口 ----------

@router.post("/init", summary="初始化 OSS 上传，获取临时凭证")
async def oss_upload_init(
    request: OSSInitRequest,
    current_user: AuthenticatedUser = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """返回 OSS 凭证，SDK 用此凭证通过 oss2 上传文件到 OSS。"""
    try:
        credentials = oss_upload_service.get_credentials(
            request.dataset_id, request.file_name
        )

        task = OSSUploadTask(
            user_id=current_user.user_id,
            user_name=current_user.user_name,
            token_hash=current_user.token_hash,
            dataset_id=request.dataset_id,
            file_name=request.file_name,
            oss_key=credentials["oss_key"],
            status="pending"
        )
        db.add(task)
        db.commit()
        db.refresh(task)

        return {
            "code": 200,
            "message": "OSS 上传初始化成功",
            "data": {
                "task_id": task.id,
                "credentials": credentials,
            }
        }

    except Exception as e:
        logger.error(f"OSS 上传初始化失败: {e}")
        raise HTTPException(status_code=500, detail=f"初始化失败: {e}")


@router.post("/complete", summary="通知 OSS 上传完成")
async def oss_upload_complete(
    request: OSSCompleteRequest,
    current_user: AuthenticatedUser = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """SDK 上传到 OSS 完成后调用，服务器验证文件存在并记录上传完成。"""
    task = db.query(OSSUploadTask).filter(
        OSSUploadTask.id == request.task_id,
        OSSUploadTask.user_id == current_user.user_id
    ).first()

    if not task:
        raise HTTPException(status_code=404, detail="任务不存在")

    if task.status not in ("pending", "failed"):
        return {"code": 400, "message": f"任务状态为 {task.status}，无法重新触发"}

    # 验证 OSS 文件存在
    file_size = oss_upload_service.verify_oss_file(task.dataset_id, task.file_name)
    if file_size is None:
        raise HTTPException(
            status_code=400,
            detail=f"OSS 上未找到文件 {task.oss_key}，请确认上传已完成"
        )

    # 文件已在 OSS 上，直接标记完成并记录
    oss_upload_service.complete_upload(
        task_id=task.id,
        dataset_id=task.dataset_id,
        file_name=task.file_name,
        file_size=file_size,
        user_id=current_user.user_id,
        user_name=current_user.user_name,
        token_hash=current_user.token_hash
    )

    oss_key = oss_upload_service.get_oss_key(task.dataset_id, task.file_name)
    oss_path = f"oss://{oss_upload_service.bucket.bucket_name}/{oss_key}"

    return {
        "code": 200,
        "message": "上传完成",
        "data": {
            "task_id": task.id,
            "file_size": file_size,
            "file_path": oss_path,
            "status": "completed"
        }
    }


@router.get("/status/{task_id}", summary="查询 OSS 上传任务状态")
async def oss_upload_status(
    task_id: int,
    current_user: AuthenticatedUser = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """查询 OSS 上传任务状态。"""
    task = db.query(OSSUploadTask).filter(
        OSSUploadTask.id == task_id,
        OSSUploadTask.user_id == current_user.user_id
    ).first()

    if not task:
        raise HTTPException(status_code=404, detail="任务不存在")

    return {
        "code": 200,
        "message": "查询成功",
        "data": task.to_dict()
    }
