"""
app/workers/packaging_task.py — 交付打包 Celery 任务
build_delivery_package：查已选文案+图片 → package_exporter → 存路径
"""

import json
import logging

from app.workers.celery_app import celery_app

logger = logging.getLogger(__name__)


def _get_db():
    from app.core.database import SessionLocal
    return SessionLocal()


@celery_app.task(
    bind=True,
    name="app.workers.tasks.build_delivery_package",
    max_retries=2,
    default_retry_delay=10,
    queue="packaging",
)
def build_delivery_package(self, package_id: int) -> dict:
    """打包交付任务。查 delivery_packages → 收集笔记 → package_exporter"""
    logger.info("build_delivery_package start: package_id=%s", package_id)
    db = _get_db()
    try:
        from app.models.task import DeliveryPackage, TextCandidate, ImageCandidate
        from app.constants.enums import PackageStatus

        pkg = db.query(DeliveryPackage).filter(DeliveryPackage.id == package_id).first()
        if not pkg:
            raise ValueError(f"package_id={package_id} not found")

        workspace_id = pkg.workspace_id
        task_id = pkg.task_id

        from app.core.config import get_settings
        settings = get_settings()
        upload_base = settings.UPLOAD_BASE_PATH.rstrip("/")

        selected_text = db.query(TextCandidate).filter(
            TextCandidate.task_id == task_id, TextCandidate.is_selected == True,
        ).first()
        # 整套全打（倩倩姐2026-06-08拍板）：一条笔记的全部图按 seq 排序进包，
        # 不再只打 is_selected 的封面。北哥6张标准套 seq=1 是 hook 封面，天然排第一。
        selected_images = db.query(ImageCandidate).filter(
            ImageCandidate.task_id == task_id,
        ).order_by(ImageCandidate.seq).all()

        if not selected_text:
            raise ValueError("无已选文案，请先选择文案")

        text_data = json.loads(selected_text.content or "{}")
        images_data = []
        for ic in selected_images:
            img_bytes = b""
            if ic.url:
                # url 形如 /uploads/ws/task/file.jpg，本身已含 uploads 前缀。
                # 工作目录是 /app，直接 lstrip("/") 当相对路径读，不能再拼 upload_base(会重复 uploads/uploads)。
                rel = ic.url.lstrip("/")
                abs_path = rel
                try:
                    with open(abs_path, "rb") as f:
                        img_bytes = f.read()
                except OSError as e:
                    logger.warning("图片读取失败，跳过：%s %s", abs_path, e)
            images_data.append({
                "seq": ic.seq,
                "role": ic.role.value if hasattr(ic.role, "value") else str(ic.role),
                "data": img_bytes,
            })

        notes = [{
            "title": text_data.get("title", ""),
            "content": text_data.get("content", ""),
            "tags": text_data.get("tags", []),
            "images": images_data,
            "banned_word_status": (selected_text.banned_word_status.value
                                   if hasattr(selected_text.banned_word_status, "value")
                                   else str(selected_text.banned_word_status)),
        }]

        from app.services.ai_engine.package_exporter import build_delivery_package as do_build
        # 打包产物放专用目录 uploads/packages/，与图片目录 uploads/{ws}/{task}/ 分开
        packages_base = f"{upload_base}/packages"
        zip_path = do_build(workspace_id, task_id, notes, base_path=packages_base)

        pkg.package_path = zip_path
        pkg.download_url = f"/api/v1/delivery-packages/{package_id}/download-file"
        pkg.status = PackageStatus.READY
        db.commit()

        logger.info("delivery package ready: package_id=%s path=%s", package_id, zip_path)
        return {"package_id": package_id, "status": "ready", "path": zip_path}

    except Exception as exc:
        logger.error("build_delivery_package failed: package_id=%s err=%s", package_id, exc)
        raise self.retry(exc=exc)
    finally:
        db.close()
