import { prisma } from "@/lib/prisma";
import type { Prisma, SpanType } from "@agentlens/database";

type EventCreate = Prisma.EventCreateWithoutTraceInput;
type DecisionCreate = Prisma.DecisionPointCreateWithoutTraceInput;

interface DemoSpan {
  id: string;
  name: string;
  type: SpanType;
  status: "RUNNING" | "COMPLETED" | "ERROR";
  parentSpanId?: string;
  input?: Prisma.InputJsonValue;
  output?: Prisma.InputJsonValue;
  tokenCount?: number;
  costUsd?: number;
  durationMs?: number;
  startedAt: Date;
  endedAt?: Date;
  metadata?: Prisma.InputJsonValue;
  statusMessage?: string;
}

function daysAgo(days: number, offsetMs = 0): Date {
  const d = new Date();
  d.setDate(d.getDate() - days);
  d.setMilliseconds(d.getMilliseconds() + offsetMs);
  return d;
}

function endDate(start: Date, durationMs: number): Date {
  return new Date(start.getTime() + durationMs);
}

export async function seedDemoData(userId: string) {
  const traces = [
    createSimpleChatTrace(userId),
    createMultiToolAgentTrace(userId),
    createRagPipelineTrace(userId),
    createErrorHandlingTrace(userId),
    createLongRunningWorkflowTrace(userId),
    createCodeAnalysisTrace(userId),
    createWebSearchTrace(userId),
  ];

  for (const traceFn of traces) {
    const { trace, spans, events, decisions } = traceFn;

    await prisma.trace.create({
      data: {
        ...trace,
        spans: { create: spans },
        events: { create: events },
        decisionPoints: { create: decisions },
      },
    });
  }

  await prisma.user.update({
    where: { id: userId },
    data: { demoSeeded: true },
  });
}

function createSimpleChatTrace(userId: string) {
  const start = daysAgo(1);
  const duration = 1240;
  const spanId = `demo-span-chat-${userId.slice(0, 8)}`;

  return {
    trace: {
      name: "Simple Chat Completion",
      userId,
      status: "COMPLETED" as const,
      isDemo: true,
      tags: ["openai", "chat"],
      metadata: { model: "gpt-4o", temperature: 0.7 },
      totalCost: 0.0032,
      totalTokens: 245,
      totalDuration: duration,
      startedAt: start,
      endedAt: endDate(start, duration),
    },
    spans: [
      {
        id: spanId,
        name: "chat.completions.create",
        type: "LLM_CALL" as const,
        status: "COMPLETED" as const,
        input: { messages: [{ role: "user", content: "Explain quantum computing in simple terms" }] },
        output: { content: "Quantum computing uses quantum bits (qubits) that can exist in multiple states simultaneously..." },
        tokenCount: 245,
        costUsd: 0.0032,
        durationMs: duration,
        startedAt: start,
        endedAt: endDate(start, duration),
        metadata: { model: "gpt-4o", provider: "openai" },
      },
    ],
    events: [] as EventCreate[],
    decisions: [] as DecisionCreate[],
  };
}

