"""查重 API 路由。"""

from __future__ import annotations

import logging
from typing import Any
from uuid import uuid4

from app.auth import AuthenticatedUser, get_current_user
from app.core.storage import OSSStorageService, get_storage_service
from app.dependencies import get_duplication_repository
from app.schemas.duplication import (
    DuplicateSegmentResponse,
    DuplicationDetailResponse,
    DuplicationRecordResponse,
    DuplicationUploadResponse,
)
from fastapi import APIRouter, Depends, File, HTTPException, Response, UploadFile, status

from packages.application import (
    DeleteDuplicationRecordUseCase,
    GetDuplicationDetailUseCase,
    ListDuplicationRecordsUseCase,
    RetryDuplicationUseCase,
    UploadForDuplicationCommand,
    UploadForDuplicationUseCase,
)
from packages.domain.duplication import DuplicationRecord

logger = logging.getLogger(__name__)

router = APIRouter()

# 查重功能只接受视频文件
ALLOWED_VIDEO_MIME_TYPES = frozenset(
    {
        "video/mp4",
        "video/mpeg",
        "video/quicktime",
        "video/x-msvideo",
        "video/webm",
        "video/x-matroska",
        "video/3gpp",
    }
)


def _validate_video_mime_type(content_type: str | None) -> str:
    """验证视频文件的 MIME 类型，如果无效则抛出异常。"""
    if not content_type:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Content-Type header is required",
        )

    # 处理带参数的类型，如 "video/mp4; charset=utf-8"
    base_type = content_type.split(";")[0].strip().lower()

    if base_type not in ALLOWED_VIDEO_MIME_TYPES:
        raise HTTPException(
            status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
            detail="只支持视频文件。支持的类型: mp4, mpeg, mov, avi, webm, mkv, 3gp",
        )

    return base_type


def _to_record_response(record: DuplicationRecord) -> DuplicationRecordResponse:
    return DuplicationRecordResponse(
        id=record.id,
        filename=record.filename,
        file_size=record.file_size,
        duration_seconds=record.duration_seconds,
        status=record.status,
        duplicate_rate=record.duplicate_rate,
        duplicate_count=record.duplicate_count,
        created_at=record.created_at.isoformat(),
        updated_at=record.updated_at.isoformat(),
    )


def _to_detail_response(record: DuplicationRecord) -> DuplicationDetailResponse:
    return DuplicationDetailResponse(
        id=record.id,
        filename=record.filename,
        file_size=record.file_size,
        duration_seconds=record.duration_seconds,
        status=record.status,
        duplicate_rate=record.duplicate_rate,
        duplicate_count=record.duplicate_count,
        created_at=record.created_at.isoformat(),
        updated_at=record.updated_at.isoformat(),
        segments=[
            DuplicateSegmentResponse(
                id=seg.id,
                source_start=seg.source_start,
                source_end=seg.source_end,
                matched_video_id=seg.matched_video_id,
                matched_video_name=seg.matched_video_name,
                matched_start=seg.matched_start,
                matched_end=seg.matched_end,
                similarity=seg.similarity,
            )
            for seg in record.segments
        ],
    )


