"""Workflow execution API routes."""

from __future__ import annotations

import json
import logging

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel

from mixersystem.studio.config import StudioConfig
from mixersystem.studio.process_manager import ProcessManager
from mixersystem.studio.routes import get_config, get_process_manager
from mixersystem.studio.session_paths import normalize_session_folder_arg, resolve_session_path

log = logging.getLogger(__name__)

VALID_STAGES = {"task", "plan", "work", "update", "upgrade", "report"}

router = APIRouter(prefix="/api/v1/workflows", tags=["workflows"])


class StartRequest(BaseModel):
    workflow: str
    session_folder: str
    args: dict = {}
    delete_before: str | None = None


@router.post("/start")
async def start_workflow(
    body: StartRequest,
    pm: ProcessManager = Depends(get_process_manager),
    config: StudioConfig = Depends(get_config),
):
    normalized_session_folder = ""
    if body.session_folder:
        try:
            normalized_session_folder = normalize_session_folder_arg(body.session_folder)
        except ValueError as e:
            raise HTTPException(status_code=400, detail=str(e)) from e

    folder_path = None
    if normalized_session_folder:
        folder_name = normalized_session_folder.removeprefix(".mixer/sessions/")
        try:
            folder_path = resolve_session_path(config.sessions_dir, folder_name)
        except ValueError as e:
            raise HTTPException(status_code=400, detail=str(e)) from e

    # Delete existing artifact before re-running from scratch
    if body.delete_before:
        if body.delete_before not in VALID_STAGES:
            raise HTTPException(
                status_code=400,
                detail=f"Invalid stage '{body.delete_before}'",
            )
        if not folder_path:
            raise HTTPException(status_code=400, detail="session_folder is required for delete_before")
        artifact = folder_path / f"{body.delete_before}.md"
        if artifact.exists():
            artifact.unlink()
            log.info("Deleted %s for fresh start", artifact)

    # Run task router if modules haven't been locked yet
    data = {}
    session_json = folder_path / "session.json" if folder_path else None
    if session_json and session_json.is_file():
        try:
            data = json.loads(session_json.read_text())
        except (OSError, json.JSONDecodeError):
            data = {}

    if folder_path and not data.get("modules_locked") and (folder_path / "task.md").is_file():
        try:
            from mixersystem.data.task_router import resolve_modules
            from mixersystem.data.repository import context_scope
            with context_scope(
                project_root=str(config.sessions_dir.parent.parent),
                session_folder=str(folder_path),
            ):
                await resolve_modules(str(folder_path))
        except (ImportError, OSError, ValueError):
            log.warning("Pre-flight module resolution failed", exc_info=True)

    try:
        run = await pm.start_workflow(body.workflow, normalized_session_folder, body.args)
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e)) from e
    return run.to_dict()


@router.post("/runs/{run_id}/stop")
async def stop_workflow(
    run_id: str,
    pm: ProcessManager = Depends(get_process_manager),
):
    run = await pm.stop_workflow(run_id)
    if not run:
        raise HTTPException(status_code=404, detail=f"Run '{run_id}' not found")
    return run.to_dict()


@router.get("/runs")
def list_runs(pm: ProcessManager = Depends(get_process_manager)):
    return [r.to_dict() for r in pm.list_runs()]


@router.get("/runs/active")
def list_active_runs(pm: ProcessManager = Depends(get_process_manager)):
    return [r.to_dict() for r in pm.list_active()]


@router.get("/runs/{run_id}")
def get_run(run_id: str, pm: ProcessManager = Depends(get_process_manager)):
    run = pm.get_run(run_id)
    if not run:
        raise HTTPException(status_code=404, detail=f"Run '{run_id}' not found")
    return run.to_dict()


@router.get("/forms")
def get_workflow_forms():
    """Return workflow form definitions for the Studio frontend."""
    from mixersystem.studio._forms_fallback import WORKFLOW_FORMS

    return WORKFLOW_FORMS
