import { PrismaClient } from "./apps/web/prisma/generated/client/index.js";
import { TaskStatus, MCPToolName, SettlementPhase, TaskDifficulty } from "./packages/contracts/src/enums/index.js";
import { v4 as uuidv4 } from "uuid";

const prisma = new PrismaClient();

async function main() {
  console.log("=== Idempotency and Payment Flow Test ===");

  // 1. Create a mock task
  const taskId = uuidv4();
  await prisma.task.create({
    data: {
      id: taskId,
      title: "Test Task",
      difficulty: TaskDifficulty.COMPONENT,
      status: TaskStatus.OPEN,
      requirements: "Test requirements",
      base_reward_cents: 500,
    }
  });
  console.log(`[+] Created Task ${taskId}`);

  // 2. Simulate Claim Task (Auth Hold)
  console.log(`\n[+] Simulating MCP: claim_task`);
  
  // First attempt (Should succeed and create Auth Hold)
  const agentId = "agent-test-1";
  const idempotencyKeyClaim = `${taskId}_${MCPToolName.CLAIM_TASK}`;
  
  const claim1 = await prisma.$transaction(async (tx) => {
    // authHold logic
    const existing = await tx.ledgerEntry.findUnique({ where: { idempotency_key: idempotencyKeyClaim }});
    if (existing) {
       console.log("Idempotent hit for claim_task!");
       return existing;
    }
    
    await tx.task.update({
      where: { id: taskId },
      data: { status: TaskStatus.EXECUTING, agent_id: agentId }
    });

    return await tx.ledgerEntry.create({
      data: {
        task_id: taskId,
        phase: SettlementPhase.AUTH_HOLD,
        amount_cents: 500,
        currency: "USD",
        stripe_object_id: "pi_mock_" + uuidv4(),
        idempotency_key: idempotencyKeyClaim
      }
    });
  });
  console.log(`[1] First claim_task attempt created ledger entry: ${claim1.id}`);

  // Second attempt (Should hit idempotency key and NOT duplicate)
  const claim2 = await prisma.$transaction(async (tx) => {
    const existing = await tx.ledgerEntry.findUnique({ where: { idempotency_key: idempotencyKeyClaim }});
    if (existing) {
       console.log("Idempotent hit for claim_task!");
       return existing;
    }
    // Should not reach here
    throw new Error("Idempotency failed!");
  });
  console.log(`[2] Second claim_task attempt returned same entry: ${claim2.id}`);

  // 3. Simulate Submit Solution (Capture)
  console.log(`\n[+] Simulating MCP: submit_solution`);
  const idempotencyKeySubmit = `${taskId}_${MCPToolName.SUBMIT_SOLUTION}`;
  
  const submit1 = await prisma.$transaction(async (tx) => {
    const existing = await tx.ledgerEntry.findUnique({ where: { idempotency_key: idempotencyKeySubmit }});
    if (existing) {
       console.log("Idempotent hit for submit_solution!");
       return existing;
    }

    await tx.task.update({
      where: { id: taskId },
      data: { status: TaskStatus.COMPLETED }
    });

    return await tx.ledgerEntry.create({
      data: {
        task_id: taskId,
        phase: SettlementPhase.CAPTURE,
        amount_cents: 500,
        currency: "USD",
        stripe_object_id: claim1.stripe_object_id,
        idempotency_key: idempotencyKeySubmit
      }
    });
  });
  console.log(`[1] First submit_solution attempt created ledger entry: ${submit1.id}`);

  const submit2 = await prisma.$transaction(async (tx) => {
    const existing = await tx.ledgerEntry.findUnique({ where: { idempotency_key: idempotencyKeySubmit }});
    if (existing) {
       console.log("Idempotent hit for submit_solution!");
       return existing;
    }
    throw new Error("Idempotency failed!");
  });
  console.log(`[2] Second submit_solution attempt returned same entry: ${submit2.id}`);

  // Verify DB state
  const finalTask = await prisma.task.findUnique({ where: { id: taskId }, include: { ledger_entries: true } });
  console.log(`\n=== Final Verification ===`);
  console.log(`Task Status: ${finalTask?.status}`);
  console.log(`Ledger Entries: ${finalTask?.ledger_entries.length}`);
  finalTask?.ledger_entries.forEach(entry => {
    console.log(`  - Phase: ${entry.phase}, Amount: ${entry.amount_cents}, Key: ${entry.idempotency_key}`);
  });

  if (finalTask?.status === TaskStatus.COMPLETED && finalTask.ledger_entries.length === 2) {
    console.log("\n✅ End-to-End Simulation Passed! Idempotency and State transitions are correct.");
  } else {
    console.log("\n❌ Simulation Failed.");
  }
}

main()
  .catch(console.error)
  .finally(async () => {
    await prisma.$disconnect();
  });
