// components/diff-viewer/UnifiedView.tsx
import React, { useState, useMemo } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { 
  FileText, 
  Plus, 
  Minus, 
  Copy,
  Download,
  ChevronDown,
  ChevronRight
} from 'lucide-react';
import { DiffFile, DiffPreferences } from './DiffViewerContext';

interface UnifiedViewProps {
  files: DiffFile[];
  selectedFile: DiffFile | null;
  onFileSelect: (filePath: string) => void;
  theme: string;
  preferences: DiffPreferences;
}

interface DiffLine {
  type: 'added' | 'removed' | 'unchanged' | 'context';
  content: string;
  lineNumber?: number;
}

const UnifiedView: React.FC<UnifiedViewProps> = ({
  files,
  selectedFile,
  onFileSelect,
  theme,
  preferences
}) => {
  const [expandedHunks, setExpandedHunks] = useState<Set<string>>(new Set());

  // Parse diff content into structured format
  const parseDiffContent = (diffContent: string): DiffLine[] => {
    if (!diffContent) return [];

    const lines = diffContent.split('\n');
    const diffLines: DiffLine[] = [];
    let lineNumber = 0;

    for (const line of lines) {
      if (line.startsWith('@@')) {
        // Parse hunk header
        const match = line.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);
        if (match) {
          lineNumber = parseInt(match[3]) - 1;
        }
        diffLines.push({ type: 'context', content: line });
      } else if (line.startsWith('+')) {
        lineNumber++;
        diffLines.push({
          type: 'added',
          content: line.substring(1),
          lineNumber
        });
      } else if (line.startsWith('-')) {
        diffLines.push({
          type: 'removed',
          content: line.substring(1),
          lineNumber: undefined
        });
      } else {
        lineNumber++;
        diffLines.push({
          type: 'unchanged',
          content: line.substring(1),
          lineNumber
        });
      }
    }

    return diffLines;
  };

  // Group diff lines into hunks
  const groupIntoHunks = (diffLines: DiffLine[]) => {
    const hunks: { header: string; lines: DiffLine[] }[] = [];
    let currentHunk: { header: string; lines: DiffLine[] } | null = null;

    for (const line of diffLines) {
      if (line.type === 'context' && line.content.startsWith('@@')) {
        if (currentHunk) {
          hunks.push(currentHunk);
        }
        currentHunk = { header: line.content, lines: [] };
      } else if (currentHunk) {
        currentHunk.lines.push(line);
      }
    }

    if (currentHunk) {
      hunks.push(currentHunk);
    }

    return hunks;
  };

  const diffLines = useMemo(() => {
    if (!selectedFile?.diff_content) return [];
    return parseDiffContent(selectedFile.diff_content);
  }, [selectedFile]);

  const hunks = useMemo(() => {
    return groupIntoHunks(diffLines);
  }, [diffLines]);

  const toggleHunk = (hunkIndex: number) => {
    const hunkId = `${selectedFile?.file_path}-${hunkIndex}`;
    setExpandedHunks(prev => {
      const newSet = new Set(prev);
      if (newSet.has(hunkId)) {
        newSet.delete(hunkId);
      } else {
        newSet.add(hunkId);
      }
      return newSet;
    });
  };

  const copyToClipboard = (text: string) => {
    navigator.clipboard.writeText(text);
  };

  const downloadDiff = () => {
    if (!selectedFile?.diff_content) return;
    
    const blob = new Blob([selectedFile.diff_content], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${selectedFile.file_path}.diff`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  const getLineClass = (type: DiffLine['type']) => {
    switch (type) {
      case 'added':
        return 'bg-green-50 dark:bg-green-900/20 border-l-4 border-green-500';
      case 'removed':
        return 'bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500';
      case 'unchanged':
        return 'bg-gray-50 dark:bg-gray-800/50';
      case 'context':
        return 'bg-blue-50 dark:bg-blue-900/20 font-mono text-sm';
      default:
        return '';
    }
  };

  const getLineIcon = (type: DiffLine['type']) => {
    switch (type) {
      case 'added':
        return <Plus className="h-3 w-3 text-green-600" />;
      case 'removed':
        return <Minus className="h-3 w-3 text-red-600" />;
      default:
        return null;
    }
  };

  const getLinePrefix = (type: DiffLine['type']) => {
    switch (type) {
      case 'added':
        return '+';
      case 'removed':
        return '-';
      case 'unchanged':
        return ' ';
      case 'context':
        return '@';
      default:
        return ' ';
    }
  };

  return (
    <div className="h-full flex flex-col">
      {/* File tabs */}
      <div className="border-b">
        <Tabs value={selectedFile?.file_path || ''} onValueChange={onFileSelect}>
          <TabsList className="w-full justify-start">
            {files.map((file) => (
              <TabsTrigger 
                key={file.file_path} 
                value={file.file_path}
                className="flex items-center space-x-2"
              >
                <FileText className="h-4 w-4" />
                <span className="truncate max-w-32">{file.file_path.split('/').pop()}</span>
                <Badge 
                  variant={
                    file.change_type === 'added' ? 'default' :
                    file.change_type === 'modified' ? 'secondary' :
                    file.change_type === 'deleted' ? 'destructive' : 'outline'
                  }
                  className="ml-1"
                >
                  {file.change_type}
                </Badge>
              </TabsTrigger>
            ))}
          </TabsList>
        </Tabs>
      </div>

      {/* File info and controls */}
      {selectedFile && (
        <div className="p-4 border-b bg-muted/50">
          <div className="flex items-center justify-between">
            <div className="flex items-center space-x-4">
              <div>
                <h3 className="font-medium">{selectedFile.file_path}</h3>
                <div className="flex items-center space-x-2 text-sm text-muted-foreground">
                  <span>{selectedFile.change_type}</span>
                  {selectedFile.diff_size_bytes && (
                    <span>• {(selectedFile.diff_size_bytes / 1024).toFixed(1)} KB</span>
                  )}
                </div>
              </div>
            </div>
            
            <div className="flex items-center space-x-2">
              <Button
                variant="outline"
                size="sm"
                onClick={() => copyToClipboard(selectedFile.diff_content || '')}
              >
                <Copy className="h-4 w-4 mr-2" />
                Copy
              </Button>
              <Button
                variant="outline"
                size="sm"
                onClick={downloadDiff}
              >
                <Download className="h-4 w-4 mr-2" />
                Download
              </Button>
            </div>
          </div>
        </div>
      )}

      {/* Diff content */}
      <div className="flex-1 overflow-hidden h-[500px]">
        <ScrollArea className="h-full">
          <div className="font-mono text-sm">
            {hunks.map((hunk, hunkIndex) => {
              const hunkId = `${selectedFile?.file_path}-${hunkIndex}`;
              const isExpanded = expandedHunks.has(hunkId);
              
              return (
                <div key={hunkIndex} className="border-b last:border-b-0">
                  <div 
                    className="bg-blue-100 dark:bg-blue-900/30 px-4 py-2 cursor-pointer hover:bg-blue-200 dark:hover:bg-blue-900/50"
                    onClick={() => toggleHunk(hunkIndex)}
                  >
                    <div className="flex items-center justify-between">
                      <span className="font-mono text-sm">{hunk.header}</span>
                      <div className="flex items-center space-x-2">
                        <Button variant="ghost" size="sm">
                          {isExpanded ? (
                            <>
                              <ChevronDown className="h-4 w-4 mr-1" />
                              Collapse
                            </>
                          ) : (
                            <>
                              <ChevronRight className="h-4 w-4 mr-1" />
                              Expand
                            </>
                          )}
                        </Button>
                      </div>
                    </div>
                  </div>
                  
                  {isExpanded && (
                    <div>
                      {hunk.lines.map((line, lineIndex) => (
                        <div
                          key={lineIndex}
                          className={`px-4 py-1 flex items-center space-x-2 ${getLineClass(line.type)}`}
                        >
                          <div className="w-8 text-right text-xs text-muted-foreground">
                            {line.lineNumber || ''}
                          </div>
                          <div className="w-4 flex justify-center">
                            {getLineIcon(line.type)}
                          </div>
                          <div className="w-4 text-center font-mono text-xs">
                            {getLinePrefix(line.type)}
                          </div>
                          <div className="flex-1">
                            <code className="text-sm">{line.content}</code>
                          </div>
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        </ScrollArea>
      </div>
    </div>
  );
};

export default UnifiedView;
