"""Evolution API routes"""

import logging

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

from agentkit.core.protocol import EvolutionEvent

logger = logging.getLogger(__name__)

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


class TriggerEvolutionRequest(BaseModel):
    agent_name: str
    skill_name: str | None = None


def _get_evolution_store(request: Request):
    store = getattr(request.app.state, "evolution_store", None)
    if store is None:
        raise HTTPException(
            status_code=503,
            detail="Evolution store is not configured",
        )
    return store


@router.get("/events")
async def list_evolution_events(
    agent_name: str | None = None,
    event_type: str | None = None,
    limit: int = 50,
    offset: int = 0,
    req: Request = None,
):
    """List evolution events with pagination and filtering."""
    store = _get_evolution_store(req)
    try:
        events = await store.list_events(
            agent_name=agent_name,
            change_type=event_type,
        )
    except Exception as e:
        logger.error(f"Failed to list evolution events: {e}")
        raise HTTPException(status_code=500, detail="Failed to list evolution events")

    # Apply pagination
    total = len(events)
    paginated = events[offset : offset + limit]
    return {
        "items": paginated,
        "total": total,
        "limit": limit,
        "offset": offset,
    }


@router.get("/skills/{skill_name}/versions")
async def get_skill_versions(skill_name: str, req: Request = None):
    """Get version history for a skill."""
    store = _get_evolution_store(req)
    try:
        versions = await store.list_skill_versions(skill_name)
    except Exception as e:
        logger.error(f"Failed to get skill versions for '{skill_name}': {e}")
        raise HTTPException(status_code=500, detail="Failed to get skill versions")
    return {"skill_name": skill_name, "versions": versions}


@router.post("/trigger")
async def trigger_evolution(request: TriggerEvolutionRequest, req: Request = None):
    """Manually trigger evolution for an agent/skill."""
    store = _get_evolution_store(req)
    pool = getattr(req.app.state, "agent_pool", None)

    # Find the agent
    agent = None
    if pool is not None:
        agent = pool.get_agent(request.agent_name)

    if agent is None:
        raise HTTPException(
            status_code=404,
            detail=f"Agent '{request.agent_name}' not found",
        )

    # Check if agent supports evolution
    if not hasattr(agent, "evolve_after_task"):
        raise HTTPException(
            status_code=400,
            detail=f"Agent '{request.agent_name}' does not support evolution",
        )

    # Record a trigger event in the evolution store
    event = EvolutionEvent(
        agent_name=request.agent_name,
        change_type="manual_trigger",
        before={"skill_name": request.skill_name},
        after={"status": "triggered"},
        metrics=None,
    )
    try:
        event_id = await store.record(event)
    except Exception as e:
        logger.error(f"Failed to record trigger event: {e}")
        raise HTTPException(status_code=500, detail="Failed to trigger evolution")

    return {
        "event_id": event_id,
        "agent_name": request.agent_name,
        "skill_name": request.skill_name,
        "status": "triggered",
    }


@router.get("/ab-tests")
async def list_ab_tests(
    status: str | None = None,
    limit: int = 50,
    req: Request = None,
):
    """List A/B test configurations and results."""
    store = _get_evolution_store(req)

    # InMemoryEvolutionStore and PersistentEvolutionStore store AB results
    # per test_id. We need to aggregate all test IDs.
    ab_results_attr = None
    if hasattr(store, "_ab_results"):
        ab_results_attr = store._ab_results
    elif hasattr(store, "_Session"):
        # PersistentEvolutionStore — query from DB
        try:
            from sqlalchemy import select
            from agentkit.evolution.models import ABTestResultModel

            with store._Session() as session:
                stmt = select(ABTestResultModel)
                if status:
                    stmt = stmt.where(ABTestResultModel.variant == status)
                stmt = stmt.order_by(ABTestResultModel.created_at.desc())
                entries = session.execute(stmt).scalars().all()
                results = [
                    {
                        "id": e.id,
                        "test_id": e.test_id,
                        "variant": e.variant,
                        "score": e.score,
                        "sample_count": e.sample_count,
                        "created_at": e.created_at.isoformat() if e.created_at else None,
                    }
                    for e in entries
                ]
                return {"items": results[:limit], "total": len(results)}
        except Exception as e:
            logger.error(f"Failed to list A/B tests from persistent store: {e}")
            raise HTTPException(status_code=500, detail="Failed to list A/B tests")

    if ab_results_attr is not None:
        # InMemoryEvolutionStore
        all_results = []
        for test_id, entries in ab_results_attr.items():
            for entry in entries:
                if status and entry.get("variant") != status:
                    continue
                all_results.append(entry)
        all_results.sort(key=lambda x: x.get("created_at", ""), reverse=True)
        total = len(all_results)
        return {"items": all_results[:limit], "total": total}

    # EvolutionStore (async SQLAlchemy) — no direct AB results access
    return {"items": [], "total": 0}
