import { useEffect, useState, useCallback } from 'react';
import { createLogger } from '@automaker/utils/logger';
import { useAppStore } from '@/store/app-store';
import { getElectronAPI } from '@/lib/electron';
import { Card, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { File, Folder, FolderOpen, ChevronRight, ChevronDown, Code, RefreshCw } from 'lucide-react';
import { Spinner } from '@/components/ui/spinner';
import { cn } from '@/lib/utils';

const logger = createLogger('CodeView');

interface FileTreeNode {
  name: string;
  path: string;
  isDirectory: boolean;
  children?: FileTreeNode[];
  isExpanded?: boolean;
}

const IGNORE_PATTERNS = ['node_modules', '.git', '.next', 'dist', 'build', '.DS_Store', '*.log'];

const shouldIgnore = (name: string) => {
  return IGNORE_PATTERNS.some((pattern) => {
    if (pattern.startsWith('*')) {
      return name.endsWith(pattern.slice(1));
    }
    return name === pattern;
  });
};

export function CodeView() {
  const { currentProject } = useAppStore();
  const [fileTree, setFileTree] = useState<FileTreeNode[]>([]);
  const [selectedFile, setSelectedFile] = useState<string | null>(null);
  const [fileContent, setFileContent] = useState<string>('');
  const [isLoading, setIsLoading] = useState(true);
  const [expandedFolders, setExpandedFolders] = useState<Set<string>>(new Set());

  // Load directory tree
  const loadTree = useCallback(async () => {
    if (!currentProject) return;

    setIsLoading(true);
    try {
      const api = getElectronAPI();
      const result = await api.readdir(currentProject.path);

      if (result.success && result.entries) {
        const entries = result.entries
          .filter((e) => !shouldIgnore(e.name))
          .sort((a, b) => {
            // Directories first
            if (a.isDirectory && !b.isDirectory) return -1;
            if (!a.isDirectory && b.isDirectory) return 1;
            return a.name.localeCompare(b.name);
          })
          .map((e) => ({
            name: e.name,
            path: `${currentProject.path}/${e.name}`,
            isDirectory: e.isDirectory,
          }));

        setFileTree(entries);
      }
    } catch (error) {
      logger.error('Failed to load file tree:', error);
    } finally {
      setIsLoading(false);
    }
  }, [currentProject]);

  useEffect(() => {
    loadTree();
  }, [loadTree]);

  // Load subdirectory
  const loadSubdirectory = async (path: string): Promise<FileTreeNode[]> => {
    try {
      const api = getElectronAPI();
      const result = await api.readdir(path);

      if (result.success && result.entries) {
        return result.entries
          .filter((e) => !shouldIgnore(e.name))
          .sort((a, b) => {
            if (a.isDirectory && !b.isDirectory) return -1;
            if (!a.isDirectory && b.isDirectory) return 1;
            return a.name.localeCompare(b.name);
          })
          .map((e) => ({
            name: e.name,
            path: `${path}/${e.name}`,
            isDirectory: e.isDirectory,
          }));
      }
    } catch (error) {
      logger.error('Failed to load subdirectory:', error);
    }
    return [];
  };

  // Load file content
  const loadFileContent = async (path: string) => {
    try {
      const api = getElectronAPI();
      const result = await api.readFile(path);

      if (result.success && result.content) {
        setFileContent(result.content);
        setSelectedFile(path);
      }
    } catch (error) {
      logger.error('Failed to load file:', error);
    }
  };

  // Toggle folder expansion
  const toggleFolder = async (node: FileTreeNode) => {
    const newExpanded = new Set(expandedFolders);

    if (expandedFolders.has(node.path)) {
      newExpanded.delete(node.path);
    } else {
      newExpanded.add(node.path);

      // Load children if not already loaded
      if (!node.children) {
        const children = await loadSubdirectory(node.path);
        // Update the tree with children
        const updateTree = (nodes: FileTreeNode[]): FileTreeNode[] => {
          return nodes.map((n) => {
            if (n.path === node.path) {
              return { ...n, children };
            }
            if (n.children) {
              return { ...n, children: updateTree(n.children) };
            }
            return n;
          });
        };
        setFileTree(updateTree(fileTree));
      }
    }

    setExpandedFolders(newExpanded);
  };

  // Render file tree node
  const renderNode = (node: FileTreeNode, depth: number = 0) => {
    const isExpanded = expandedFolders.has(node.path);
    const isSelected = selectedFile === node.path;

    return (
      <div key={node.path}>
        <div
          className={cn(
            'flex items-center gap-2 py-1 px-2 rounded cursor-pointer hover:bg-muted/50',
            isSelected && 'bg-muted'
          )}
          style={{ paddingLeft: `${depth * 16 + 8}px` }}
          onClick={() => {
            if (node.isDirectory) {
              toggleFolder(node);
            } else {
              loadFileContent(node.path);
            }
          }}
          data-testid={`file-tree-item-${node.name}`}
        >
          {node.isDirectory ? (
            <>
              {isExpanded ? (
                <ChevronDown className="w-4 h-4 text-muted-foreground shrink-0" />
              ) : (
                <ChevronRight className="w-4 h-4 text-muted-foreground shrink-0" />
              )}
              {isExpanded ? (
                <FolderOpen className="w-4 h-4 text-primary shrink-0" />
              ) : (
                <Folder className="w-4 h-4 text-primary shrink-0" />
              )}
            </>
          ) : (
            <>
              <span className="w-4" />
              <File className="w-4 h-4 text-muted-foreground shrink-0" />
            </>
          )}
          <span className="text-sm truncate">{node.name}</span>
        </div>
        {node.isDirectory && isExpanded && node.children && (
          <div>{node.children.map((child) => renderNode(child, depth + 1))}</div>
        )}
      </div>
    );
  };

  if (!currentProject) {
    return (
      <div className="flex-1 flex items-center justify-center" data-testid="code-view-no-project">
        <p className="text-muted-foreground">No project selected</p>
      </div>
    );
  }

  if (isLoading) {
    return (
      <div className="flex-1 flex items-center justify-center" data-testid="code-view-loading">
        <Spinner size="lg" />
      </div>
    );
  }

  return (
    <div className="flex-1 flex flex-col overflow-hidden content-bg" data-testid="code-view">
      {/* Header */}
      <div className="flex items-center justify-between p-4 border-b border-white/10 bg-zinc-950/50 backdrop-blur-md">
        <div className="flex items-center gap-3">
          <Code className="w-5 h-5 text-muted-foreground" />
          <div>
            <h1 className="text-xl font-bold">Code Explorer</h1>
            <p className="text-sm text-muted-foreground">{currentProject.name}</p>
          </div>
        </div>
        <Button variant="outline" size="sm" onClick={loadTree} data-testid="refresh-tree">
          <RefreshCw className="w-4 h-4 mr-2" />
          Refresh
        </Button>
      </div>

      {/* Split View */}
      <div className="flex-1 flex overflow-hidden">
        {/* File Tree */}
        <div className="w-64 border-r overflow-y-auto" data-testid="file-tree">
          <div className="p-2">{fileTree.map((node) => renderNode(node))}</div>
        </div>

        {/* Code Preview */}
        <div className="flex-1 overflow-hidden">
          {selectedFile ? (
            <div className="h-full flex flex-col">
              <div className="px-4 py-2 border-b bg-muted/30">
                <p className="text-sm font-mono text-muted-foreground truncate">
                  {selectedFile.replace(currentProject.path, '')}
                </p>
              </div>
              <Card className="flex-1 m-4 overflow-hidden">
                <CardContent className="p-0 h-full">
                  <pre className="p-4 h-full overflow-auto text-sm font-mono whitespace-pre-wrap">
                    <code data-testid="code-content">{fileContent}</code>
                  </pre>
                </CardContent>
              </Card>
            </div>
          ) : (
            <div className="flex-1 flex items-center justify-center">
              <p className="text-muted-foreground">Select a file to view its contents</p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
