"""Release management endpoints (recovery, stuck-release handling)."""

from __future__ import annotations

import logging
import os
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException

from ilum.api.deps import get_manager
from ilum.api.models import ReleaseRecoveryResponse
from ilum.core.release import ReleaseManager
from ilum.errors import HelmError

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/release", tags=["release"])


def ensure_release_not_stuck(mgr: ReleaseManager) -> None:
    """Check if the release is stuck and auto-recover via rollback.

    Call this before any mutating Helm operation to avoid the
    "another operation is in progress" error.

    Raises :class:`HTTPException` (409) if recovery fails.
    """
    release = os.environ.get("ILUM_RELEASE_NAME", "ilum")
    if not mgr.is_stuck(release):
        return

    logger.warning("Release '%s' is stuck — attempting auto-recovery via rollback", release)
    try:
        mgr.helm.rollback(release)
        logger.info("Auto-recovered stuck release '%s'", release)
    except HelmError as exc:
        logger.error("Failed to auto-recover stuck release '%s': %s", release, exc)
        raise HTTPException(
            status_code=409,
            detail=(
                f"Release '{release}' is stuck in a pending state and automatic "
                f"recovery failed: {exc}. Manual intervention required: "
                f"run 'helm rollback {release}' from the CLI."
            ),
        ) from exc


@router.post("/recover", response_model=ReleaseRecoveryResponse)
async def recover_release(
    mgr: Annotated[ReleaseManager, Depends(get_manager)],
) -> ReleaseRecoveryResponse:
    """Detect and recover a stuck Helm release via rollback.

    Returns 200 with ``recovered=true`` if a rollback was performed,
    or ``recovered=false`` if the release was not stuck.
    """
    release = os.environ.get("ILUM_RELEASE_NAME", "ilum")
    try:
        info = mgr.get_release_info(release)
    except Exception as exc:
        raise HTTPException(404, f"Release '{release}' not found.") from exc

    if info.status not in ("pending-install", "pending-upgrade", "pending-rollback"):
        return ReleaseRecoveryResponse(
            recovered=False,
            previous_status=info.status,
            message=f"Release is '{info.status}' — no recovery needed.",
        )

    previous_status = info.status
    try:
        mgr.helm.rollback(release)
    except HelmError as exc:
        raise HTTPException(
            status_code=502,
            detail=(
                f"Rollback failed for stuck release '{release}' (status: {previous_status}): {exc}"
            ),
        ) from exc

    # Get the new revision after rollback
    new_info = mgr.get_release_info(release)
    logger.info(
        "Recovered release '%s' from '%s' — now revision %d",
        release,
        previous_status,
        new_info.revision,
    )
    return ReleaseRecoveryResponse(
        recovered=True,
        previous_status=previous_status,
        rolled_back_to=new_info.revision,
        message=(
            f"Release recovered from '{previous_status}' via rollback "
            f"to revision {new_info.revision}."
        ),
    )
