import os
from pathlib import Path
from typing import Any, Dict

from django.conf import settings
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from .cli import run_lk_agent

def _default_workdir() -> str:
    # Prefer explicit env, else assume repo layout: <repo>/backend/agent_runtime
    env_dir = os.getenv("LIVEKIT_AGENT_WORKDIR")
    if env_dir and str(env_dir).strip():
        return str(env_dir).strip()
    base_dir = getattr(settings, "BASE_DIR", None)
    if base_dir:
        return str(Path(base_dir).parent / "agent_runtime")
    return "backend/agent_runtime"


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def deploy_agent(request):
    """
    Deploy a LiveKit Cloud agent by shelling out to the LiveKit CLI (`lk`).

    This endpoint is optional and will return 501 unless `lk` is installed on the server.

    Body:
      - action: "create" | "deploy" (default "deploy")
      - workdir: directory containing agent Dockerfile + livekit.toml (optional)
      - region: optional LiveKit Cloud region
      - config: optional livekit.toml path (default handled by lk)
      - agent_id: optional agent id (for deploy/update)
      - secrets: { KEY: VALUE } optional environment secrets to inject
      - secrets_file: path to secrets file (server-side path) optional
      - timeout_s: int (default 900)
      - silent: bool (default true)
    """
    data = request.data if isinstance(request.data, dict) else {}
    action = str(data.get("action") or "deploy").strip().lower()
    if action not in ("create", "deploy"):
        return Response(
            {"message": "Invalid action. Use 'create' or 'deploy'."},
            status=status.HTTP_400_BAD_REQUEST,
        )

    workdir = str(data.get("workdir") or _default_workdir()).strip()
    if not workdir:
        return Response(
            {"message": "workdir is required."},
            status=status.HTTP_400_BAD_REQUEST,
        )

    workdir_path = Path(workdir)
    if not workdir_path.exists():
        return Response(
            {"message": f"workdir does not exist: {workdir}"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    region = (str(data.get("region")).strip() if data.get("region") is not None else None) or None
    config = (str(data.get("config")).strip() if data.get("config") is not None else None) or None
    agent_id = (str(data.get("agent_id")).strip() if data.get("agent_id") is not None else None) or None
    secrets_file = (str(data.get("secrets_file")).strip() if data.get("secrets_file") is not None else None) or None
    silent = bool(data.get("silent", True))
    timeout_s = data.get("timeout_s", 900)
    try:
        timeout_s = int(timeout_s)
        timeout_s = max(10, min(timeout_s, 3600))
    except (TypeError, ValueError):
        timeout_s = 900

    secrets = data.get("secrets")
    if secrets is not None and not isinstance(secrets, dict):
        return Response(
            {"message": "secrets must be an object/dict of KEY: VALUE"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    payload: Dict[str, Any] = run_lk_agent(
        action,
        workdir_path,
        region=region,
        config=config,
        agent_id=agent_id,
        secrets=secrets,
        secrets_file=secrets_file,
        silent=silent,
        timeout_s=timeout_s,
    )

    if payload.get("exit_code") is None and "lk" in str(payload.get("message", "")).lower():
        return Response(payload, status=status.HTTP_501_NOT_IMPLEMENTED)
    return Response(payload, status=status.HTTP_200_OK if payload.get("ok") else status.HTTP_502_BAD_GATEWAY)