function createMultiToolAgentTrace(userId: string) {
  const start = daysAgo(2);
  const parentId = `demo-span-agent-${userId.slice(0, 8)}`;
  const toolIds = [
    `demo-span-tool1-${userId.slice(0, 8)}`,
    `demo-span-tool2-${userId.slice(0, 8)}`,
    `demo-span-tool3-${userId.slice(0, 8)}`,
  ];
  const llmId = `demo-span-llm-${userId.slice(0, 8)}`;

  return {
    trace: {
      name: "Multi-Tool Agent Run",
      userId,
      status: "COMPLETED" as const,
      isDemo: true,
      tags: ["agent", "tools", "production"],
      metadata: { agent: "research-assistant", run_id: "demo-run-001" },
      totalCost: 0.0187,
      totalTokens: 1823,
      totalDuration: 8420,
      startedAt: start,
      endedAt: endDate(start, 8420),
    },
    spans: [
      {
        id: parentId,
        name: "research-assistant",
        type: "AGENT" as const,
        status: "COMPLETED" as const,
        durationMs: 8420,
        startedAt: start,
        endedAt: endDate(start, 8420),
        metadata: { max_iterations: 5 },
      },
      {
        id: toolIds[0],
        name: "web_search",
        type: "TOOL_CALL" as const,
        status: "COMPLETED" as const,
        parentSpanId: parentId,
        input: { query: "latest AI research papers 2026" },
        output: { results: [{ title: "Scaling Laws for Neural Language Models", url: "https://arxiv.org/..." }] },
        durationMs: 2100,
        startedAt: endDate(start, 200),
        endedAt: endDate(start, 2300),
      },
      {
        id: toolIds[1],
        name: "document_reader",
        type: "TOOL_CALL" as const,
        status: "COMPLETED" as const,
        parentSpanId: parentId,
        input: { url: "https://arxiv.org/..." },
        output: { content: "Abstract: We study empirical scaling laws for language model performance..." },
        durationMs: 1800,
        startedAt: endDate(start, 2400),
        endedAt: endDate(start, 4200),
      },
      {
        id: toolIds[2],
        name: "summarizer",
        type: "TOOL_CALL" as const,
        status: "COMPLETED" as const,
        parentSpanId: parentId,
        input: { text: "Abstract: We study empirical scaling laws..." },
        output: { summary: "The paper examines how language model performance scales with compute, data, and model size." },
        durationMs: 1500,
        startedAt: endDate(start, 4300),
        endedAt: endDate(start, 5800),
      },
      {
        id: llmId,
        name: "gpt-4o-synthesis",
        type: "LLM_CALL" as const,
        status: "COMPLETED" as const,
        parentSpanId: parentId,
        input: { messages: [{ role: "system", content: "Synthesize research findings" }] },
        output: { content: "Based on the latest research, AI scaling laws suggest..." },
        tokenCount: 1823,
        costUsd: 0.0187,
        durationMs: 2400,
        startedAt: endDate(start, 5900),
        endedAt: endDate(start, 8300),
        metadata: { model: "gpt-4o" },
      },
    ],
    events: [] as EventCreate[],
    decisions: [
      {
        type: "TOOL_SELECTION" as const,
        reasoning: "User asked about latest AI research, need web search to get current information",
        chosen: { tool: "web_search", args: { query: "latest AI research papers 2026" } },
        alternatives: [{ tool: "memory_lookup" }, { tool: "knowledge_base" }],
        parentSpanId: parentId,
        durationMs: 150,
        costUsd: 0.001,
        timestamp: endDate(start, 100),
      },
      {
        type: "ROUTING" as const,
        reasoning: "Search results contain arxiv links, routing to document reader for full content",
        chosen: { next_step: "document_reader" },
        alternatives: [{ next_step: "direct_response" }, { next_step: "ask_clarification" }],
        parentSpanId: parentId,
        durationMs: 80,
        costUsd: 0.0005,
        timestamp: endDate(start, 2350),
      },
    ],
  };
}

function createRagPipelineTrace(userId: string) {
  const start = daysAgo(3);
  const retrievalId = `demo-span-retrieval-${userId.slice(0, 8)}`;
  const embeddingId = `demo-span-embed-${userId.slice(0, 8)}`;
  const genId = `demo-span-gen-${userId.slice(0, 8)}`;

  return {
    trace: {
      name: "RAG Pipeline",
      userId,
      status: "COMPLETED" as const,
      isDemo: true,
      tags: ["rag", "retrieval", "embeddings"],
      metadata: { pipeline: "knowledge-qa", version: "2.1" },
      totalCost: 0.0091,
      totalTokens: 892,
      totalDuration: 4350,
      startedAt: start,
      endedAt: endDate(start, 4350),
    },
    spans: [
      {
        id: embeddingId,
        name: "embed_query",
        type: "LLM_CALL" as const,
        status: "COMPLETED" as const,
        input: { text: "How does our refund policy work?" },
        output: { embedding: [0.023, -0.041, 0.089] },
        tokenCount: 12,
        costUsd: 0.00001,
        durationMs: 320,
        startedAt: start,
        endedAt: endDate(start, 320),
        metadata: { model: "text-embedding-3-small" },
      },
      {
        id: retrievalId,
        name: "vector_search",
        type: "MEMORY_OP" as const,
        status: "COMPLETED" as const,
        input: { embedding: [0.023, -0.041, 0.089], top_k: 5 },
        output: { documents: [{ id: "doc-1", score: 0.92, title: "Refund Policy v3" }] },
        durationMs: 180,
        startedAt: endDate(start, 400),
        endedAt: endDate(start, 580),
        metadata: { index: "company-docs", results_count: 5 },
      },
      {
        id: genId,
        name: "generate_answer",
        type: "LLM_CALL" as const,
        status: "COMPLETED" as const,
        input: { messages: [{ role: "system", content: "Answer using the provided context" }] },
        output: { content: "Our refund policy allows returns within 30 days of purchase..." },
        tokenCount: 880,
        costUsd: 0.009,
        durationMs: 3600,
        startedAt: endDate(start, 650),
        endedAt: endDate(start, 4250),
        metadata: { model: "gpt-4o-mini" },
      },
    ],
    events: [] as EventCreate[],
    decisions: [
      {
        type: "MEMORY_RETRIEVAL" as const,
        reasoning: "Query about refund policy matched knowledge base with high confidence",
        chosen: { source: "vector_search", confidence: 0.92 },
        alternatives: [{ source: "web_search" }, { source: "ask_human" }],
        durationMs: 50,
        timestamp: endDate(start, 350),
      },
    ],
  };
}

