/**
 * E2E Test Suite Management API
 * 
 * CRUD operations for test suites, test cases, runs, and results.
 */

import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/db';

export const dynamic = 'force-dynamic';

// GET - List test suites or get specific suite
export async function GET(request: NextRequest) {
  try {
    const searchParams = request.nextUrl.searchParams;
    const suiteId = searchParams.get('suiteId');
    const includeTestCases = searchParams.get('includeTestCases') === 'true';
    const includeRuns = searchParams.get('includeRuns') === 'true';

    if (suiteId) {
      const suite = await prisma.e2ETestSuite.findUnique({
        where: { id: suiteId },
        include: {
          E2ETestCase: includeTestCases,
          E2ETestRun: includeRuns ? {
            orderBy: { runNumber: 'desc' },
            take: 10
          } : false
        }
      });

      if (!suite) {
        return NextResponse.json({ error: 'Suite not found' }, { status: 404 });
      }

      return NextResponse.json({ success: true, suite });
    }

    const suites = await prisma.e2ETestSuite.findMany({
      orderBy: { createdAt: 'desc' },
      include: {
        _count: {
          select: { E2ETestCase: true, E2ETestRun: true }
        }
      }
    });

    return NextResponse.json({ success: true, suites });
  } catch (error: any) {
    console.error('Error fetching test suites:', error);
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}

// POST - Create test suite or add test cases
export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const { action = 'createSuite', ...data } = body;

    switch (action) {
      case 'createSuite': {
        const { name, description, version, environment, metadata } = data;
        const suite = await prisma.e2ETestSuite.create({
          data: {
            name,
            description,
            version: version || '1.0',
            environment: environment || 'staging',
            metadata: metadata || {}
          }
        });
        return NextResponse.json({ success: true, suite });
      }

      case 'addTestCase': {
        const { suiteId, testCaseId, scenario, objective, expectedOutcome, priority, category, preconditions, testSteps, testData } = data;
        const testCase = await prisma.e2ETestCase.create({
          data: {
            suiteId,
            testCaseId,
            scenario,
            objective,
            expectedOutcome,
            priority: priority || 'medium',
            category: category || 'happy_path',
            preconditions: preconditions || [],
            testSteps: testSteps || [],
            testData: testData || {}
          }
        });
        return NextResponse.json({ success: true, testCase });
      }

      case 'addBulkTestCases': {
        const { suiteId, testCases } = data;
        const created = await prisma.e2ETestCase.createMany({
          data: testCases.map((tc: any) => ({
            suiteId,
            testCaseId: tc.testCaseId,
            scenario: tc.scenario,
            objective: tc.objective,
            expectedOutcome: tc.expectedOutcome,
            priority: tc.priority || 'medium',
            category: tc.category || 'happy_path',
            preconditions: tc.preconditions || [],
            testSteps: tc.testSteps || [],
            testData: tc.testData || {}
          })),
          skipDuplicates: true
        });
        return NextResponse.json({ success: true, count: created.count });
      }

      case 'startRun': {
        const { suiteId, environment, triggeredBy } = data;
        
        // Get latest run number
        const lastRun = await prisma.e2ETestRun.findFirst({
          where: { suiteId },
          orderBy: { runNumber: 'desc' }
        });

        const runNumber = (lastRun?.runNumber || 0) + 1;

        // Count test cases
        const totalCases = await prisma.e2ETestCase.count({ where: { suiteId } });

        const run = await prisma.e2ETestRun.create({
          data: {
            suiteId,
            runNumber,
            environment: environment || 'staging',
            triggeredBy,
            status: 'running',
            totalCases
          }
        });

        // Create pending results for all test cases
        const testCases = await prisma.e2ETestCase.findMany({ where: { suiteId } });
        await prisma.e2ETestResult.createMany({
          data: testCases.map((tc: any) => ({
            runId: run.id,
            testCaseId: tc.id,
            status: 'pending'
          }))
        });

        return NextResponse.json({ success: true, run });
      }

      case 'updateResult': {
        const { runId, testCaseId, status, errorMessage, stackTrace, durationMs, logs, assertions } = data;
        
        const result = await prisma.e2ETestResult.update({
          where: { runId_testCaseId: { runId, testCaseId } },
          data: {
            status,
            startedAt: status === 'running' ? new Date() : undefined,
            completedAt: ['passed', 'failed', 'blocked', 'skipped'].includes(status) ? new Date() : undefined,
            durationMs,
            errorMessage,
            stackTrace,
            logs: logs || [],
            assertions: assertions || []
          }
        });

        // Update run totals
        const allResults = await prisma.e2ETestResult.findMany({ where: { runId } });
        const passed = allResults.filter((r: any) => r.status === 'passed').length;
        const failed = allResults.filter((r: any) => r.status === 'failed').length;
        const blocked = allResults.filter((r: any) => r.status === 'blocked').length;
        const skipped = allResults.filter((r: any) => r.status === 'skipped').length;
        const completed = passed + failed + blocked + skipped;
        const total = allResults.length;

        await prisma.e2ETestRun.update({
          where: { id: runId },
          data: {
            passedCases: passed,
            failedCases: failed,
            blockedCases: blocked,
            skippedCases: skipped,
            status: completed === total ? (failed > 0 ? 'failed' : 'completed') : 'running',
            completedAt: completed === total ? new Date() : undefined
          }
        });

        return NextResponse.json({ success: true, result });
      }

      default:
        return NextResponse.json({ error: `Unknown action: ${action}` }, { status: 400 });
    }
  } catch (error: any) {
    console.error('Error in test suite operation:', error);
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}

// DELETE - Delete suite or test case
export async function DELETE(request: NextRequest) {
  try {
    const body = await request.json();
    const { suiteId, testCaseId } = body;

    if (testCaseId) {
      await prisma.e2ETestCase.delete({ where: { id: testCaseId } });
    } else if (suiteId) {
      await prisma.e2ETestSuite.delete({ where: { id: suiteId } });
    }

    return NextResponse.json({ success: true });
  } catch (error: any) {
    console.error('Error deleting:', error);
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}
