"""
文件管理API路由
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Query, UploadFile, File, Form
from fastapi.responses import FileResponse, StreamingResponse
from sqlalchemy.orm import Session

from app.core.deps import get_db, get_current_user
from app.schemas.file_management import (
    UploadedFileCreate,
    UploadedFileUpdate,
    UploadedFileResponse,
    UploadedFileWithUrl,
    FileUploadResponse,
    FileShareCreate,
    FileShareResponse,
    FileBatchDelete,
    FileStatistics,
    ChunkUploadInit,
    ChunkUploadInfo,
    ChunkUploadComplete
)
from app.crud.file_management import uploaded_file
from app.services.file_service import file_service, chunk_upload_manager

router = APIRouter()


@router.post("/upload", response_model=FileUploadResponse)
async def upload_file(
    file: UploadFile = File(..., description="上传的文件"),
    remark: Optional[str] = Form(None, description="备注"),
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    上传文件

    - **file**: 上传的文件
    - **remark**: 备注

    支持的文件类型:
    - 图片: JPEG, PNG, GIF, BMP, WebP, SVG
    - 文档: PDF, Word, Excel, PowerPoint, TXT, CSV
    - 压缩包: ZIP, RAR, 7Z

    文件大小限制:
    - 图片: 最大10MB
    - 其他: 最大100MB
    """
    # 上传文件
    file_obj = await file_service.upload_file(
        db=db,
        file=file,
        uploader_id=current_user.id,
        remark=remark
    )

    # 生成访问URL
    base_url = "http://localhost:8000"  # TODO: 从配置读取
    download_url = f"{base_url}/api/v1/files/{file_obj.id}/download"
    preview_url = None
    if file_obj.file_type and file_obj.file_type.startswith('image/'):
        preview_url = f"{base_url}/api/v1/files/{file_obj.id}/preview"

    return FileUploadResponse(
        id=file_obj.id,
        file_name=file_obj.file_name,
        original_name=file_obj.original_name,
        file_size=file_obj.file_size,
        file_type=file_obj.file_type,
        file_path=file_obj.file_path,
        download_url=download_url,
        preview_url=preview_url,
        message="上传成功"
    )


@router.get("/", response_model=List[UploadedFileResponse])
def get_files(
    skip: int = Query(0, ge=0, description="跳过条数"),
    limit: int = Query(20, ge=1, le=100, description="返回条数"),
    keyword: Optional[str] = Query(None, description="搜索关键词"),
    file_type: Optional[str] = Query(None, description="文件类型"),
    uploader_id: Optional[int] = Query(None, description="上传者ID"),
    start_date: Optional[str] = Query(None, description="开始日期(YYYY-MM-DD)"),
    end_date: Optional[str] = Query(None, description="结束日期(YYYY-MM-DD)"),
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    获取文件列表

    - **skip**: 跳过条数
    - **limit**: 返回条数（最大100）
    - **keyword**: 搜索关键词（文件名）
    - **file_type**: 文件类型筛选
    - **uploader_id**: 上传者ID筛选
    - **start_date**: 开始日期
    - **end_date**: 结束日期
    """
    items, total = uploaded_file.get_multi(
        db,
        skip=skip,
        limit=limit,
        keyword=keyword,
        file_type=file_type,
        uploader_id=uploader_id,
        start_date=start_date,
        end_date=end_date
    )

    # 添加上传者姓名
    result = []
    for item in items:
        item_dict = UploadedFileResponse.from_orm(item).dict()
        if item.uploader:
            item_dict['uploader_name'] = item.uploader.real_name
        result.append(UploadedFileResponse(**item_dict))

    return result


@router.get("/statistics", response_model=FileStatistics)
def get_file_statistics(
    uploader_id: Optional[int] = Query(None, description="上传者ID筛选"),
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    获取文件统计信息

    - **uploader_id**: 上传者ID筛选

    返回文件总数、总大小、类型分布等统计信息
    """
    return file_service.get_statistics(db, uploader_id=uploader_id)


@router.get("/{file_id}", response_model=UploadedFileWithUrl)
def get_file(
    file_id: int,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    获取文件详情

    - **file_id**: 文件ID

    返回文件详情及访问URL
    """
    file_obj = uploaded_file.get(db, file_id)
    if not file_obj:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文件不存在"
        )

    # 生成访问URL
    base_url = "http://localhost:8000"
    file_dict = UploadedFileWithUrl.from_orm(file_obj).dict()
    file_dict['download_url'] = f"{base_url}/api/v1/files/{file_id}/download"

    if file_obj.file_type and file_obj.file_type.startswith('image/'):
        file_dict['preview_url'] = f"{base_url}/api/v1/files/{file_id}/preview"

    if file_obj.share_code:
        file_dict['share_url'] = f"{base_url}/api/v1/files/share/{file_obj.share_code}"

    return UploadedFileWithUrl(**file_dict)


@router.get("/{file_id}/download")
def download_file(
    file_id: int,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    下载文件

    - **file_id**: 文件ID

    返回文件流
    """
    file_obj = uploaded_file.get(db, file_id)
    if not file_obj:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文件不存在"
        )

    # 检查文件是否存在
    if not file_service.file_exists(file_obj):
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文件已被删除或移动"
        )

    # 增加下载次数
    uploaded_file.increment_download_count(db, file_id=file_id)

    # 返回文件
    file_path = file_service.get_file_path(file_obj)
    return FileResponse(
        path=str(file_path),
        filename=file_obj.original_name,
        media_type=file_obj.file_type
    )