function createErrorHandlingTrace(userId: string) {
  const start = daysAgo(5);
  const spanId = `demo-span-err-${userId.slice(0, 8)}`;

  return {
    trace: {
      name: "Error Handling Example",
      userId,
      status: "ERROR" as const,
      isDemo: true,
      tags: ["error", "rate-limit"],
      metadata: { error_type: "RateLimitError", retries: 3 },
      totalCost: 0.0,
      totalTokens: 0,
      totalDuration: 15200,
      startedAt: start,
      endedAt: endDate(start, 15200),
    },
    spans: [
      {
        id: spanId,
        name: "chat.completions.create",
        type: "LLM_CALL" as const,
        status: "ERROR" as const,
        statusMessage: "RateLimitError: Rate limit exceeded. Retry after 30s.",
        input: { messages: [{ role: "user", content: "Analyze this dataset" }] },
        durationMs: 15200,
        startedAt: start,
        endedAt: endDate(start, 15200),
        metadata: { model: "gpt-4o", retry_count: 3 },
      },
    ],
    events: [
      {
        type: "ERROR" as const,
        name: "RateLimitError",
        spanId,
        metadata: { message: "Rate limit exceeded", status_code: 429 },
        timestamp: endDate(start, 5000),
      },
      {
        type: "RETRY" as const,
        name: "Retry attempt 1",
        spanId,
        metadata: { attempt: 1, backoff_ms: 2000 },
        timestamp: endDate(start, 7000),
      },
      {
        type: "RETRY" as const,
        name: "Retry attempt 2",
        spanId,
        metadata: { attempt: 2, backoff_ms: 4000 },
        timestamp: endDate(start, 11000),
      },
      {
        type: "ERROR" as const,
        name: "Max retries exceeded",
        spanId,
        metadata: { message: "Giving up after 3 retries", final_status: 429 },
        timestamp: endDate(start, 15200),
      },
    ],
    decisions: [
      {
        type: "RETRY" as const,
        reasoning: "Received 429 rate limit error, exponential backoff strategy selected",
        chosen: { action: "retry", strategy: "exponential_backoff", max_retries: 3 },
        alternatives: [{ action: "fail_immediately" }, { action: "switch_model" }],
        durationMs: 20,
        timestamp: endDate(start, 5100),
      },
    ],
  };
}

function createLongRunningWorkflowTrace(userId: string) {
  const start = daysAgo(6);
  const totalDuration = 34500;
  const chainId = `demo-span-chain-${userId.slice(0, 8)}`;
  const spanPrefix = `demo-span-wf-${userId.slice(0, 8)}`;

  const stepNames = [
    "data_ingestion",
    "preprocessing",
    "feature_extraction",
    "model_inference",
    "post_processing",
    "validation",
    "output_formatting",
  ];

  const spans: DemoSpan[] = [
    {
      id: chainId,
      name: "data-processing-pipeline",
      type: "CHAIN",
      status: "COMPLETED",
      durationMs: totalDuration,
      startedAt: start,
      endedAt: endDate(start, totalDuration),
      metadata: { pipeline: "batch-analysis", version: "1.4" },
    },
  ];

  let elapsed = 200;
  for (let i = 0; i < stepNames.length; i++) {
    const stepDuration = 2000 + Math.floor(Math.random() * 5000);
    spans.push({
      id: `${spanPrefix}-${i}`,
      name: stepNames[i],
      type: i === 3 ? "LLM_CALL" : "CUSTOM",
      status: "COMPLETED",
      durationMs: stepDuration,
      startedAt: endDate(start, elapsed),
      endedAt: endDate(start, elapsed + stepDuration),
      metadata: { step: i + 1, total_steps: stepNames.length },
    });
    elapsed += stepDuration + 100;
  }

  return {
    trace: {
      name: "Long-Running Workflow",
      userId,
      status: "COMPLETED" as const,
      isDemo: true,
      tags: ["pipeline", "batch", "production"],
      metadata: { pipeline: "batch-analysis", records_processed: 1250 },
      totalCost: 0.042,
      totalTokens: 4200,
      totalDuration: totalDuration,
      startedAt: start,
      endedAt: endDate(start, totalDuration),
    },
    spans: spans.map((s) => ({
      ...s,
      parentSpanId: s.id === chainId ? undefined : chainId,
    })),
    events: [] as EventCreate[],
    decisions: [
      {
        type: "PLANNING" as const,
        reasoning: "Large dataset detected, selecting batch processing strategy with parallel feature extraction",
        chosen: { strategy: "batch_parallel", batch_size: 50 },
        alternatives: [{ strategy: "sequential" }, { strategy: "streaming" }],
        parentSpanId: chainId,
        durationMs: 100,
        timestamp: endDate(start, 100),
      },
    ],
  };
}

