'use client';

import { useCallback, useRef, useState, useMemo } from 'react';
import ReactFlow, {
  Background,
  Controls,
  MiniMap,
  Node,
  Edge,
  Connection,
  ReactFlowProvider,
  useReactFlow,
  Panel,
  BackgroundVariant,
} from 'reactflow';
import 'reactflow/dist/style.css';

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 { Separator } from '@/components/ui/separator';
import { Input } from '@/components/ui/input';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  Play,
  Code,
  Trash2,
  Undo,
  Redo,
  Save,
  Download,
  Upload,
  Search,
  Zap,
  GitBranch,
  Box,
  Hash,
  Globe,
  Settings,
  Copy,
  Check,
  AlertTriangle,
} from 'lucide-react';

import { useVisualScriptStore } from '@/stores/visual-script-store';
import {
  ALL_NODES,
  CATEGORY_COLORS,
  NodeCategory,
  NodeDefinition,
  getNodesByCategory,
} from '@/lib/visual-scripting/node-definitions';
import {
  generateCode,
  validateScript,
  Platform,
  NodeData,
} from '@/lib/visual-scripting/code-generator';
import { CustomNode } from './nodes/CustomNode';
import { toast } from 'sonner';

// Custom node types
const nodeTypes = {
  custom: CustomNode,
};

// Category icons
const CATEGORY_ICONS: Record<NodeCategory, React.ReactNode> = {
  events: <Zap className="h-4 w-4" />,
  logic: <GitBranch className="h-4 w-4" />,
  actions: <Play className="h-4 w-4" />,
  data: <Hash className="h-4 w-4" />,
  references: <Globe className="h-4 w-4" />,
  custom: <Settings className="h-4 w-4" />,
};

interface VisualScriptingCanvasProps {
  platform: Platform;
  onCodeGenerated?: (code: string) => void;
}

