"""Experience case API router (CRUD + import from results for Phase 2)."""
import json
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session

from ..database import get_db
from ..models.experience_case import ExperienceCase
from ..models.simulation_plan import SimulationPlan
from ..models.simulation_result import SimulationResult

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


def _case_to_dict(case: ExperienceCase) -> dict:
    return {
        "id": case.id,
        "source_plan_id": case.source_plan_id or "",
        "topology": case.topology or "SSSR",
        "model_path": case.model_path or "",
        "params": case.get_params(),
        "metrics": case.get_metrics(),
        "conclusion": case.conclusion or "",
        "tags": [t.strip() for t in (case.tags or "").split(",") if t.strip()],
        "rating": case.rating or 0,
        "created_at": case.created_at,
    }


def _generate_conclusion(params: dict, metrics: dict) -> str:
    """Auto-generate a simple conclusion from metrics values.

    Uses ASCII-only text. Describes key performance indicators.
    """
    parts = []
    tavg = metrics.get("tavg_nm")
    if tavg is not None:
        parts.append(f"avg torque {tavg:.3f} Nm")
    eff = metrics.get("efficiency_pct")
    if eff is not None:
        parts.append(f"efficiency {eff:.1f}%")
    ripple = metrics.get("ripple_pct")
    if ripple is not None:
        parts.append(f"ripple {ripple:.2f}%")
    losses = metrics.get("total_losses_w")
    if losses is not None:
        parts.append(f"total losses {losses:.1f} W")

    if not parts:
        return "Imported from simulation result"

    # Add quality assessment
    if eff is not None and tavg is not None:
        if eff >= 85 and tavg >= 1.0:
            parts.append("good overall performance")
        elif eff < 80:
            parts.append("efficiency below target")

    return "; ".join(parts)


# ---------------------------------------------------------------------------
# CRUD
# ---------------------------------------------------------------------------

@router.get("")
def list_experience(
    topology: str | None = None,
    tag: str | None = None,
    skip: int = 0,
    limit: int = 50,
    db: Session = Depends(get_db),
):
    """List experience cases with filters."""
    query = db.query(ExperienceCase)
    if topology:
        query = query.filter(ExperienceCase.topology == topology)
    if tag:
        query = query.filter(ExperienceCase.tags.contains(tag))
    total = query.count()
    cases = query.order_by(ExperienceCase.created_at.desc()).offset(skip).limit(limit).all()
    return {"total": total, "items": [_case_to_dict(c) for c in cases]}


@router.post("", status_code=201)
def create_experience(
    data: dict,
    db: Session = Depends(get_db),
):
    """Create an experience case from a dict."""
    case = ExperienceCase(
        source_plan_id=data.get("source_plan_id", ""),
        topology=data.get("topology", "SSSR"),
        model_path=data.get("model_path", ""),
        conclusion=data.get("conclusion", ""),
        tags=",".join(data.get("tags", [])),
        rating=data.get("rating", 0),
    )
    case.params_json = json.dumps(data.get("params", {}), ensure_ascii=False)
    case.metrics_json = json.dumps(data.get("metrics", {}), ensure_ascii=False)
    db.add(case)
    db.commit()
    db.refresh(case)
    return _case_to_dict(case)


@router.get("/{case_id}")
def get_experience(case_id: int, db: Session = Depends(get_db)):
    """Get an experience case by ID."""
    case = db.query(ExperienceCase).filter(ExperienceCase.id == case_id).first()
    if not case:
        raise HTTPException(status_code=404, detail="Experience case not found")
    return _case_to_dict(case)


@router.put("/{case_id}")
def update_experience(
    case_id: int,
    data: dict,
    db: Session = Depends(get_db),
):
    """Update an experience case (conclusion, tags, rating, params, metrics)."""
    case = db.query(ExperienceCase).filter(ExperienceCase.id == case_id).first()
    if not case:
        raise HTTPException(status_code=404, detail="Experience case not found")

    if "conclusion" in data:
        case.conclusion = data["conclusion"]
    if "tags" in data:
        case.tags = ",".join(data["tags"])
    if "rating" in data:
        case.rating = int(data["rating"])
    if "params" in data:
        case.params_json = json.dumps(data["params"], ensure_ascii=False)
    if "metrics" in data:
        case.metrics_json = json.dumps(data["metrics"], ensure_ascii=False)
    if "topology" in data:
        case.topology = data["topology"]
    if "model_path" in data:
        case.model_path = data["model_path"]

    db.commit()
    db.refresh(case)
    return _case_to_dict(case)


