from __future__ import annotations

from contextlib import suppress

from fastapi import Depends, FastAPI, HTTPException, Request, status
from fastapi.responses import FileResponse, JSONResponse

from .config import Settings, get_settings
from .image_io import (
    cleanup_expired_files,
    delete_temp_file,
    download_source_image,
    ensure_directories,
    resolve_result_path,
    save_output_image,
)
from .schemas import HealthResponse, UpscaleRequest, UpscaleResponse
from .security import verify_bearer_token
from .upscaler import UpscaleEngineUnavailable, build_upscaler


def create_app(settings: Settings | None = None) -> FastAPI:
    app = FastAPI(title="skinbase-enhance-worker", version="1.0.0")
    resolved_settings = settings or get_settings()
    ensure_directories(resolved_settings)
    cleanup_expired_files(resolved_settings)
    app.state.settings = resolved_settings
    app.state.upscaler = build_upscaler(resolved_settings)

    @app.get("/health", response_model=HealthResponse)
    def health() -> HealthResponse:
        engine_health = app.state.upscaler.health()

        with suppress(Exception):
            cleanup_expired_files(app.state.settings)

        return HealthResponse(
            status=engine_health.status,
            service="skinbase-enhance-worker",
            engine=engine_health.engine,
            device=engine_health.device,
            models_loaded=engine_health.models_loaded,
            max_input_width=app.state.settings.max_input_width,
            max_input_height=app.state.settings.max_input_height,
            max_output_width=app.state.settings.max_output_width,
            max_output_height=app.state.settings.max_output_height,
            realesrgan=engine_health.details.get("realesrgan"),
        )

    @app.post("/v1/upscale", response_model=UpscaleResponse)
    def upscale(payload: UpscaleRequest, request: Request, _: None = Depends(verify_bearer_token)):
        cleanup_expired_files(app.state.settings)
        downloaded = None

        try:
            downloaded = download_source_image(payload.source_url, app.state.settings)
            result = app.state.upscaler.upscale(downloaded, payload.scale, payload.mode, payload.output_format)
            stored = save_output_image(result.image, payload.output_format, app.state.settings, payload.job_id)

            return UpscaleResponse(
                success=True,
                job_id=payload.job_id,
                output_url=str(request.base_url).rstrip("/") + f"/v1/results/{stored.filename}",
                width=stored.width,
                height=stored.height,
                filesize=stored.filesize,
                mime=stored.mime,
                metadata=result.metadata,
            )
        except HTTPException as exc:
            return JSONResponse(status_code=exc.status_code, content={"success": False, "error": exc.detail})
        except UpscaleEngineUnavailable as exc:
            return JSONResponse(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, content={"success": False, "error": str(exc)})
        finally:
            delete_temp_file(downloaded.path if downloaded is not None else None)

    @app.get("/v1/results/{filename}")
    def result(filename: str):
        path = resolve_result_path(app.state.settings, filename)

        if not path.exists() or not path.is_file():
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Not found")

        return FileResponse(path)

    @app.delete("/v1/results/{filename}")
    def delete_result(filename: str, _: None = Depends(verify_bearer_token)):
        path = resolve_result_path(app.state.settings, filename)

        if not path.exists() or not path.is_file():
            return {"success": True, "deleted": False}

        path.unlink(missing_ok=True)

        return {"success": True, "deleted": True}

    return app


app = create_app()