"""내보내기 API 라우터."""

from pathlib import Path

from fastapi import APIRouter, Depends, Request
from fastapi.responses import FileResponse
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.errors import AppError
from app.i18n.loader import t
from app.models.catalog import UserAccount
from app.schemas.export import (
    ExportFileResponse,
    PDFValidationResponse,
    ProjectExportResponse,
    ProjectImportRequest,
    ProjectImportResponse,
    WebbookGenerateRequest,
)
from app.services.export_service import ExportService
from app.services.project_export_service import ProjectExportService, ProjectImportService

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

# A separate router without the project_id path prefix, for import
import_router = APIRouter(
    prefix="/api/v1/projects",
    tags=["exports"],
)


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


@router.post("/episodes/{episode_id}/generate-webbook")
def generate_webbook(
    episode_id: str,
    body: WebbookGenerateRequest,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Generate webbook package for an episode."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    package = service.generate_webbook(
        episode_id=episode_id,
        web_episode_count=body.web_episode_count,
        sections_per_episode=body.sections_per_episode,
        ip=ip,
    )
    return {"ok": True, "message": t("export.webbook_started"), "package": package}


@router.post("/episodes/{episode_id}/render-pdf")
def render_pdf(
    episode_id: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Render PDFs from existing webbook package + images."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    paths = service.render_pdfs(episode_id=episode_id, ip=ip)
    return {
        "ok": True,
        "message": t("export.render_started"),
        "files": [Path(p).name for p in paths],
    }


@router.post("/episodes/{episode_id}/export-html-zip")
def export_html_zip(
    episode_id: str,
    request: Request,
    original: bool = False,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """씬별 원본 텍스트 + 이미지를 HTML로 만들어 ZIP 생성 (exports 디렉토리에 저장).

    original=true: 이미지를 JPEG 변환 없이 원본 파일(PNG 등) 그대로 export (무손실).
    """
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    zip_path = service.generate_html_zip(episode_id=episode_id, ip=ip, original=original)
    filename = Path(zip_path).name
    msg = ("원본 PNG " if original else "") + "HTML ZIP 생성 완료"
    return {"ok": True, "filename": filename, "message": msg}


@router.post("/exports/{filename}/validate", response_model=PDFValidationResponse)
def validate_pdf(
    filename: str,
    request: Request,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Validate a rendered PDF using GPT vision."""
    ip = request.client.host if request.client else None
    service = _make_service(project_id, db, current_user)
    return service.validate_pdf(filename=filename, ip=ip)


@router.get("/exports", response_model=list[ExportFileResponse])
def list_exports(
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """List all exported files."""
    service = _make_service(project_id, db, current_user)
    return service.list_exports()


@router.get("/exports/{filename}")
def download_export(
    filename: str,
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Download an exported PDF file."""
    project_dir = Path(settings.projects_dir) / project_id
    exports_dir = project_dir / "assets" / "exports"
    file_path = exports_dir / filename

    # Security: ensure filename doesn't escape the exports directory
    try:
        file_path.resolve().relative_to(exports_dir.resolve())
    except ValueError:
        raise AppError(
            code="export.file_not_found",
            message=t("export.file_not_found"),
            status_code=404,
        )

    if not file_path.exists() or not file_path.is_file():
        raise AppError(
            code="export.file_not_found",
            message=t("export.file_not_found"),
            status_code=404,
        )

    media_types = {".zip": "application/octet-stream", ".pdf": "application/pdf"}
    media = media_types.get(file_path.suffix, "application/octet-stream")
    return FileResponse(
        path=str(file_path),
        media_type=media,
        filename=filename,
        headers={"Content-Disposition": f'attachment; filename="{filename}"'},
    )


# ── JSON project export / import ──────────────────────────────────────────

@router.get("/export", response_model=ProjectExportResponse)
def export_project_json(
    project_id: str = Depends(verify_project_access),
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Export entire project as a JSON document."""
    svc = ProjectExportService(db=db, project_id=project_id)
    try:
        return svc.export_json()
    except AppError:
        raise
    except Exception as exc:
        raise AppError(
            code="export.failed",
            message=t("export.failed"),
            status_code=500,
        ) from exc


@import_router.post("/import", response_model=ProjectImportResponse)
def import_project_json(
    body: ProjectImportRequest,
    db: OrmSession = Depends(get_db),
    current_user: UserAccount = Depends(get_current_user),
):
    """Import a project from an exported JSON document."""
    svc = ProjectImportService(db=db, actor_id=current_user.id)
    try:
        new_pid = svc.import_json(data=body.data, new_name=body.new_name)
    except AppError:
        raise
    except Exception as exc:
        raise AppError(
            code="import.failed",
            message=t("import.failed"),
            status_code=500,
        ) from exc
    return ProjectImportResponse(
        project_id=new_pid,
        message=t("import.success"),
    )
