"""이미지 관리 API 라우터."""

from pathlib import Path
from typing import Optional

from fastapi import APIRouter, Depends, Query, Request, UploadFile, File, Form
from fastapi.responses import FileResponse
from pydantic import BaseModel
from sqlalchemy.orm import Session as OrmSession

from app.api.deps import get_db, get_current_user, verify_project_access
from app.core.config import settings
from app.core.database import SessionLocal
from app.core.errors import AppError
from app.core.job_manager import submit_background_job
from app.i18n.loader import t
from app.models.catalog import UserAccount
from app.schemas.image import ImageResponse, ReviewUpdate, ValidationResponse
from app.schemas.trace import GenerationTraceResponse, RejectionStatsResponse
from app.modules.llm.gemini_key_pool import key_count as gemini_key_count
from app.services.image_service import ImageService


class GenerateSingleRequest(BaseModel):
    custom_prompt: Optional[str] = None


class EditAngleRequest(BaseModel):
    horizontal: int = 0
    vertical: int = 0
    zoom: float = 1.0


class EditColorRequest(BaseModel):
    color_prompt: str


class SelectVariantRequest(BaseModel):
    variant: str  # "original" | "A" | "B"


class SelectOriginalRequest(BaseModel):
    image_id: str


router = APIRouter(
    prefix="/api/v1/projects/{project_id}",
    tags=["images"],
)


def _make_service(
    project_id: str,
    db: OrmSession,
    user: UserAccount,
) -> ImageService:
    return ImageService(
        db=db,
        project_id=project_id,
        actor_id=user.id,
    )