@router.get("/{file_id}/preview")
def preview_file(
    file_id: int,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    预览文件

    - **file_id**: 文件ID

    支持图片直接预览，其他文件类型可能需要转换为预览格式
    """
    file_obj = uploaded_file.get(db, file_id)
    if not file_obj:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文件不存在"
        )

    # 检查文件是否存在
    if not file_service.file_exists(file_obj):
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文件已被删除或移动"
        )

    # 检查文件类型是否支持预览
    if not file_obj.file_type or not file_obj.file_type.startswith('image/'):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="该文件类型不支持在线预览"
        )

    # 返回缩略图（如果存在）
    if file_obj.thumbnail_path:
        thumbnail_path = file_obj.thumbnail_path
        if Path(thumbnail_path).exists():
            return FileResponse(
                path=thumbnail_path,
                media_type="image/jpeg"
            )

    # 返回原图
    file_path = file_service.get_file_path(file_obj)
    return FileResponse(
        path=str(file_path),
        media_type=file_obj.file_type
    )


@router.put("/{file_id}", response_model=UploadedFileResponse)
def update_file(
    file_id: int,
    obj_in: UploadedFileUpdate,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    更新文件信息

    - **file_id**: 文件ID
    - **remark**: 备注
    """
    file_obj = uploaded_file.get(db, file_id)
    if not file_obj:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文件不存在"
        )

    # 检查权限：只有上传者可以更新
    if file_obj.uploader_id != current_user.id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权限修改此文件"
        )

    # 更新文件
    file_obj = uploaded_file.update(
        db,
        db_obj=file_obj,
        obj_in=obj_in.dict(exclude_unset=True)
    )

    return UploadedFileResponse.from_orm(file_obj)


