"""Plan generation API router (rule engine + parameter registry)."""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session

from ..database import get_db
from ..models.project import Project
from ..schemas.generation import (
    ParameterRegistryResponse,
    RangeRecommendRequest, RangeRecommendation,
    PlanGenerateRequest, PlanGenerateResponse,
)
from ..services.rule_engine import (
    get_parameter_registry, get_parameter,
    recommend_range, generate_plan, BoundaryConditions,
)

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


# ---------------------------------------------------------------------------
# Parameter registry
# ---------------------------------------------------------------------------

@router.get("/scan-parameters", response_model=ParameterRegistryResponse)
def list_scan_parameters(category: str | None = None):
    """List all scannable Motor-CAD parameters with their metadata.

    Used by the frontend plan editor to populate variable dropdowns.
    """
    params = get_parameter_registry()
    if category:
        params = [p for p in params if p["category"].lower() == category.lower()]
    return ParameterRegistryResponse(total=len(params), parameters=params)


# ---------------------------------------------------------------------------
# Range recommendation
# ---------------------------------------------------------------------------

@router.post("/recommend-range", response_model=RangeRecommendation)
def recommend_scan_range(request: RangeRecommendRequest):
    """Recommend a scan range for a parameter based on boundary conditions."""
    p = get_parameter(request.parameter_name)
    if p is None:
        raise HTTPException(
            status_code=404,
            detail=f"Unknown parameter: {request.parameter_name}",
        )
    bc = BoundaryConditions.from_dict(request.boundary_conditions or {})
    rng = recommend_range(request.parameter_name, bc)
    return RangeRecommendation(**rng)


# ---------------------------------------------------------------------------
# Plan generation
# ---------------------------------------------------------------------------

@router.post("/generate-plan", response_model=PlanGenerateResponse)
def generate_plan_from_bc(request: PlanGenerateRequest):
    """Generate a recommended simulation plan from boundary conditions.

    Uses the rule engine to recommend scan ranges for each parameter and
    returns a plan draft that can be edited and then saved via the plans API.
    """
    bc = BoundaryConditions.from_dict(request.boundary_conditions or {})
    plan = generate_plan(
        bc=bc,
        param_names=request.parameter_names,
        model_path=request.model_path,
    )
    return PlanGenerateResponse(**plan)


@router.post("/projects/{project_id}/generate-plan", response_model=PlanGenerateResponse)
def generate_plan_for_project(
    project_id: int,
    request: PlanGenerateRequest,
    db: Session = Depends(get_db),
):
    """Generate a plan for an existing project using its boundary conditions.

    The project's stored boundary conditions are used as the base; any
    boundary_conditions in the request override them.
    """
    project = db.query(Project).filter(Project.id == project_id).first()
    if not project:
        raise HTTPException(status_code=404, detail="Project not found")

    # Merge: project BC as base, request BC overrides
    merged_bc = dict(project.get_boundary_conditions())
    if request.boundary_conditions:
        merged_bc.update(request.boundary_conditions)
    # Ensure topology from project
    merged_bc.setdefault("topology", project.topology or "SSSR")

    bc = BoundaryConditions.from_dict(merged_bc)
    model_path = request.model_path or project.model_path or ""
    plan = generate_plan(
        bc=bc,
        param_names=request.parameter_names,
        model_path=model_path,
    )
    return PlanGenerateResponse(**plan)