function VisualScriptingCanvasInner({
  platform,
  onCodeGenerated,
}: VisualScriptingCanvasProps) {
  const reactFlowWrapper = useRef<HTMLDivElement>(null);
  const { screenToFlowPosition } = useReactFlow();

  const {
    nodes,
    edges,
    onNodesChange,
    onEdgesChange,
    onConnect,
    addNode,
    clearScript,
    undo,
    redo,
    setGeneratedCode,
    generatedCode,
    history,
    historyIndex,
  } = useVisualScriptStore();

  const [searchQuery, setSearchQuery] = useState('');
  const [showCodePreview, setShowCodePreview] = useState(false);
  const [validationResult, setValidationResult] = useState<{
    valid: boolean;
    errors: string[];
    warnings: string[];
  } | null>(null);
  const [copied, setCopied] = useState(false);

  // Filter nodes by search and category
  const filteredNodes = useMemo(() => {
    if (!searchQuery) return ALL_NODES;
    const query = searchQuery.toLowerCase();
    return ALL_NODES.filter(
      (n) =>
        n.label.toLowerCase().includes(query) ||
        n.description.toLowerCase().includes(query) ||
        n.category.toLowerCase().includes(query)
    );
  }, [searchQuery]);

  // Handle node drop from palette
  const onDrop = useCallback(
    (event: React.DragEvent) => {
      event.preventDefault();

      const nodeType = event.dataTransfer.getData('application/reactflow');
      if (!nodeType) return;

      const nodeDef = ALL_NODES.find((n) => n.type === nodeType);
      if (!nodeDef) return;

      const position = screenToFlowPosition({
        x: event.clientX,
        y: event.clientY,
      });

      const newNode: Node<NodeData> = {
        id: `${nodeType}-${Date.now()}`,
        type: 'custom',
        position,
        data: {
          type: nodeType,
          label: nodeDef.label,
          values: {},
        },
      };

      addNode(newNode);
    },
    [screenToFlowPosition, addNode]
  );

  const onDragOver = useCallback((event: React.DragEvent) => {
    event.preventDefault();
    event.dataTransfer.dropEffect = 'move';
  }, []);

  // Generate code from nodes
  const handleGenerateCode = useCallback(() => {
    const result = generateCode(nodes, edges, platform);
    setGeneratedCode(result.code);
    onCodeGenerated?.(result.code);

    const validation = validateScript(nodes, edges, platform);
    setValidationResult(validation);

    if (result.errors.length > 0) {
      toast.error(`Generation errors: ${result.errors.join(', ')}`);
    } else if (result.warnings.length > 0) {
      toast.warning(`Warnings: ${result.warnings.join(', ')}`);
    } else {
      toast.success('Code generated successfully!');
    }

    setShowCodePreview(true);
  }, [nodes, edges, platform, setGeneratedCode, onCodeGenerated]);

  // Copy code to clipboard
  const handleCopyCode = useCallback(async () => {
    await navigator.clipboard.writeText(generatedCode);
    setCopied(true);
    toast.success('Code copied to clipboard!');
    setTimeout(() => setCopied(false), 2000);
  }, [generatedCode]);

  // Drag start from palette
  const onDragStart = (event: React.DragEvent, nodeType: string) => {
    event.dataTransfer.setData('application/reactflow', nodeType);
    event.dataTransfer.effectAllowed = 'move';
  };

  const categories: NodeCategory[] = [
    'events',
    'logic',
    'actions',
    'data',
    'references',
  ];

  return (
    <div className="flex h-full w-full">
      {/* Node Palette (Left Panel) */}
      <div className="w-64 border-r bg-card flex flex-col">
        <div className="p-3 border-b">
          <div className="relative">
            <Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
            <Input
              placeholder="Search nodes..."
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              className="pl-9 h-9"
            />
          </div>
        </div>

        <Tabs defaultValue="events" className="flex-1 flex flex-col">
          <TabsList className="grid grid-cols-5 mx-2 mt-2">
            {categories.map((cat) => (
              <TabsTrigger
                key={cat}
                value={cat}
                className="px-2"
                title={cat.charAt(0).toUpperCase() + cat.slice(1)}
              >
                {CATEGORY_ICONS[cat]}
              </TabsTrigger>
            ))}
          </TabsList>

          <ScrollArea className="flex-1">
            {categories.map((category) => (
              <TabsContent key={category} value={category} className="mt-0 p-2">
                <div className="space-y-1">
                  {(searchQuery
                    ? filteredNodes.filter((n) => n.category === category)
                    : getNodesByCategory(category)
                  )
                    .filter((n) => n.platforms.includes(platform))
                    .map((nodeDef) => (
                      <NodePaletteItem
                        key={nodeDef.type}
                        node={nodeDef}
                        onDragStart={onDragStart}
                      />
                    ))}
                </div>
              </TabsContent>
            ))}
          </ScrollArea>
        </Tabs>
      </div>

      {/* Main Canvas */}
      <div ref={reactFlowWrapper} className="flex-1 relative">
        <ReactFlow
          nodes={nodes}
          edges={edges}
          onNodesChange={onNodesChange}
          onEdgesChange={onEdgesChange}
          onConnect={onConnect}
          onDrop={onDrop}
          onDragOver={onDragOver}
          nodeTypes={nodeTypes}
          fitView
          snapToGrid
          snapGrid={[15, 15]}
          defaultEdgeOptions={{
            type: 'smoothstep',
            animated: false,
          }}
        >
          <Background variant={BackgroundVariant.Dots} gap={15} size={1} />
          <Controls />
          <MiniMap
            nodeColor={(node) => {
              const def = ALL_NODES.find((n) => n.type === node.data?.type);
              return def?.color || '#6b7280';
            }}
            className="!bg-card"
          />

          {/* Top Toolbar */}
          <Panel position="top-center" className="flex gap-2">
            <Button
              variant="outline"
              size="sm"
              onClick={undo}
              disabled={historyIndex <= 0}
            >
              <Undo className="h-4 w-4 mr-1" />
              Undo
            </Button>
            <Button
              variant="outline"
              size="sm"
              onClick={redo}
              disabled={historyIndex >= history.length - 1}
            >
              <Redo className="h-4 w-4 mr-1" />
              Redo
            </Button>
            <Separator orientation="vertical" className="h-8" />
            <Button variant="outline" size="sm" onClick={clearScript}>
              <Trash2 className="h-4 w-4 mr-1" />
              Clear
            </Button>
            <Separator orientation="vertical" className="h-8" />
            <Button variant="default" size="sm" onClick={handleGenerateCode}>
              <Code className="h-4 w-4 mr-1" />
              Generate Code
            </Button>
          </Panel>

          {/* Platform Badge */}
          <Panel position="top-right">
            <Badge variant="secondary" className="text-xs">
              {platform.toUpperCase()}
            </Badge>
          </Panel>

          {/* Stats */}
          <Panel position="bottom-left" className="text-xs text-muted-foreground">
            {nodes.length} nodes • {edges.length} connections
          </Panel>
        </ReactFlow>
      </div>

      {/* Code Preview Dialog */}
      <Dialog open={showCodePreview} onOpenChange={setShowCodePreview}>
        <DialogContent className="max-w-3xl max-h-[80vh]">
          <DialogHeader>
            <DialogTitle className="flex items-center gap-2">
              <Code className="h-5 w-5" />
              Generated Code
              {validationResult && (
                <Badge
                  variant={validationResult.valid ? 'default' : 'destructive'}
                >
                  {validationResult.valid ? 'Valid' : 'Has Issues'}
                </Badge>
              )}
            </DialogTitle>
          </DialogHeader>

          {validationResult && validationResult.errors.length > 0 && (
            <div className="bg-destructive/10 border border-destructive/20 rounded-md p-3 mb-4">
              <p className="font-medium text-destructive text-sm flex items-center gap-2">
                <AlertTriangle className="h-4 w-4" />
                Errors
              </p>
              <ul className="text-sm text-destructive/80 mt-1 list-disc list-inside">
                {validationResult.errors.map((err, i) => (
                  <li key={i}>{err}</li>
                ))}
              </ul>
            </div>
          )}

          {validationResult && validationResult.warnings.length > 0 && (
            <div className="bg-yellow-500/10 border border-yellow-500/20 rounded-md p-3 mb-4">
              <p className="font-medium text-yellow-600 text-sm flex items-center gap-2">
                <AlertTriangle className="h-4 w-4" />
                Warnings
              </p>
              <ul className="text-sm text-yellow-600/80 mt-1 list-disc list-inside">
                {validationResult.warnings.map((warn, i) => (
                  <li key={i}>{warn}</li>
                ))}
              </ul>
            </div>
          )}

          <ScrollArea className="h-[400px] w-full rounded-md border bg-muted/50">
            <pre className="p-4 text-sm font-mono whitespace-pre-wrap">
              {generatedCode}
            </pre>
          </ScrollArea>

          <div className="flex justify-end gap-2 mt-4">
            <Button variant="outline" onClick={handleCopyCode}>
              {copied ? (
                <Check className="h-4 w-4 mr-1" />
              ) : (
                <Copy className="h-4 w-4 mr-1" />
              )}
              {copied ? 'Copied!' : 'Copy Code'}
            </Button>
            <Button onClick={() => setShowCodePreview(false)}>Done</Button>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}

// Node Palette Item Component
function NodePaletteItem({
  node,
  onDragStart,
}: {
  node: NodeDefinition;
  onDragStart: (event: React.DragEvent, nodeType: string) => void;
}) {
  return (
    <div
      draggable
      onDragStart={(e) => onDragStart(e, node.type)}
      className="flex items-center gap-2 p-2 rounded-md border bg-background hover:bg-accent cursor-grab active:cursor-grabbing transition-colors"
      style={{ borderLeftColor: node.color, borderLeftWidth: 3 }}
    >
      <div
        className="w-6 h-6 rounded flex items-center justify-center text-white"
        style={{ backgroundColor: node.color }}
      >
        {CATEGORY_ICONS[node.category]}
      </div>
      <div className="flex-1 min-w-0">
        <p className="text-sm font-medium truncate">{node.label}</p>
        <p className="text-xs text-muted-foreground truncate">
          {node.description}
        </p>
      </div>
    </div>
  );
}

// Export with provider wrapper
export default function VisualScriptingCanvas(
  props: VisualScriptingCanvasProps
) {
  return (
    <ReactFlowProvider>
      <VisualScriptingCanvasInner {...props} />
    </ReactFlowProvider>
  );
}