@router.delete("/{file_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_file(
    file_id: int,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    删除文件

    - **file_id**: 文件ID

    软删除文件记录和物理删除文件
    """
    file_obj = uploaded_file.get(db, file_id)
    if not file_obj:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文件不存在"
        )

    # 检查权限：只有上传者可以删除
    if file_obj.uploader_id != current_user.id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权限删除此文件"
        )

    # 软删除数据库记录
    uploaded_file.delete(db, db_obj=file_obj, deleter_id=current_user.id)

    # 从磁盘删除文件
    file_service.delete_file_from_disk(file_obj)

    return None


@router.delete("/batch", status_code=status.HTTP_204_NO_CONTENT)
def delete_files_batch(
    obj_in: FileBatchDelete,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    批量删除文件

    - **file_ids**: 文件ID列表

    批量软删除文件记录和物理删除文件
    """
    # 软删除数据库记录
    count = uploaded_file.delete_batch(
        db,
        file_ids=obj_in.file_ids,
        deleter_id=current_user.id
    )

    # 从磁盘删除文件
    for file_id in obj_in.file_ids:
        file_obj = uploaded_file.get(db, file_id)
        if file_obj and file_obj.uploader_id == current_user.id:
            file_service.delete_file_from_disk(file_obj)

    return None


@router.post("/{file_id}/share", response_model=FileShareResponse)
def create_share_link(
    file_id: int,
    share_in: FileShareCreate = FileShareCreate(),
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    生成分享链接

    - **file_id**: 文件ID
    - **expire_days**: 有效期（天），默认7天，最大30天

    生成用于文件分享的临时链接
    """
    file_obj = uploaded_file.get(db, file_id)
    if not file_obj:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文件不存在"
        )

    # 检查权限：只有上传者可以分享
    if file_obj.uploader_id != current_user.id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权限分享此文件"
        )

    # 生成分享链接
    base_url = "http://localhost:8000"
    return file_service.generate_share_link(
        db,
        file_id=file_id,
        expire_days=share_in.expire_days,
        base_url=base_url
    )


@router.get("/share/{share_code}")
def access_shared_file(
    share_code: str,
    db: Session = Depends(get_db)
):
    """
    访问分享的文件

    - **share_code**: 分享码

    通过分享码访问文件（无需登录）
    """
    file_obj = file_service.get_shared_file(db, share_code)
    if not file_obj:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="分享链接不存在或已过期"
        )

    # 检查文件是否存在
    if not file_service.file_exists(file_obj):
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文件已被删除或移动"
        )

    # 增加下载次数
    uploaded_file.increment_download_count(db, file_id=file_obj.id)

    # 返回文件
    file_path = file_service.get_file_path(file_obj)
    return FileResponse(
        path=str(file_path),
        filename=file_obj.original_name,
        media_type=file_obj.file_type
    )


# ===== 分片上传 =====

@router.post("/chunks/init")
def init_chunk_upload(
    obj_in: ChunkUploadInit,
    current_user = Depends(get_current_user)
):
    """
    初始化分片上传

    - **file_name**: 文件名
    - **file_size**: 文件大小（字节）
    - **file_type**: 文件类型
    - **total_chunks**: 总分片数
    - **file_hash**: 文件哈希（可选）

    返回上传ID，用于后续上传分片
    """
    upload_id = chunk_upload_manager.init_upload(
        file_name=obj_in.file_name,
        file_size=obj_in.file_size,
        file_type=obj_in.file_type,
        total_chunks=obj_in.total_chunks,
        file_hash=obj_in.file_hash
    )

    return {"upload_id": upload_id, "message": "初始化成功"}


@router.post("/chunks/upload")
async def upload_chunk(
    upload_id: str,
    chunk_index: int,
    chunk: UploadFile = File(..., description="分片文件"),
    current_user = Depends(get_current_user)
):
    """
    上传分片

    - **upload_id**: 上传ID
    - **chunk_index**: 分片索引（从0开始）
    - **chunk**: 分片文件
    """
    content = await chunk.read()
    success = chunk_upload_manager.save_chunk(upload_id, chunk_index, content)

    if not success:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="上传会话不存在"
        )

    return {"message": f"分片 {chunk_index} 上传成功"}


@router.post("/chunks/complete", response_model=FileUploadResponse)
def complete_chunk_upload(
    obj_in: ChunkUploadComplete,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """
    完成分片上传

    - **upload_id**: 上传ID
    - **file_name**: 文件名
    - **file_hash**: 文件哈希（可选）

    合并所有分片并创建文件记录
    """
    # 合并分片
    try:
        file_obj = chunk_upload_manager.merge_chunks(
            db=db,
            upload_id=obj_in.upload_id,
            uploader_id=current_user.id,
            file_service=file_service
        )
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"合并分片失败: {str(e)}"
        )

    # 生成访问URL
    base_url = "http://localhost:8000"
    download_url = f"{base_url}/api/v1/files/{file_obj.id}/download"
    preview_url = None
    if file_obj.file_type and file_obj.file_type.startswith('image/'):
        preview_url = f"{base_url}/api/v1/files/{file_obj.id}/preview"

    return FileUploadResponse(
        id=file_obj.id,
        file_name=file_obj.file_name,
        original_name=file_obj.original_name,
        file_size=file_obj.file_size,
        file_type=file_obj.file_type,
        file_path=file_obj.file_path,
        download_url=download_url,
        preview_url=preview_url,
        message="上传成功"
    )
