"""Trajectory trace API endpoints."""
from __future__ import annotations

import os

from aiohttp import web


async def list_traces(request: web.Request) -> web.Response:
    """List traces, optionally filtered by project/source/days."""
    store = request.app["store"]
    project = request.rel_url.query.get("project")
    source = request.rel_url.query.get("source")
    status = request.rel_url.query.get("status")
    days_raw = request.rel_url.query.get("days")
    limit_raw = request.rel_url.query.get("limit")
    days = int(days_raw) if days_raw else None
    limit = int(limit_raw) if limit_raw else 50
    traces = await store.list_traces(
        project=project, source=source, status=status, days=days, limit=limit,
    )
    return web.json_response(traces)


async def get_trace(request: web.Request) -> web.Response:
    """Full trace with spans."""
    store = request.app["store"]
    trace_id = request.match_info["trace_id"]
    trace = await store.get_trace(trace_id)
    if trace is None:
        raise web.HTTPNotFound(reason=f"Trace not found: {trace_id}")
    spans = await store.list_spans(trace_id)
    trace["spans"] = spans
    return web.json_response(trace)


async def get_trace_execution(request: web.Request) -> web.Response:
    """Execution turns for a trace."""
    store = request.app["store"]
    trace_id = request.match_info["trace_id"]
    trace = await store.get_trace(trace_id)
    if trace is None:
        raise web.HTTPNotFound(reason=f"Trace not found: {trace_id}")
    turns = await store.list_execution_turns(trace_id=trace_id)
    return web.json_response({"trace_id": trace_id, "turns": turns})


async def get_trace_raw(request: web.Request) -> web.Response:
    """Raw agent.log JSONL for a trace's tasks."""
    store = request.app["store"]
    trace_id = request.match_info["trace_id"]
    trace = await store.get_trace(trace_id)
    if trace is None:
        raise web.HTTPNotFound(reason=f"Trace not found: {trace_id}")
    spans = await store.list_spans(trace_id)
    results_dir = request.app.get("results_dir", "results")
    lines: list[str] = []
    for span in spans:
        task_id = span.get("task_id")
        if task_id:
            log_path = os.path.join(results_dir, task_id, "agent.log")
            if os.path.exists(log_path):
                with open(log_path) as f:
                    lines.append(f"# --- task: {task_id} ---\n")
                    lines.append(f.read())
    return web.Response(
        text="".join(lines),
        content_type="application/x-ndjson",
    )


async def trace_stats(request: web.Request) -> web.Response:
    """Aggregate stats — traces/day, cost/project."""
    store = request.app["store"]
    project = request.rel_url.query.get("project")
    days_raw = request.rel_url.query.get("days")
    days = int(days_raw) if days_raw else 30
    stats = await store.get_trace_stats(project=project, days=days)
    return web.json_response(stats)


async def export_traces(request: web.Request) -> web.Response:
    """Research export — JSONL of traces with spans."""
    store = request.app["store"]
    days_raw = request.rel_url.query.get("days")
    project = request.rel_url.query.get("project")
    days = int(days_raw) if days_raw else 30

    import json

    traces = await store.list_traces(project=project, days=days, limit=10000)
    lines: list[str] = []
    for trace in traces:
        spans = await store.list_spans(trace["trace_id"])
        trace["spans"] = spans
        lines.append(json.dumps(trace))

    return web.Response(
        text="\n".join(lines),
        content_type="application/x-ndjson",
        headers={"Content-Disposition": "attachment; filename=traces-export.jsonl"},
    )
