"""Values management endpoints."""

from __future__ import annotations

import os
from typing import Annotated, Any

from fastapi import APIRouter, Depends

from ilum.api.deps import get_manager
from ilum.api.models import (
    OperationCreated,
    ValuesDiffEntry,
    ValuesDiffResponse,
    ValuesUpdateRequest,
)
from ilum.api.operations import OperationStore, get_operation_store
from ilum.api.routers.release import ensure_release_not_stuck
from ilum.core.release import ReleaseManager
from ilum.core.safety import DriftResult

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


def _get_chart_version(mgr: ReleaseManager, release: str) -> str:
    """Best-effort chart version from the release."""
    try:
        info = mgr.get_release_info(release)
        return info.chart_version
    except Exception:
        return ""


@router.get("")
async def get_values(
    mgr: Annotated[ReleaseManager, Depends(get_manager)],
) -> dict[str, Any]:
    """Return current Helm values for the release."""
    release = os.environ.get("ILUM_RELEASE_NAME", "ilum")
    return mgr.fetch_live_values(release)


@router.get("/diff", response_model=ValuesDiffResponse)
async def get_values_diff(
    mgr: Annotated[ReleaseManager, Depends(get_manager)],
) -> ValuesDiffResponse:
    """Detect drift between live values and last CLI snapshot."""
    release = os.environ.get("ILUM_RELEASE_NAME", "ilum")
    drift: DriftResult = mgr.check_drift(release)

    changes: list[ValuesDiffEntry] = []
    if drift.diff:
        for key, value in drift.diff.added.items():
            changes.append(ValuesDiffEntry(key=key, new=value, change_type="added"))
        for key, value in drift.diff.removed.items():
            changes.append(ValuesDiffEntry(key=key, old=value, change_type="removed"))
        for key, (old, new) in drift.diff.changed.items():
            changes.append(ValuesDiffEntry(key=key, old=old, new=new, change_type="changed"))

    return ValuesDiffResponse(
        has_drift=drift.has_drift,
        snapshot_exists=drift.snapshot_exists,
        changes=changes,
    )


@router.put("", response_model=OperationCreated, status_code=202)
async def update_values(
    body: ValuesUpdateRequest,
    mgr: Annotated[ReleaseManager, Depends(get_manager)],
    store: Annotated[OperationStore, Depends(get_operation_store)],
) -> OperationCreated:
    """Apply --set flags via helm upgrade (async operation via K8s Job)."""
    from fastapi import HTTPException

    from ilum.api.job_runner import build_helm_job, check_no_active_helm_operation

    if not body.set_flags:
        raise HTTPException(400, "No set_flags provided.")

    release = os.environ.get("ILUM_RELEASE_NAME", "ilum")
    namespace = os.environ.get("ILUM_NAMESPACE", "default")
    chart = os.environ.get("ILUM_CHART_REF", "ilum/ilum")

    check_no_active_helm_operation(store, mgr.k8s, namespace)
    ensure_release_not_stuck(mgr)

    # Planning stays in-process (read-only)
    plan = mgr.plan_upgrade(release=release, chart=chart, set_flags=body.set_flags)

    # Pin chart version to avoid accidental upgrades after helm repo update
    version = plan.chart_version or _get_chart_version(mgr, release)

    op_id = store.create(operation="upgrade", modules=[])
    job = build_helm_job(
        op_id=op_id,
        operation="upgrade",
        release=release,
        namespace=namespace,
        chart_ref=plan.chart,
        set_flags=plan.set_flags,
        version=version,
        reset_defaults=plan.reset_defaults,
    )
    mgr.k8s.create_job(namespace, job)

    op = store.get(op_id)
    if op:
        op.job_name = f"ilum-helm-{op_id}"
        op.status = "running"

    return OperationCreated(id=op_id, status="running", message="Applying values update")
