"""api.v1.traces — Execution trace query."""
from __future__ import annotations
import json
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException
from agentpaas.api.deps import get_tenant, get_database
from agentpaas.api.middleware.auth import TenantContext
from agentpaas.db.models import Database

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

@router.get("/{run_id}")
async def get_trace(run_id: str, tenant: TenantContext = Depends(get_tenant), db: Database = Depends(get_database)):
    """Return run row plus structured step-level trace (BUG-06 fix)."""
    run = db.fetchone("SELECT * FROM runs WHERE id = ? AND tenant_id = ?", (run_id, tenant.tenant_id))
    if not run:
        raise HTTPException(404, {"error": {"code": "RUN_NOT_FOUND"}})

    # Parse persisted trace JSON (BUG-06)
    trace_steps = []
    raw_trace = run.get("trace_json") or "[]"
    try:
        trace_steps = json.loads(raw_trace)
    except (json.JSONDecodeError, TypeError):
        trace_steps = []

    # If no DB trace, try workspace trace file
    if not trace_steps and run.get("workspace_path"):
        import os
        trace_file = os.path.join(run["workspace_path"], "trace.json")
        if os.path.isfile(trace_file):
            try:
                with open(trace_file, encoding="utf-8") as f:
                    trace_steps = json.load(f)
            except Exception:
                pass

    return {
        **dict(run),
        "trace": trace_steps,
        "trace_count": len(trace_steps),
    }


@router.get("/{run_id}/tools")
async def get_tool_audit(
    run_id: str,
    tenant: TenantContext = Depends(get_tenant),
    db: Database = Depends(get_database),
):
    """SEC-11: Get ToolGateway audit log for a run."""
    run = db.fetchone(
        "SELECT * FROM runs WHERE id = ? AND tenant_id = ?",
        (run_id, tenant.tenant_id)
    )
    if not run:
        raise HTTPException(404, {"error": {"code": "RUN_NOT_FOUND"}})

    # Return tool audit entries from the run's error/output fields
    audit = []
    if run.get("output"):
        try:
            output = json.loads(run["output"]) if isinstance(run["output"], str) else run["output"]
            if isinstance(output, dict) and "tool_audit" in output:
                audit = output["tool_audit"]
        except (json.JSONDecodeError, TypeError):
            pass
    return {"run_id": run_id, "tool_audit": audit}


@router.get("/{run_id}/confirm")
async def get_pending_confirmation(
    run_id: str,
    tenant: TenantContext = Depends(get_tenant),
    db: Database = Depends(get_database),
):
    """SEC-12/SEC-30: Query the run's pending HIGH-risk tool confirmation."""
    run = db.fetchone(
        "SELECT id FROM runs WHERE id = ? AND tenant_id = ?",
        (run_id, tenant.tenant_id))
    if not run:
        raise HTTPException(404, {"error": {"code": "RUN_NOT_FOUND"}})
    from agentpaas.engine.confirmations import get_pending
    pending = get_pending(run_id)
    return {"run_id": run_id, "pending": pending}


@router.post("/{run_id}/confirm")
async def confirm_tool_call(
    run_id: str,
    body: Optional[dict] = None,
    tenant: TenantContext = Depends(get_tenant),
    db: Database = Depends(get_database),
):
    """SEC-12/SEC-30: Confirm (or deny) a paused HIGH-risk tool call.

    AUDIT_2026-06-11 ③: 接通真实确认机制 —— ToolGateway 的
    confirm_callback 阻塞在 engine.confirmations 登记处上，这里 resolve。
    Body: {"approved": true|false}，缺省 true（放行）。
    """
    run = db.fetchone(
        "SELECT id FROM runs WHERE id = ? AND tenant_id = ?",
        (run_id, tenant.tenant_id))
    if not run:
        raise HTTPException(404, {"error": {"code": "RUN_NOT_FOUND"}})

    approved = True
    if isinstance(body, dict) and "approved" in body:
        approved = bool(body["approved"])

    from agentpaas.engine.confirmations import resolve
    if not resolve(run_id, approved):
        raise HTTPException(
            404, {"error": {"code": "NO_PENDING_CONFIRMATION",
                            "message": "该 run 当前没有等待确认的工具调用（可能已超时拒绝）"}})
    return {"run_id": run_id,
            "status": "confirmed" if approved else "denied"}
