/**
 * Integration Test Runner Component
 * 
 * Superuser-only UI for running comprehensive integration tests.
 * Requires AAL2 if MFA is enrolled.
 */

import { useState, useCallback } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import { Progress } from '@/components/ui/progress';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Badge } from '@/components/ui/badge';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import { useSuperuserGuard } from '@/hooks/useSuperuserGuard';
import { IntegrationTestRunner as TestRunner, allTestSuites, type TestResult } from '@/lib/integrationTests';
import { Play, Square, Download, ChevronDown, CheckCircle2, XCircle, Clock, SkipForward } from 'lucide-react';
import { toast } from 'sonner';

export function IntegrationTestRunner() {
  const superuserGuard = useSuperuserGuard();
  const [selectedSuites, setSelectedSuites] = useState<string[]>(allTestSuites.map(s => s.id));
  const [isRunning, setIsRunning] = useState(false);
  const [results, setResults] = useState<TestResult[]>([]);
  const [runner] = useState(() => new TestRunner((result) => {
    setResults(prev => {
      const existing = prev.findIndex(r => r.id === result.id);
      if (existing >= 0) {
        const updated = [...prev];
        updated[existing] = result;
        return updated;
      }
      return [...prev, result];
    });
  }));

  const toggleSuite = useCallback((suiteId: string) => {
    setSelectedSuites(prev =>
      prev.includes(suiteId)
        ? prev.filter(id => id !== suiteId)
        : [...prev, suiteId]
    );
  }, []);

  const runTests = useCallback(async () => {
    const suitesToRun = allTestSuites.filter(s => selectedSuites.includes(s.id));
    
    if (suitesToRun.length === 0) {
      toast.error('Please select at least one test suite');
      return;
    }

    setIsRunning(true);
    setResults([]);
    runner.reset();
    
    toast.info(`Running ${suitesToRun.length} test suite(s)...`);
    
    try {
      await runner.runAllSuites(suitesToRun);
      const summary = runner.getSummary();
      
      if (summary.failed > 0) {
        toast.error(`Tests completed with ${summary.failed} failure(s)`);
      } else {
        toast.success(`All ${summary.passed} tests passed!`);
      }
    } catch (error) {
      console.error('Test run error:', error);
      toast.error('Test run failed');
    } finally {
      setIsRunning(false);
    }
  }, [selectedSuites, runner]);

  const stopTests = useCallback(() => {
    runner.stop();
    setIsRunning(false);
    toast.info('Test run stopped');
  }, [runner]);

  const exportResults = useCallback(() => {
    const summary = runner.getSummary();
    const exportData = {
      timestamp: new Date().toISOString(),
      summary,
      results: runner.getResults()
    };
    
    const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `integration-tests-${Date.now()}.json`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    
    toast.success('Test results exported');
  }, [runner]);

  // Guard is handled by the route/page, no loading state needed here

  const summary = runner.getSummary();
  const totalTests = allTestSuites
    .filter(s => selectedSuites.includes(s.id))
    .reduce((sum, s) => sum + s.tests.length, 0);
  const progress = totalTests > 0 ? (results.length / totalTests) * 100 : 0;

  return (
    <div className="space-y-6">
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2">
            🧪 Integration Test Runner
          </CardTitle>
          <CardDescription>
            Superuser-only comprehensive testing system. Tests run against real database functions and edge functions.
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-6">
          {/* Suite Selection */}
          <div className="space-y-3">
            <h3 className="font-medium">Select Test Suites:</h3>
            <div className="space-y-2">
              {allTestSuites.map(suite => (
                <div key={suite.id} className="flex items-start space-x-3">
                  <Checkbox
                    id={suite.id}
                    checked={selectedSuites.includes(suite.id)}
                    onCheckedChange={() => toggleSuite(suite.id)}
                    disabled={isRunning}
                  />
                  <div className="space-y-1 flex-1">
                    <label
                      htmlFor={suite.id}
                      className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer"
                    >
                      {suite.name} ({suite.tests.length} tests)
                    </label>
                    <p className="text-sm text-muted-foreground">
                      {suite.description}
                    </p>
                  </div>
                </div>
              ))}
            </div>
          </div>

          {/* Controls */}
          <div className="flex gap-2">
            <Button onClick={runTests} disabled={isRunning || selectedSuites.length === 0}>
              <Play className="w-4 h-4 mr-2" />
              Run Selected
            </Button>
            {isRunning && (
              <Button onClick={stopTests} variant="destructive">
                <Square className="w-4 h-4 mr-2" />
                Stop
              </Button>
            )}
            {results.length > 0 && !isRunning && (
              <Button onClick={exportResults} variant="outline">
                <Download className="w-4 h-4 mr-2" />
                Export Results
              </Button>
            )}
          </div>

          {/* Progress */}
          {results.length > 0 && (
            <div className="space-y-2">
              <div className="flex justify-between text-sm">
                <span>Progress: {results.length}/{totalTests} tests</span>
                <span>{progress.toFixed(0)}%</span>
              </div>
              <Progress value={progress} />
            </div>
          )}

          {/* Summary */}
          {results.length > 0 && (
            <div className="flex gap-4 text-sm">
              <div className="flex items-center gap-2">
                <CheckCircle2 className="w-4 h-4 text-green-500" />
                <span>{summary.passed} passed</span>
              </div>
              <div className="flex items-center gap-2">
                <XCircle className="w-4 h-4 text-destructive" />
                <span>{summary.failed} failed</span>
              </div>
              <div className="flex items-center gap-2">
                <SkipForward className="w-4 h-4 text-muted-foreground" />
                <span>{summary.skipped} skipped</span>
              </div>
              <div className="flex items-center gap-2">
                <Clock className="w-4 h-4" />
                <span>{(summary.totalDuration / 1000).toFixed(2)}s</span>
              </div>
            </div>
          )}
        </CardContent>
      </Card>

      {/* Results */}
      {results.length > 0 && (
        <Card>
          <CardHeader>
            <CardTitle>Test Results</CardTitle>
          </CardHeader>
          <CardContent>
            <ScrollArea className="h-[600px] pr-4">
              <div className="space-y-2">
                {results.map(result => (
                  <Collapsible key={result.id}>
                    <div className="flex items-start gap-3 p-3 rounded-lg border bg-card">
                      <div className="pt-0.5">
                        {result.status === 'pass' && <CheckCircle2 className="w-4 h-4 text-green-500" />}
                        {result.status === 'fail' && <XCircle className="w-4 h-4 text-destructive" />}
                        {result.status === 'skip' && <SkipForward className="w-4 h-4 text-muted-foreground" />}
                        {result.status === 'running' && <Clock className="w-4 h-4 text-blue-500 animate-pulse" />}
                      </div>
                      <div className="flex-1 space-y-1">
                        <div className="flex items-start justify-between gap-2">
                          <div className="space-y-1">
                            <p className="text-sm font-medium">{result.name}</p>
                            <p className="text-xs text-muted-foreground">{result.suite}</p>
                          </div>
                          <div className="flex items-center gap-2">
                            <Badge variant="outline" className="text-xs">
                              {result.duration}ms
                            </Badge>
                            {(result.error || result.details) && (
                              <CollapsibleTrigger asChild>
                                <Button variant="ghost" size="sm" className="h-6 w-6 p-0">
                                  <ChevronDown className="h-3 w-3" />
                                </Button>
                              </CollapsibleTrigger>
                            )}
                          </div>
                        </div>
                        {result.error && (
                          <p className="text-sm text-destructive">{result.error}</p>
                        )}
                      </div>
                    </div>
                    {(result.error || result.details) && (
                      <CollapsibleContent>
                        <div className="ml-7 mt-2 p-3 rounded-lg bg-muted/50 space-y-2">
                          {result.error && result.stack && (
                            <div>
                              <p className="text-xs font-medium mb-1">Stack Trace:</p>
                              <pre className="text-xs whitespace-pre-wrap font-mono bg-background p-2 rounded">
                                {result.stack}
                              </pre>
                            </div>
                          )}
                          {result.details && (
                            <div>
                              <p className="text-xs font-medium mb-1">Details:</p>
                              <pre className="text-xs whitespace-pre-wrap font-mono bg-background p-2 rounded">
                                {JSON.stringify(result.details, null, 2)}
                              </pre>
                            </div>
                          )}
                        </div>
                      </CollapsibleContent>
                    )}
                  </Collapsible>
                ))}
              </div>
            </ScrollArea>
          </CardContent>
        </Card>
      )}
    </div>
  );
}