@router.delete("/{case_id}", status_code=204)
def delete_experience(case_id: int, db: Session = Depends(get_db)):
    """Delete an experience case."""
    case = db.query(ExperienceCase).filter(ExperienceCase.id == case_id).first()
    if not case:
        raise HTTPException(status_code=404, detail="Experience case not found")
    db.delete(case)
    db.commit()
    return None


# ---------------------------------------------------------------------------
# Import from simulation results
# ---------------------------------------------------------------------------

@router.post("/from-plan/{plan_id}")
def import_from_plan(
    plan_id: int,
    data: dict | None = None,
    db: Session = Depends(get_db),
):
    """Import all OK results from a plan into the experience library.

    Creates one experience case per OK simulation result.
    Auto-generates conclusion if not provided.

    Request body (optional):
        tags: list of tags to apply to all imported cases
        rating: default rating (0-5)
        auto_conclusion: bool (default True) - generate conclusion from metrics
    """
    plan = db.query(SimulationPlan).filter(SimulationPlan.id == plan_id).first()
    if not plan:
        raise HTTPException(status_code=404, detail="Plan not found")

    data = data or {}
    tags = data.get("tags", ["auto-imported"])
    rating = int(data.get("rating", 0))
    auto_conclusion = data.get("auto_conclusion", True)

    results = db.query(SimulationResult).filter(
        SimulationResult.plan_id == plan_id,
        SimulationResult.status == "OK",
    ).all()

    if not results:
        return {"imported": 0, "skipped": 0, "message": "No OK results found in plan"}

    # Get topology and model_path from plan_json if available
    plan_dict = plan.get_plan_dict() if hasattr(plan, "get_plan_dict") else {}
    topology = plan_dict.get("topology") or getattr(plan, "topology", None) or "SSSR"
    model_path = plan_dict.get("model_path") or getattr(plan, "model_path", "") or ""

    imported = 0
    skipped = 0
    for r in results:
        params = r.get_params()
        metrics = r.get_metrics()
        if not params or not metrics:
            skipped += 1
            continue

        conclusion = ""
        if auto_conclusion:
            conclusion = _generate_conclusion(params, metrics)

        case = ExperienceCase(
            source_plan_id=plan.plan_id or str(plan.id),
            topology=topology,
            model_path=model_path,
            conclusion=conclusion,
            tags=",".join(tags),
            rating=rating,
        )
        case.params_json = json.dumps(params, ensure_ascii=False)
        case.metrics_json = json.dumps(metrics, ensure_ascii=False)
        db.add(case)
        imported += 1

    db.commit()
    return {
        "imported": imported,
        "skipped": skipped,
        "plan_id": plan.id,
        "plan_uuid": plan.plan_id,
        "message": f"Imported {imported} cases from plan",
    }


@router.post("/from-result/{result_id}")
def import_from_result(
    result_id: int,
    data: dict | None = None,
    db: Session = Depends(get_db),
):
    """Import a single simulation result into the experience library."""
    result = db.query(SimulationResult).filter(SimulationResult.id == result_id).first()
    if not result:
        raise HTTPException(status_code=404, detail="Result not found")
    if result.status != "OK":
        raise HTTPException(status_code=400, detail=f"Cannot import non-OK result (status={result.status})")

    data = data or {}
    plan = db.query(SimulationPlan).filter(SimulationPlan.id == result.plan_id).first()

    params = result.get_params()
    metrics = result.get_metrics()
    conclusion = data.get("conclusion") or _generate_conclusion(params, metrics)
    tags = data.get("tags", ["auto-imported"])
    rating = int(data.get("rating", 0))

    # Get topology and model_path from plan_json if available
    plan_dict = plan.get_plan_dict() if plan and hasattr(plan, "get_plan_dict") else {}
    topology = plan_dict.get("topology") or (getattr(plan, "topology", None) if plan else None) or "SSSR"
    model_path = plan_dict.get("model_path") or (getattr(plan, "model_path", "") if plan else "") or ""

    case = ExperienceCase(
        source_plan_id=plan.plan_id if plan else str(result.plan_id),
        topology=topology,
        model_path=model_path,
        conclusion=conclusion,
        tags=",".join(tags),
        rating=rating,
    )
    case.params_json = json.dumps(params, ensure_ascii=False)
    case.metrics_json = json.dumps(metrics, ensure_ascii=False)
    db.add(case)
    db.commit()
    db.refresh(case)
    return _case_to_dict(case)
