import logging
from typing import Optional
from fastapi import APIRouter, Query, Response
from fastapi.responses import StreamingResponse
import httpx
from src.models.schemas import ResponseModel
from src.services.storage_service import storage_manager
from src.utils.errors import InvalidParameterException, StorageException

router = APIRouter(prefix="/storage", tags=["Storage"])
logger = logging.getLogger(__name__)

@router.delete("/files", response_model=ResponseModel)
async def delete_file(path: str = Query(..., description="File path or URL to delete")):
    """ 删除 a file from storage.
    
    Raises:
        InvalidParameterException: Path is invalid
        StorageException: Failed to delete file
    """
    # 参数 validation
    if not path or not path.strip():
        raise InvalidParameterException("path", "File path cannot be empty")

    # Blob URLs are client-side only, nothing to delete on server
    if path.startswith('blob:'):
        return ResponseModel(data={"deleted": True, "path": path})

    try:
        # 提取 key from URL if needed
        key = path
        if path.startswith(('http://', 'https://')):
            from urllib.parse import urlparse
            parsed = urlparse(path)
            key = parsed.path.lstrip('/')
            
        # Handle local storage prefix /files/ 
        if key.startswith('files/'):
            key = key[6:]
            
        success = storage_manager.delete(key)
        if success:
            return ResponseModel(data={"deleted": True, "path": key})
        else:
            # File doesn't exist or deletion failed
            raise StorageException("delete", "File not found or deletion failed")
            
    except StorageException:
        raise
    except Exception as e:
        logger.error(f"Failed to delete file {path}: {e}", exc_info=True)
        raise StorageException("delete", str(e))


@router.get("/download")
async def download_file(url: str = Query(..., description="Original or signed media URL"),
                        filename: Optional[str] = Query(None, description="Optional download filename")):
    """
    专用下载接口：
    - 后端代理拉取远端资源
    - 设置 Content-Disposition=attachment，避免浏览器直接在当前页打开视频/音频
    """
    if not url or not url.strip():
        raise InvalidParameterException("url", "Download url cannot be empty")

    # 如果是 OSS 原始地址，可以在这里重新签名（视业务需要）
    try:
        signed_url = storage_manager.sign_url(url) or url
    except Exception:
        # 签名失败时退回原始 URL
        signed_url = url

    try:
        client_timeout = httpx.Timeout(60.0)
        async with httpx.AsyncClient(timeout=client_timeout, follow_redirects=True) as client:
            upstream = await client.get(signed_url)
            upstream.raise_for_status()

            # 透传部分头部（例如 Content-Type）
            content_type = upstream.headers.get("content-type", "application/octet-stream")
            content_length = upstream.headers.get("content-length")

            # 下载文件名：优先使用 query 参数，其次从 URL / 头部推断
            final_name = filename
            if not final_name:
                # 从 URL path 中取最后一段
                from urllib.parse import urlparse
                parsed = urlparse(url)
                candidate = (parsed.path or "").rstrip("/").split("/")[-1] or "download"
                final_name = candidate

            headers = {
                "Content-Disposition": f'attachment; filename="{final_name}"',
                "Content-Type": content_type,
            }
            if content_length is not None:
                headers["Content-Length"] = content_length

            return StreamingResponse(
                iter(upstream.iter_bytes()),
                status_code=upstream.status_code,
                headers=headers,
                media_type=content_type,
            )
    except Exception as e:
        logger.error(f"Failed to proxy download for {url}: {e}", exc_info=True)
        # 返回一个统一错误响应，而不是让浏览器打开原地址
        return Response(
            content="Failed to download file",
            status_code=500,
            media_type="text/plain; charset=utf-8",
        )