@router.post("/upload", response_model=DuplicationUploadResponse)
async def upload_for_duplication(
    file: UploadFile = File(..., description="要查重的视频文件"),
    authenticated_user: AuthenticatedUser = Depends(get_current_user),
    duplication_repository: Any = Depends(get_duplication_repository),
    storage_service: OSSStorageService = Depends(get_storage_service),
) -> DuplicationUploadResponse:
    """上传视频进行查重。"""
    if file.filename is None:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="文件名不能为空",
        )

    # P0-1: 验证 MIME 类型（只接受视频文件）
    validated_content_type = _validate_video_mime_type(file.content_type)

    # P0-2: 验证文件大小（参考 OSS_DIRECT_UPLOAD_MAX_MB）
    from app.config import get_settings

    settings = get_settings()
    max_size_bytes = settings.OSS_DIRECT_UPLOAD_MAX_MB * 1024 * 1024

    # 先检查 Content-Length header（如果可用）
    if file.size is not None and file.size > max_size_bytes:
        raise HTTPException(
            status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
            detail=f"文件超过上传限制 ({settings.OSS_DIRECT_UPLOAD_MAX_MB}MB)",
        )

    # 读取文件内容并上传到 OSS
    file_id = uuid4().hex[:8]
    safe_filename = file.filename.replace("/", "_").replace("\\", "_")
    storage_key = f"duplication/{file_id}/{safe_filename}"

    try:
        content = await file.read()
        file_size = len(content)

        # 再次检查实际文件大小
        if file_size > max_size_bytes:
            raise HTTPException(
                status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
                detail=f"文件超过上传限制 ({settings.OSS_DIRECT_UPLOAD_MAX_MB}MB)",
            )
    except HTTPException:
        raise
    except Exception as exc:
        logger.error("读取查重文件失败: %s", exc, exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="文件读取失败，请稍后重试",
        ) from exc

    try:
        storage_service.upload_file(
            content,
            storage_key,
            content_type=validated_content_type,
        )
    except Exception as exc:
        logger.error("查重文件上传 OSS 失败: %s", exc, exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            detail="文件上传失败，请稍后重试",
        ) from exc

    use_case = UploadForDuplicationUseCase(duplication_repository)
    record = use_case.execute(
        UploadForDuplicationCommand(
            user_id=authenticated_user.user.id,
            filename=file.filename,
            file_size=file_size,
            storage_key=storage_key,
        )
    )

    logger.info(
        "Duplication upload: record=%s file=%s user=%s",
        record.id,
        file.filename,
        authenticated_user.user.id,
    )

    return DuplicationUploadResponse(
        id=record.id,
        status=record.status,
        message=f'文件 "{file.filename}" 已上传，正在查重中...',
    )


@router.get("/records", response_model=list[DuplicationRecordResponse])
def list_duplication_records(
    authenticated_user: AuthenticatedUser = Depends(get_current_user),
    duplication_repository: Any = Depends(get_duplication_repository),
) -> list[DuplicationRecordResponse]:
    """获取当前用户的查重记录列表。"""
    use_case = ListDuplicationRecordsUseCase(duplication_repository)
    records = use_case.execute(authenticated_user.user.id)
    return [_to_record_response(r) for r in records]


@router.get("/records/{record_id}", response_model=DuplicationDetailResponse)
def get_duplication_detail(
    record_id: str,
    authenticated_user: AuthenticatedUser = Depends(get_current_user),
    duplication_repository: Any = Depends(get_duplication_repository),
) -> DuplicationDetailResponse:
    """获取查重记录详情（含重复片段）。"""
    use_case = GetDuplicationDetailUseCase(duplication_repository)
    record = use_case.execute(record_id)
    if record is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"查重记录 {record_id} 不存在",
        )
    if record.user_id != authenticated_user.user.id:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"查重记录 {record_id} 不存在",
        )
    return _to_detail_response(record)


@router.delete("/records/{record_id}", status_code=status.HTTP_204_NO_CONTENT, response_class=Response)
def delete_duplication_record(
    record_id: str,
    authenticated_user: AuthenticatedUser = Depends(get_current_user),
    duplication_repository: Any = Depends(get_duplication_repository),
) -> Response:
    """删除查重记录。"""
    # 检查记录是否存在且属于当前用户
    detail_uc = GetDuplicationDetailUseCase(duplication_repository)
    record = detail_uc.execute(record_id)
    if record is None or record.user_id != authenticated_user.user.id:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"查重记录 {record_id} 不存在",
        )

    use_case = DeleteDuplicationRecordUseCase(duplication_repository)
    use_case.execute(record_id)
    return Response(status_code=204)


@router.post("/records/{record_id}/retry", response_model=DuplicationUploadResponse)
def retry_duplication(
    record_id: str,
    authenticated_user: AuthenticatedUser = Depends(get_current_user),
    duplication_repository: Any = Depends(get_duplication_repository),
) -> DuplicationUploadResponse:
    """重新提交查重。"""
    # 检查记录存在且属于当前用户
    detail_uc = GetDuplicationDetailUseCase(duplication_repository)
    record = detail_uc.execute(record_id)
    if record is None or record.user_id != authenticated_user.user.id:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"查重记录 {record_id} 不存在",
        )

    use_case = RetryDuplicationUseCase(duplication_repository)
    updated = use_case.execute(record_id)
    if updated is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"查重记录 {record_id} 不存在",
        )

    return DuplicationUploadResponse(
        id=updated.id,
        status=updated.status,
        message="已重新提交查重",
    )
