"""
聊天檔案管理 API
模擬 Node.js AVA File Service 的 /chat/* 端點
"""

import re
import logging
from pathlib import Path
from typing import Optional

from fastapi import APIRouter, File, Form, UploadFile, HTTPException
from fastapi.responses import FileResponse, JSONResponse

from ..config import MockConfig

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/chat", tags=["Chat Files"])


def sanitize_filename(filename: str) -> str:
    """清理檔名中的危險字元（與 Node.js 版本一致）"""
    return re.sub(r'[/\\?%*:|"<>]', "_", filename)


@router.post("/upload")
async def upload_chat_file(
    file: UploadFile = File(...),
    userId: str = Form(...),
    conversationId: str = Form(...)
):
    """
    上傳聊天檔案
    
    對應 Node.js 端點: POST /chat/upload
    """
    try:
        # 確保儲存目錄存在
        storage_dir = MockConfig.ensure_storage_dirs()
        
        # 清理檔名
        safe_filename = sanitize_filename(file.filename or "unnamed_file")
        
        # 建立目標目錄
        target_dir = storage_dir / "chat" / userId / conversationId
        target_dir.mkdir(parents=True, exist_ok=True)
        
        # 儲存檔案
        target_path = target_dir / safe_filename
        
        content = await file.read()
        
        # 檢查檔案大小
        if len(content) > MockConfig.MAX_FILE_SIZE:
            return JSONResponse(
                status_code=400,
                content={"success": False, "error": "File size exceeds 1GB limit"}
            )
        
        with open(target_path, "wb") as f:
            f.write(content)
        
        # 回傳路徑格式與 Node.js 版本一致
        file_path = f"chat/download/{userId}/{conversationId}/{safe_filename}"
        
        logger.info(f"File uploaded: {file_path}")
        
        return {
            "success": True,
            "files": {
                safe_filename: {
                    "status": True,
                    "msg": "File uploaded successfully",
                    "path": file_path
                }
            }
        }
        
    except Exception as e:
        logger.error(f"Upload error: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={"success": False, "error": str(e)}
        )


@router.get("/download/{userId}/{conversationId}/{filename}")
async def download_chat_file(
    userId: str,
    conversationId: str,
    filename: str,
    preview: Optional[bool] = False
):
    """
    下載聊天檔案
    
    對應 Node.js 端點: GET /chat/download/:userId/:conversationId/:filename
    """
    try:
        storage_dir = MockConfig.ensure_storage_dirs()
        
        # 清理檔名防止路徑注入
        safe_filename = sanitize_filename(filename)
        
        # 建立檔案路徑
        file_path = storage_dir / "chat" / userId / conversationId / safe_filename
        
        # 安全性檢查：確保路徑在允許的目錄內
        try:
            file_path = file_path.resolve()
            storage_dir_resolved = storage_dir.resolve()
            if not str(file_path).startswith(str(storage_dir_resolved)):
                raise HTTPException(
                    status_code=400,
                    detail="Invalid path. Potential directory traversal attack detected."
                )
        except Exception:
            raise HTTPException(status_code=400, detail="Invalid path")
        
        # 檢查檔案是否存在
        if not file_path.exists():
            raise HTTPException(status_code=404, detail="File not found")
        
        # 決定 Content-Disposition
        if preview and safe_filename.lower().endswith(".pdf"):
            media_type = "application/pdf"
            disposition = "inline"
        else:
            media_type = "application/octet-stream"
            disposition = "attachment"
        
        logger.info(f"File download: {file_path}")
        
        return FileResponse(
            path=file_path,
            filename=safe_filename,
            media_type=media_type,
            headers={"Content-Disposition": f'{disposition}; filename="{safe_filename}"'}
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Download error: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/files/{userId}/{conversationId}")
async def list_chat_files(userId: str, conversationId: str):
    """
    列出聊天檔案
    
    對應 Node.js 端點: GET /chat/files/:userId/:conversationId
    """
    try:
        storage_dir = MockConfig.ensure_storage_dirs()
        target_dir = storage_dir / "chat" / userId / conversationId
        
        if not target_dir.exists():
            return {"success": True, "files": []}
        
        files = []
        for f in target_dir.iterdir():
            if f.is_file():
                stat = f.stat()
                files.append({
                    "name": f.name,
                    "size": stat.st_size,
                    "created": stat.st_ctime,
                    "modified": stat.st_mtime
                })
        
        return {"success": True, "files": files}
        
    except Exception as e:
        logger.error(f"List files error: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={"success": False, "error": str(e)}
        )


@router.delete("/files/{userId}/{conversationId}")
async def delete_chat_files(userId: str, conversationId: str):
    """
    刪除聊天檔案
    
    對應 Node.js 端點: DELETE /chat/files/:userId/:conversationId
    """
    try:
        storage_dir = MockConfig.ensure_storage_dirs()
        target_dir = storage_dir / "chat" / userId / conversationId
        
        if not target_dir.exists():
            return {"success": True, "message": "Directory not found, nothing to delete"}
        
        # 刪除目錄中的所有檔案
        deleted_count = 0
        for f in target_dir.iterdir():
            if f.is_file():
                f.unlink()
                deleted_count += 1
        
        # 嘗試刪除空目錄
        try:
            target_dir.rmdir()
        except OSError:
            pass  # 目錄不為空或其他原因
        
        logger.info(f"Deleted {deleted_count} files from {target_dir}")
        
        return {"success": True, "deleted_count": deleted_count}
        
    except Exception as e:
        logger.error(f"Delete files error: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={"success": False, "error": str(e)}
        )
