import { useState, useMemo } from 'react';
import { Copy, Download, ChevronRight, ChevronDown, Check } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Input } from '@/components/ui/input';
import { toast } from 'sonner';

interface RawDataViewerProps {
  data: any;
  title?: string;
}

export function RawDataViewer({ data, title = 'Raw Data' }: RawDataViewerProps) {
  const [searchQuery, setSearchQuery] = useState('');
  const [expandedPaths, setExpandedPaths] = useState<Set<string>>(new Set(['root']));
  const [copiedPath, setCopiedPath] = useState<string | null>(null);

  const jsonString = useMemo(() => JSON.stringify(data, null, 2), [data]);

  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(jsonString);
      toast.success('Copied to clipboard');
    } catch (error) {
      toast.error('Failed to copy');
    }
  };

  const handleDownload = () => {
    const blob = new Blob([jsonString], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${title.toLowerCase().replace(/\s+/g, '-')}-${Date.now()}.json`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    toast.success('Download started');
  };

  const togglePath = (path: string) => {
    const newExpanded = new Set(expandedPaths);
    if (newExpanded.has(path)) {
      newExpanded.delete(path);
    } else {
      newExpanded.add(path);
    }
    setExpandedPaths(newExpanded);
  };

  const handleCopyValue = async (value: any, path: string) => {
    try {
      const valueString = typeof value === 'string' ? value : JSON.stringify(value, null, 2);
      await navigator.clipboard.writeText(valueString);
      setCopiedPath(path);
      setTimeout(() => setCopiedPath(null), 2000);
      toast.success('Value copied');
    } catch (error) {
      toast.error('Failed to copy');
    }
  };

  const renderValue = (value: any, key: string, path: string, depth: number = 0): JSX.Element => {
    const isExpanded = expandedPaths.has(path);
    const indent = depth * 20;

    // Filter by search query
    if (searchQuery && !JSON.stringify({ [key]: value }).toLowerCase().includes(searchQuery.toLowerCase())) {
      return <></>;
    }

    if (value === null) {
      return (
        <div className="flex items-center gap-2 py-1" style={{ paddingLeft: `${indent}px` }}>
          <span className="text-sm font-mono text-muted-foreground">{key}:</span>
          <span className="text-sm font-mono text-muted-foreground italic">null</span>
        </div>
      );
    }

    if (typeof value === 'boolean') {
      return (
        <div className="flex items-center gap-2 py-1" style={{ paddingLeft: `${indent}px` }}>
          <span className="text-sm font-mono text-muted-foreground">{key}:</span>
          <span className={`text-sm font-mono ${value ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}`}>
            {value.toString()}
          </span>
        </div>
      );
    }

    if (typeof value === 'number') {
      return (
        <div className="flex items-center gap-2 py-1" style={{ paddingLeft: `${indent}px` }}>
          <span className="text-sm font-mono text-muted-foreground">{key}:</span>
          <span className="text-sm font-mono text-purple-600 dark:text-purple-400">{value}</span>
          <Button
            variant="ghost"
            size="icon"
            className="h-4 w-4 opacity-0 group-hover:opacity-100"
            onClick={() => handleCopyValue(value, path)}
          >
            {copiedPath === path ? <Check className="h-3 w-3" /> : <Copy className="h-3 w-3" />}
          </Button>
        </div>
      );
    }

    if (typeof value === 'string') {
      const isUrl = value.startsWith('http://') || value.startsWith('https://');
      const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
      const isDate = !isNaN(Date.parse(value)) && value.includes('-');

      return (
        <div className="flex items-center gap-2 py-1 group" style={{ paddingLeft: `${indent}px` }}>
          <span className="text-sm font-mono text-muted-foreground">{key}:</span>
          {isUrl ? (
            <a href={value} target="_blank" rel="noopener noreferrer" className="text-sm font-mono text-blue-600 dark:text-blue-400 hover:underline">
              "{value}"
            </a>
          ) : (
            <span className={`text-sm font-mono ${isUuid ? 'text-orange-600 dark:text-orange-400' : isDate ? 'text-cyan-600 dark:text-cyan-400' : 'text-green-600 dark:text-green-400'}`}>
              "{value}"
            </span>
          )}
          <Button
            variant="ghost"
            size="icon"
            className="h-4 w-4 opacity-0 group-hover:opacity-100"
            onClick={() => handleCopyValue(value, path)}
          >
            {copiedPath === path ? <Check className="h-3 w-3" /> : <Copy className="h-3 w-3" />}
          </Button>
        </div>
      );
    }

    if (Array.isArray(value)) {
      return (
        <div className="py-1" style={{ paddingLeft: `${indent}px` }}>
          <div
            className="flex items-center gap-2 cursor-pointer hover:bg-muted/50 rounded px-2 py-1 -ml-2"
            onClick={() => togglePath(path)}
          >
            {isExpanded ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
            <span className="text-sm font-mono text-muted-foreground">{key}:</span>
            <Badge variant="outline" className="text-xs">Array[{value.length}]</Badge>
          </div>
          {isExpanded && (
            <div className="ml-4 border-l border-muted-foreground/20 pl-2">
              {value.map((item, index) => renderValue(item, `[${index}]`, `${path}.${index}`, depth + 1))}
            </div>
          )}
        </div>
      );
    }

    if (typeof value === 'object') {
      const keys = Object.keys(value);
      return (
        <div className="py-1" style={{ paddingLeft: `${indent}px` }}>
          <div
            className="flex items-center gap-2 cursor-pointer hover:bg-muted/50 rounded px-2 py-1 -ml-2"
            onClick={() => togglePath(path)}
          >
            {isExpanded ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
            <span className="text-sm font-mono text-muted-foreground">{key}:</span>
            <Badge variant="outline" className="text-xs">Object ({keys.length} keys)</Badge>
          </div>
          {isExpanded && (
            <div className="ml-4 border-l border-muted-foreground/20 pl-2">
              {keys.map((k) => renderValue(value[k], k, `${path}.${k}`, depth + 1))}
            </div>
          )}
        </div>
      );
    }

    return <></>;
  };

  return (
    <div className="space-y-4">
      {/* Header */}
      <div className="flex items-center justify-between gap-3">
        <h3 className="text-lg font-semibold">{title}</h3>
        <div className="flex items-center gap-2">
          <Button variant="outline" size="sm" onClick={handleCopy}>
            <Copy className="h-4 w-4 mr-2" />
            Copy
          </Button>
          <Button variant="outline" size="sm" onClick={handleDownload}>
            <Download className="h-4 w-4 mr-2" />
            Download
          </Button>
        </div>
      </div>

      {/* Search */}
      <Input
        placeholder="Search in JSON..."
        value={searchQuery}
        onChange={(e) => setSearchQuery(e.target.value)}
        className="max-w-sm"
      />

      {/* JSON Tree */}
      <ScrollArea className="h-[600px] w-full rounded-md border bg-muted/30 p-4">
        <div className="font-mono text-sm">
          {Object.keys(data).map((key) => renderValue(data[key], key, `root.${key}`, 0))}
        </div>
      </ScrollArea>

      {/* Stats */}
      <div className="flex items-center gap-4 text-xs text-muted-foreground">
        <span>Keys: {Object.keys(data).length}</span>
        <span>Size: {(jsonString.length / 1024).toFixed(2)} KB</span>
        <span>Lines: {jsonString.split('\n').length}</span>
      </div>
    </div>
  );
}