@router.get("/images", response_model=list[ImageResponse])
def list_images(
    type: str | None = Query(default=None, alias="type"),
    episode_id: str | None = Query(default=None),
    entity_id: str | None = Query(default=None),
    still_id: str | None = Query(default=None),
    outlook_id: str | None = Query(default=None),
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """List images, optionally filtered by asset type, episode, entity, or still.

    outlook_id: when provided, returns images whose prompt_used contains
    'outlook_id:{outlook_id}' (composite images referencing this outlook).
    """
    service = _make_service(project_id, db, current_user)
    return service.list_images(
        episode_id=episode_id, asset_type=type,
        entity_id=entity_id, still_id=still_id,
        outlook_id=outlook_id,
    )


@router.get("/images/{image_id}", response_model=ImageResponse)
def get_image(
    image_id: str,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Get image detail."""
    service = _make_service(project_id, db, current_user)
    return service.get_image(image_id)


@router.get("/images/{image_id}/file")
def get_image_file(
    image_id: str,
    thumb: int = 0,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Serve image file. ?thumb=1 로 축소 JPG 썸네일 반환."""
    service = _make_service(project_id, db, current_user)
    img = service.get_image(image_id)
    file_path = Path(img.file_path)

    # Path traversal guard: resolved path must be within the projects directory
    resolved = file_path.resolve()
    project_dir = Path(settings.projects_dir).resolve()
    if not str(resolved).startswith(str(project_dir) + "/") and resolved != project_dir:
        raise AppError(
            code="image.path_forbidden",
            message=t("image.not_found"),
            status_code=403,
        )

    if not file_path.exists():
        raise AppError(
            code="image.not_found",
            message=t("image.not_found"),
            status_code=404,
        )

    # 썸네일 모드: 축소 JPG 반환 (캐시 포함)
    if thumb:
        thumb_path = file_path.parent / (file_path.stem + ".thumb.jpg")
        needs_regen = not thumb_path.exists() or thumb_path.stat().st_mtime < file_path.stat().st_mtime
        if needs_regen:
            try:
                from PIL import Image as PILImage
                with PILImage.open(file_path) as pil_img:
                    pil_img.thumbnail((400, 400))
                    pil_img = pil_img.convert("RGB")
                    pil_img.save(thumb_path, "JPEG", quality=75)
            except Exception:
                # Pillow 실패 시 원본 반환
                return FileResponse(path=str(file_path), media_type="image/png", filename=file_path.name)
        return FileResponse(
            path=str(thumb_path),
            media_type="image/jpeg",
            filename=file_path.stem + ".thumb.jpg",
            headers={"Cache-Control": "public, max-age=86400"},
        )

    return FileResponse(
        path=str(file_path),
        media_type="image/png",
        filename=file_path.name,
    )


@router.patch("/images/{image_id}/review", response_model=ImageResponse)
def update_review(
    image_id: str,
    body: ReviewUpdate,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Update review status of an image."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.update_review(image_id, body.status, body.notes, ip=ip)


@router.post("/images/{image_id}/validate", response_model=ValidationResponse)
def validate_image(
    image_id: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Re-validate a single image using GPT-5.4 vision."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    result = service.validate_image(image_id, ip=ip)
    return {
        "image_id": image_id,
        "score": result.get("score"),
        "passed": result.get("passed"),
        "issues": result.get("issues", []),
        "description": result.get("description", ""),
    }


@router.get("/images/{image_id}/validation", response_model=ValidationResponse)
def get_validation(
    image_id: str,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Get validation result for a single image."""
    service = _make_service(project_id, db, current_user)
    return service.get_validation(image_id)


@router.post("/images/{image_id}/regenerate")
def regenerate_image(
    image_id: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Regenerate a single image."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    service.regenerate_image(image_id, ip=ip)
    return {"ok": True, "message": t("image.regeneration_started")}


@router.post("/images/{image_id}/set-primary", response_model=ImageResponse)
def set_primary(
    image_id: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Set an image as the primary (representative) image for its entity/still."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.set_primary_image(image_id, ip=ip)


@router.post("/entities/{entity_id}/generate-image", response_model=ImageResponse)
def generate_entity_image(
    entity_id: str,
    body: GenerateSingleRequest,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Generate a single reference image for an entity."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.generate_single_entity_image(entity_id, custom_prompt=body.custom_prompt, ip=ip)


@router.post("/stills/{still_id}/generate-image", response_model=ImageResponse)
def generate_still_image(
    still_id: str,
    body: GenerateSingleRequest,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Generate a single scene image for a still."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.generate_single_scene_image(still_id, custom_prompt=body.custom_prompt, ip=ip)


class ComposerPromptUpdate(BaseModel):
    composer_system_prompt: Optional[str] = None
    composer_user_prompt: Optional[str] = None


@router.post("/stills/{still_id}/compose-prompts")
def compose_prompts(
    still_id: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Run T2I composer on a still, save results, return both prompts."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.compose_prompts(still_id, ip=ip)


@router.get("/settings/composer-prompt")
def get_composer_prompt(
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Get current composer prompt settings for a project."""
    service = _make_service(project_id, db, current_user)
    return service.get_composer_prompt()


@router.patch("/settings/composer-prompt")
def update_composer_prompt(
    body: ComposerPromptUpdate,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Update project-level composer prompt override."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.update_composer_prompt(
        system_prompt=body.composer_system_prompt,
        user_prompt=body.composer_user_prompt,
        ip=ip,
    )


@router.post("/images/upload", response_model=ImageResponse)
async def upload_image(
    file: UploadFile = File(...),
    entity_id: Optional[str] = Form(default=None),
    still_id: Optional[str] = Form(default=None),
    episode_id: Optional[str] = Form(default=None),
    request: Request = None,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Upload a custom reference/scene image."""
    ip = request.client.host if request and request.client else None
    file_bytes = await file.read()
    filename = file.filename or "uploaded_image.png"
    service = _make_service(project_id, db, current_user)
    return service.upload_custom_image(
        file_bytes=file_bytes,
        filename=filename,
        entity_id=entity_id,
        still_id=still_id,
        episode_id=episode_id,
        ip=ip,
    )


def _run_image_gen_in_background(
    project_id: str,
    actor_id: str,
    episode_id: str,
    ip: str | None,
    mode: str = "resume",
) -> None:
    """Run image generation in a background thread with its own DB session."""
    db = SessionLocal()
    try:
        svc = ImageService(
            db=db,
            project_id=project_id,
            actor_id=actor_id,
        )
        svc.generate_images(episode_id, ip=ip, mode=mode)
    except Exception as exc:
        # Mark any stuck 'running' progress as failed so UI doesn't stay in "generating..." state
        import logging
        logging.getLogger(__name__).error("Image generation failed: %s", exc)
        try:
            from app.models.project import PipelineProgress
            stuck = (
                db.query(PipelineProgress)
                .filter(
                    PipelineProgress.project_id == project_id,
                    PipelineProgress.episode_id == episode_id,
                    PipelineProgress.operation == "image_generation",
                    PipelineProgress.status == "running",
                )
                .order_by(PipelineProgress.started_at.desc())
                .first()
            )
            if stuck:
                from datetime import datetime, timezone
                now = datetime.now(timezone.utc).isoformat()
                stuck.status = "error"
                stuck.error_message = str(exc)[:2000]
                stuck.updated_at = now
                db.commit()
        except Exception:
            pass
        raise  # re-raise so job_manager logs it
    finally:
        db.close()


@router.post("/episodes/{episode_id}/generate-reference-images")
def generate_reference_images(
    episode_id: str,
    request: Request,
    mode: str = Query("resume", pattern="^(resume|full)$"),
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """참조 이미지(엔티티)만 생성 (씬 이미지 제외). 백그라운드 스레드.

    mode: resume (기본, 미완성분만) / full (전체 삭제 후 재생성)
    """
    ip = request.client.host if request.client else None
    from app.models.project import Episode
    episode = db.query(Episode).filter(Episode.id == episode_id, Episode.project_id == project_id).first()
    if not episode:
        raise AppError(code="episode.not_found", message=t("episode.not_found"), status_code=404)
    if episode.status != "analyzed":
        raise AppError(
            code="image.analysis_not_complete",
            message=f"분석이 완료되지 않았습니다 (현재: {episode.status}). 분석을 먼저 완료하세요.",
            status_code=400,
        )
    if not settings.gemini_api_key and gemini_key_count() == 0:
        raise AppError(code="image.gemini_key_missing", message=t("image.gemini_key_missing"), status_code=400)

    def _run_ref_gen(pid, actor_id, ep_id, ip_addr, gen_mode):
        db2 = SessionLocal()
        try:
            svc = ImageService(db=db2, project_id=pid, actor_id=actor_id)
            svc.generate_reference_images_only(ep_id, ip=ip_addr, mode=gen_mode)
        except Exception as exc:
            import logging
            logging.getLogger(__name__).error("Reference image generation failed: %s", exc)
            try:
                from app.models.project import PipelineProgress
                stuck = (
                    db2.query(PipelineProgress)
                    .filter(
                        PipelineProgress.project_id == pid,
                        PipelineProgress.episode_id == ep_id,
                        PipelineProgress.operation == "reference_image_generation",
                        PipelineProgress.status == "running",
                    )
                    .order_by(PipelineProgress.started_at.desc())
                    .first()
                )
                if stuck:
                    from datetime import datetime, timezone
                    now = datetime.now(timezone.utc).isoformat()
                    stuck.status = "error"
                    stuck.error_message = str(exc)[:2000]
                    stuck.updated_at = now
                    db2.commit()
            except Exception:
                pass
            raise  # re-raise so job_manager logs it
        finally:
            db2.close()

    started = submit_background_job(
        job_key=f"ref_gen:{episode_id}",
        target=_run_ref_gen,
        args=(project_id, current_user.id, episode_id, ip, mode),
        description=f"Reference image generation for episode {episode_id}",
    )
    if not started:
        raise AppError(code="image.generation_already_running", message="참조 이미지 생성이 이미 진행 중입니다", status_code=409)
    return {"ok": True, "message": "참조 이미지 생성이 시작되었습니다"}


@router.post("/episodes/{episode_id}/generate-images")
def generate_images(
    episode_id: str,
    request: Request,
    mode: str = Query("resume", pattern="^(resume|full)$"),
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Start full image generation for an episode (background thread).

    mode: resume (기본, 미완성분만) / full (전체 삭제 후 재생성)
    """
    ip = request.client.host if request.client else None

    # Validate preconditions
    from app.models.project import Episode
    episode = (
        db.query(Episode)
        .filter(Episode.id == episode_id, Episode.project_id == project_id)
        .first()
    )
    if not episode:
        raise AppError(
            code="episode.not_found",
            message=t("episode.not_found"),
            status_code=404,
        )
    if not episode.fulltext:
        raise AppError(
            code="analysis.no_text",
            message=t("analysis.no_text"),
            status_code=400,
        )
    if not settings.gemini_api_key and gemini_key_count() == 0:
        raise AppError(
            code="image.gemini_key_missing",
            message=t("image.gemini_key_missing"),
            status_code=400,
        )

    # ── 전 단계 검증 (백그라운드 시작 전 빠른 차단) ──
    if episode.status != "analyzed":
        raise AppError(
            code="image.analysis_not_complete",
            message=f"분석이 완료되지 않았습니다 (현재: {episode.status}). 분석을 먼저 완료하세요.",
            status_code=400,
        )
    ref_count = (
        db.query(ImageAsset)
        .filter(
            ImageAsset.project_id == project_id,
            ImageAsset.episode_id == episode_id,
            ImageAsset.asset_type == "reference",
            ImageAsset.is_primary == 1,
        )
        .count()
    )
    if ref_count == 0:
        raise AppError(
            code="image.no_reference_images",
            message="참조 이미지가 없습니다. 참조 이미지를 먼저 생성하세요.",
            status_code=400,
        )

    started = submit_background_job(
        job_key=f"image_gen:{episode_id}",
        target=_run_image_gen_in_background,
        args=(project_id, current_user.id, episode_id, ip, mode),
        description=f"Image generation for episode {episode_id}",
    )
    if not started:
        raise AppError(code="image.generation_already_running", message="이미지 생성이 이미 진행 중입니다", status_code=409)

    return {"ok": True, "message": t("image.generation_started")}


@router.post("/episodes/{episode_id}/generate-variations")
def generate_variations(
    episode_id: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """원본 이미지 기반 A/B 변형 추천 + 생성. 백그라운드 스레드."""
    ip = request.client.host if request.client else None

    def _run_var_gen(pid, actor_id, ep_id):
        db2 = SessionLocal()
        try:
            svc = ImageService(db=db2, project_id=pid, actor_id=actor_id)
            svc.generate_variations_only(ep_id)
        finally:
            db2.close()

    started = submit_background_job(
        job_key=f"var_gen:{episode_id}",
        target=_run_var_gen,
        args=(project_id, current_user.id, episode_id),
        description=f"Variation generation for episode {episode_id}",
    )
    if not started:
        raise AppError(code="image.generation_already_running", message="변형 생성이 이미 진행 중입니다", status_code=409)
    return {"ok": True, "message": "변형 추천+생성이 시작되었습니다"}


@router.get("/episodes/{episode_id}/generation-status")
def get_generation_status(
    episode_id: str,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """에피소드의 이미지 생성 완료 상태 조회."""
    from app.models.project import EntityEpisodeLink, SceneStill, ImageAsset

    # 참조 이미지: 전체 엔티티 수 vs 참조 이미지 있는 엔티티 수
    entity_links = (
        db.query(EntityEpisodeLink)
        .filter(EntityEpisodeLink.project_id == project_id, EntityEpisodeLink.episode_id == episode_id)
        .all()
    )
    ref_total = len(entity_links)
    canon_ids_with_ref = set()
    if entity_links:
        ref_assets = (
            db.query(ImageAsset.entity_id)
            .filter(
                ImageAsset.project_id == project_id,
                ImageAsset.asset_type == "reference",
                ImageAsset.entity_id.in_([l.canon_id for l in entity_links]),
            )
            .distinct()
            .all()
        )
        canon_ids_with_ref = {r[0] for r in ref_assets}
    ref_done = len(canon_ids_with_ref)

    # 씬 이미지: 전체 씬 수 vs 씬 이미지 있는 씬 수
    scene_total = (
        db.query(SceneStill)
        .filter(SceneStill.project_id == project_id, SceneStill.episode_id == episode_id)
        .count()
    )
    scene_done = 0
    if scene_total > 0:
        stills_with_images = (
            db.query(ImageAsset.still_id)
            .filter(
                ImageAsset.project_id == project_id,
                ImageAsset.episode_id == episode_id,
                ImageAsset.asset_type == "scene",
            )
            .distinct()
            .count()
        )
        scene_done = stills_with_images

    # 체크포인트에서 실패 정보 로드
    from app.modules.image_checkpoint import ImageCheckpointManager
    from app.core.config import settings as _settings
    cp_dir = Path(_settings.projects_dir) / project_id / "checkpoints" / "images" / episode_id
    ref_failed = 0
    scene_failed = 0
    try:
        ref_cp = ImageCheckpointManager(cp_dir, "reference")
        ref_failed = ref_cp.failed_count
    except Exception:
        pass
    try:
        scene_cp = ImageCheckpointManager(cp_dir, "scene")
        scene_failed = scene_cp.failed_count
    except Exception:
        pass

    # primary 이미지 수
    scene_primary = (
        db.query(ImageAsset)
        .filter(
            ImageAsset.project_id == project_id,
            ImageAsset.episode_id == episode_id,
            ImageAsset.asset_type == "scene",
            ImageAsset.is_primary == 1,
        )
        .count()
    )

    # fal.ai 앵글 이미지 수
    fal_count = (
        db.query(ImageAsset)
        .filter(
            ImageAsset.project_id == project_id,
            ImageAsset.episode_id == episode_id,
            ImageAsset.variant_type == "angle_fal",
        )
        .count()
    )

    return {
        "ref_total": ref_total,
        "ref_done": ref_done,
        "ref_failed": ref_failed,
        "scene_total": scene_total,
        "scene_done": scene_done,
        "scene_failed": scene_failed,
        "scene_primary": scene_primary,
        "fal_count": fal_count,
    }


@router.post("/episodes/{episode_id}/regenerate-needs-fix")
def regenerate_needs_fix(
    episode_id: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Regenerate all needs_fix images for an episode."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    count = service.regenerate_needs_fix(episode_id, ip=ip)
    return {"ok": True, "count": count, "message": t("image.regeneration_started")}


# ------------------------------------------------------------------
# Variation pipeline endpoints
# ------------------------------------------------------------------


@router.post("/stills/{still_id}/recommend-variations")
def recommend_variations(
    still_id: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """LLM에게 A/B 변형 추천 받기."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.recommend_variations(still_id, ip=ip)


@router.post("/stills/{still_id}/generate-with-variations")
def generate_with_variations(
    still_id: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """원본 + A변형 + B변형 이미지 생성."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.generate_scene_with_variations(still_id, ip=ip)


@router.post("/images/{image_id}/edit-angle")
def edit_angle(
    image_id: str,
    body: EditAngleRequest,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """앵글 재편집 (i2i)."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    import json
    angle_json = json.dumps({
        "horizontal": body.horizontal,
        "vertical": body.vertical,
        "zoom": body.zoom,
    })
    return service.regenerate_variation(image_id, angle_json=angle_json, ip=ip)


@router.post("/images/{image_id}/edit-color")
def edit_color(
    image_id: str,
    body: EditColorRequest,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """색감 재편집 (i2i)."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.regenerate_variation(image_id, color_prompt=body.color_prompt, ip=ip)


@router.patch("/stills/{still_id}/select-variant")
def select_variant(
    still_id: str,
    body: SelectVariantRequest,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """PDF 대표 변형 선택."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.select_variant(still_id, body.variant, ip=ip)


@router.patch("/stills/{still_id}/select-original")
def select_original(
    still_id: str,
    body: SelectOriginalRequest,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """원본 이미지 선택."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.select_original(still_id, body.image_id, ip=ip)


@router.get("/stills/{still_id}/images")
def get_still_images(
    still_id: str,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """씬의 모든 이미지 (original/A/B 그룹)."""
    service = _make_service(project_id, db, current_user)
    return service.get_still_images_grouped(still_id)


# ------------------------------------------------------------------
# Generation trace endpoints
# ------------------------------------------------------------------

@router.get("/generation-traces", response_model=list[GenerationTraceResponse])
def list_generation_traces(
    offset: int = Query(default=0, ge=0),
    limit: int = Query(default=50, ge=1, le=200),
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """List all generation traces (paginated)."""
    service = _make_service(project_id, db, current_user)
    return service.get_generation_traces(offset=offset, limit=limit)


@router.get("/generation-traces/stats", response_model=RejectionStatsResponse)
def get_rejection_stats(
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Get aggregated rejection statistics."""
    service = _make_service(project_id, db, current_user)
    return service.get_rejection_stats()


@router.get("/images/{image_id}/traces", response_model=list[GenerationTraceResponse])
def get_image_traces(
    image_id: str,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Get generation traces for a specific image."""
    service = _make_service(project_id, db, current_user)
    return service.get_image_traces(image_id)