function createCodeAnalysisTrace(userId: string) {
  const start = daysAgo(4);
  const agentId = `demo-span-codeagent-${userId.slice(0, 8)}`;
  const readId = `demo-span-read-${userId.slice(0, 8)}`;
  const analyzeId = `demo-span-analyze-${userId.slice(0, 8)}`;

  return {
    trace: {
      name: "Code Review Agent",
      userId,
      status: "COMPLETED" as const,
      isDemo: true,
      tags: ["code-review", "agent"],
      metadata: { repo: "acme/backend", pr_number: 142 },
      totalCost: 0.015,
      totalTokens: 1450,
      totalDuration: 6200,
      startedAt: start,
      endedAt: endDate(start, 6200),
    },
    spans: [
      {
        id: agentId,
        name: "code-review-agent",
        type: "AGENT" as const,
        status: "COMPLETED" as const,
        durationMs: 6200,
        startedAt: start,
        endedAt: endDate(start, 6200),
      },
      {
        id: readId,
        name: "read_diff",
        type: "TOOL_CALL" as const,
        status: "COMPLETED" as const,
        parentSpanId: agentId,
        input: { pr_number: 142 },
        output: { files_changed: 5, additions: 120, deletions: 30 },
        durationMs: 800,
        startedAt: endDate(start, 100),
        endedAt: endDate(start, 900),
      },
      {
        id: analyzeId,
        name: "analyze_code",
        type: "LLM_CALL" as const,
        status: "COMPLETED" as const,
        parentSpanId: agentId,
        input: { diff: "...", instructions: "Review for bugs and style issues" },
        output: { review: "Found 2 potential issues: 1) Missing null check on line 45, 2) Unused import" },
        tokenCount: 1450,
        costUsd: 0.015,
        durationMs: 5100,
        startedAt: endDate(start, 1000),
        endedAt: endDate(start, 6100),
        metadata: { model: "gpt-4o" },
      },
    ],
    events: [] as EventCreate[],
    decisions: [
      {
        type: "TOOL_SELECTION" as const,
        reasoning: "Need to read PR diff before analyzing code",
        chosen: { tool: "read_diff", args: { pr_number: 142 } },
        alternatives: [{ tool: "read_file" }, { tool: "list_files" }],
        parentSpanId: agentId,
        durationMs: 60,
        timestamp: endDate(start, 50),
      },
    ],
  };
}

function createWebSearchTrace(userId: string) {
  const start = daysAgo(0, -3600000);
  const searchId = `demo-span-websearch-${userId.slice(0, 8)}`;

  return {
    trace: {
      name: "Web Search Agent",
      userId,
      status: "COMPLETED" as const,
      isDemo: true,
      tags: ["search", "web"],
      metadata: { query: "AgentLens observability" },
      totalCost: 0.002,
      totalTokens: 180,
      totalDuration: 2800,
      startedAt: start,
      endedAt: endDate(start, 2800),
    },
    spans: [
      {
        id: searchId,
        name: "web_search",
        type: "TOOL_CALL" as const,
        status: "COMPLETED" as const,
        input: { query: "AgentLens observability platform" },
        output: { results_count: 10, top_result: "https://agentlens.vectry.tech" },
        durationMs: 2800,
        startedAt: start,
        endedAt: endDate(start, 2800),
      },
    ],
    events: [] as EventCreate[],
    decisions: [] as DecisionCreate[],
  };
}
