"""
app/api/v1/delivery.py — 交付包路由
POST /tasks/{id}/package — 生成达人素材交付包
GET /delivery-packages/{id}/download — 下载（status: pending/ready/downloaded）
POST /delivery-packages/{id}/download-token — 签发60s一次性下载令牌（C1坑修复）
GET /delivery-packages/{id}/download-file?token= — 带令牌下载，前端可用 window.open
"""

import logging
from typing import Annotated

from fastapi import APIRouter, Depends, Header, Query
from fastapi.responses import FileResponse
from pydantic import BaseModel
from sqlalchemy.orm import Session

from app.core.database import get_db
from app.core.response import ok, raise_not_found
from app.middleware.workspace_guard import CurrentUser, require_write_permission
from app.models.task import DeliveryPackage, GenerationTask

logger = logging.getLogger(__name__)
router = APIRouter(tags=["delivery"])


class PackageRequest(BaseModel):
    note_ids: list[int] = []   # 可选，指定要打包的内容


def _fmt_package(pkg: DeliveryPackage) -> dict:
    return {
        "id": pkg.id,
        "status": pkg.status,
        "download_url": pkg.download_url,
        "expires_at": pkg.expires_at.isoformat() if pkg.expires_at else None,
    }


@router.post("/tasks/{task_id}/package")
def create_package(
    task_id: int, body: PackageRequest,
    current_user: Annotated[CurrentUser, Depends(require_write_permission)] = None,
    db: Session = Depends(get_db),
):
    """
    生成达人素材交付包。
    任务推入 Celery build_delivery_package 队列（只传 package_id）。
    """
    task = db.query(GenerationTask).filter(
        GenerationTask.id == task_id,
        GenerationTask.workspace_id == current_user.workspace_id,
    ).first()
    if not task:
        raise_not_found("任务不存在")
    if task.status not in ("approved", "pending_selection"):
        from app.core.response import raise_business
        raise_business("任务尚未生成完成，无法打包")

    pkg = DeliveryPackage(
        workspace_id=current_user.workspace_id,
        task_id=task_id,
        status="pending",
    )
    db.add(pkg)
    db.commit()
    db.refresh(pkg)

    # 推 Celery 队列，只传 package_id（基石B思路：不传任何敏感信息）
    from app.workers.tasks import build_delivery_package
    build_delivery_package.delay(pkg.id)

    return ok({"delivery_package_id": pkg.id, "status": "pending"})


@router.get("/delivery-packages/{package_id}/download")
def get_package_download(
    package_id: int,
    current_user: Annotated[CurrentUser, Depends(require_write_permission)] = None,
    db: Session = Depends(get_db),
):
    """下载交付包（status: pending/ready/downloaded）。"""
    pkg = db.query(DeliveryPackage).filter(
        DeliveryPackage.id == package_id,
        DeliveryPackage.workspace_id == current_user.workspace_id,
    ).first()
    if not pkg:
        raise_not_found("交付包不存在")

    if pkg.status == "ready" and pkg.download_url:
        # 标记为 downloaded（只能下一次，防重复公开 URL）
        pkg.status = "downloaded"
        db.commit()

    return ok(_fmt_package(pkg))


@router.post("/delivery-packages/{package_id}/download-token")
def create_download_token(
    package_id: int,
    current_user: Annotated[CurrentUser, Depends(require_write_permission)] = None,
    db: Session = Depends(get_db),
):
    """
    C1坑修复：签发一次性下载令牌（60s有效）。
    前端先用 JWT 调此接口，再用 token 直接 window.open/fetch，无需在URL里传JWT。
    """
    import secrets
    import redis as sync_redis
    from app.core.config import get_settings

    pkg = db.query(DeliveryPackage).filter(
        DeliveryPackage.id == package_id,
        DeliveryPackage.workspace_id == current_user.workspace_id,
    ).first()
    if not pkg:
        raise_not_found("交付包不存在")
    if pkg.status not in ("ready", "downloaded"):
        from app.core.response import raise_business
        raise_business("交付包尚未准备好")

    token = secrets.token_hex(32)
    r = sync_redis.from_url(get_settings().REDIS_URL, decode_responses=True)
    r.setex(f"dl_token:{token}", 60, str(package_id))
    return ok({"token": token, "expires_in": 60})


@router.get("/delivery-packages/{package_id}/download-file")
def download_package_file(
    package_id: int,
    token: str = Query(default=""),
    authorization: str = Header(default=""),
    db: Session = Depends(get_db),
):
    """
    直接下载交付包 zip 文件（FileResponse）。
    支持两种认证：
    1. ?token=<download-token>（前端 window.open 用，C1坑修复）
    2. Authorization: Bearer <JWT>（API 调用用）
    """
    import os
    import redis as sync_redis
    from app.core.config import get_settings
    from app.core.security import decode_access_token
    import jwt as pyjwt

    # token 认证（一次性，60s有效，跳过JWT）
    if token:
        r = sync_redis.from_url(get_settings().REDIS_URL, decode_responses=True)
        stored = r.getdel(f"dl_token:{token}")
        if not stored or int(stored) != package_id:
            from app.core.response import raise_business
            raise_business("下载令牌无效或已过期")
        pkg = db.query(DeliveryPackage).filter(DeliveryPackage.id == package_id).first()
    else:
        # JWT 认证
        if not authorization or not authorization.startswith("Bearer "):
            from app.core.response import raise_unauthorized
            raise_unauthorized("缺少认证信息")
        try:
            payload = decode_access_token(authorization.split(" ", 1)[1])
        except (pyjwt.PyJWTError, Exception):
            from app.core.response import raise_unauthorized
            raise_unauthorized("Token 无效")
        workspace_id = int(payload["current_workspace_id"])
        pkg = db.query(DeliveryPackage).filter(
            DeliveryPackage.id == package_id,
            DeliveryPackage.workspace_id == workspace_id,
        ).first()

    if not pkg:
        raise_not_found("交付包不存在")
    if pkg.status not in ("ready", "downloaded"):
        from app.core.response import raise_business
        raise_business("交付包尚未准备好，请稍后重试")
    if not pkg.package_path or not os.path.exists(pkg.package_path):
        from app.core.response import raise_business
        raise_business("交付包文件不存在，请重新打包")

    filename = os.path.basename(pkg.package_path)
    return FileResponse(
        path=pkg.package_path,
        media_type="application/zip",
        filename=filename,
    )
