"use client";

import type { JSX } from "react";
import { useEffect, useState } from "react";
import { useParams } from "next/navigation";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { 
  Code2, 
  FolderOpen, 
  File, 
  ChevronRight, 
  ChevronDown, 
  Search,
  Loader2,
  Github,
  RefreshCw,
  FileCode
} from "lucide-react";
import { auth } from "@/lib/firebase/config";
import { db } from "@/lib/firebase/config";
import { doc, getDoc } from "firebase/firestore";
import { toast } from "sonner";
import { cn } from "@/lib/utils";

interface Project {
  githubRepo?: string;
  githubRepoUrl?: string;
  githubDefaultBranch?: string;
}

interface FileNode {
  path: string;
  name: string;
  type: 'file' | 'folder';
  children?: FileNode[];
  size?: number;
  sha?: string;
}

interface GitHubFile {
  path: string;
  sha: string;
  size: number;
  url: string;
}

export default function CodePage() {
  const params = useParams();
  const projectId = params.projectId as string;
  
  const [project, setProject] = useState<Project | null>(null);
  const [loading, setLoading] = useState(true);
  const [loadingFiles, setLoadingFiles] = useState(false);
  const [fileTree, setFileTree] = useState<FileNode[]>([]);
  const [expandedFolders, setExpandedFolders] = useState<Set<string>>(new Set(['/']));
  const [selectedFile, setSelectedFile] = useState<string | null>(null);
  const [fileContent, setFileContent] = useState<string | null>(null);
  const [loadingContent, setLoadingContent] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");

  useEffect(() => {
    fetchProject();
  }, [projectId]);

  const fetchProject = async () => {
    try {
      const projectRef = doc(db, "projects", projectId);
      const projectSnap = await getDoc(projectRef);
      
      if (projectSnap.exists()) {
        const projectData = projectSnap.data() as Project;
        setProject(projectData);
        
        // Auto-load files if GitHub is connected
        if (projectData.githubRepo) {
          await fetchFileTree(projectData.githubRepo, projectData.githubDefaultBranch);
        }
      }
    } catch (error) {
      console.error("Error fetching project:", error);
      toast.error("Failed to load project");
    } finally {
      setLoading(false);
    }
  };

  const fetchFileTree = async (repoFullName: string, branch = 'main') => {
    setLoadingFiles(true);
    try {
      const user = auth.currentUser;
      if (!user) {
        toast.error("Please sign in");
        return;
      }

      const token = await user.getIdToken();
      const [owner, repo] = repoFullName.split('/');

      const response = await fetch(
        `/api/github/repo-tree?owner=${owner}&repo=${repo}&branch=${branch}`,
        {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }
      );

      if (!response.ok) {
        throw new Error("Failed to fetch repository files");
      }

      const data = await response.json();
      const tree = buildFileTree(data.files);
      setFileTree(tree);
      
      toast.success(`Loaded ${data.totalFiles} files from ${repoFullName}`);
    } catch (error) {
      console.error("Error fetching file tree:", error);
      toast.error("Failed to load repository files");
    } finally {
      setLoadingFiles(false);
    }
  };

  const buildFileTree = (files: GitHubFile[]): FileNode[] => {
    const root: FileNode = {
      path: '/',
      name: '/',
      type: 'folder',
      children: [],
    };

    files.forEach((file) => {
      const parts = file.path.split('/');
      let currentNode = root;

      parts.forEach((part, index) => {
        const isFile = index === parts.length - 1;
        const fullPath = parts.slice(0, index + 1).join('/');

        if (!currentNode.children) {
          currentNode.children = [];
        }

        let childNode = currentNode.children.find(child => child.name === part);

        if (!childNode) {
          childNode = {
            path: fullPath,
            name: part,
            type: isFile ? 'file' : 'folder',
            ...(isFile && { size: file.size, sha: file.sha }),
            ...(!isFile && { children: [] }),
          };
          currentNode.children.push(childNode);
        }

        if (!isFile) {
          currentNode = childNode;
        }
      });
    });

    // Sort children recursively
    const sortNodes = (nodes: FileNode[]) => {
      nodes.sort((a, b) => {
        if (a.type === b.type) return a.name.localeCompare(b.name);
        return a.type === 'folder' ? -1 : 1;
      });
      nodes.forEach(node => {
        if (node.children) {
          sortNodes(node.children);
        }
      });
    };

    if (root.children) {
      sortNodes(root.children);
    }

    return root.children || [];
  };

  const fetchFileContent = async (filePath: string) => {
    if (!project?.githubRepo) return;

    setLoadingContent(true);
    setSelectedFile(filePath);
    setFileContent(null);

    try {
      const user = auth.currentUser;
      if (!user) {
        toast.error("Please sign in");
        return;
      }

      const token = await user.getIdToken();
      const [owner, repo] = project.githubRepo.split('/');
      const branch = project.githubDefaultBranch || 'main';

      console.log('[Code Page] Fetching file:', filePath);

      const response = await fetch(
        `/api/github/file-content?owner=${owner}&repo=${repo}&path=${encodeURIComponent(filePath)}&branch=${branch}`,
        {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }
      );

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        console.error('[Code Page] Failed to fetch file:', errorData);
        throw new Error(errorData.error || "Failed to fetch file content");
      }

      const data = await response.json();
      console.log('[Code Page] File loaded:', data.name, `(${data.size} bytes)`);
      setFileContent(data.content);
    } catch (error) {
      console.error("Error fetching file content:", error);
      toast.error(error instanceof Error ? error.message : "Failed to load file content");
      setFileContent(`// Error loading file: ${error instanceof Error ? error.message : 'Unknown error'}`);
    } finally {
      setLoadingContent(false);
    }
  };

  const toggleFolder = (path: string) => {
    const newExpanded = new Set(expandedFolders);
    if (newExpanded.has(path)) {
      newExpanded.delete(path);
    } else {
      newExpanded.add(path);
    }
    setExpandedFolders(newExpanded);
  };

  const renderFileTree = (nodes: FileNode[], level = 0): JSX.Element[] => {
    return nodes
      .filter(node => {
        if (!searchQuery) return true;
        return node.name.toLowerCase().includes(searchQuery.toLowerCase());
      })
      .map((node) => (
        <div key={node.path}>
          <button
            onClick={() => {
              if (node.type === 'folder') {
                toggleFolder(node.path);
              } else {
                fetchFileContent(node.path);
              }
            }}
            className={cn(
              "w-full flex items-center gap-2 px-2 py-1.5 text-sm hover:bg-muted rounded transition-colors",
              selectedFile === node.path && "bg-muted"
            )}
            style={{ paddingLeft: `${level * 12 + 8}px` }}
          >
            {node.type === 'folder' ? (
              <>
                {expandedFolders.has(node.path) ? (
                  <ChevronDown className="h-4 w-4 shrink-0" />
                ) : (
                  <ChevronRight className="h-4 w-4 shrink-0" />
                )}
                <FolderOpen className="h-4 w-4 shrink-0 text-blue-500" />
              </>
            ) : (
              <>
                <div className="w-4" />
                <FileCode className="h-4 w-4 shrink-0 text-muted-foreground" />
              </>
            )}
            <span className="truncate">{node.name}</span>
            {node.size && (
              <span className="ml-auto text-xs text-muted-foreground shrink-0">
                {formatFileSize(node.size)}
              </span>
            )}
          </button>
          {node.type === 'folder' && expandedFolders.has(node.path) && node.children && (
            renderFileTree(node.children, level + 1)
          )}
        </div>
      ));
  };

  const formatFileSize = (bytes: number): string => {
    if (bytes < 1024) return `${bytes} B`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  };

  if (loading) {
    return (
      <div className="flex h-full items-center justify-center">
        <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
      </div>
    );
  }

  if (!project?.githubRepo) {
    return (
      <div className="flex h-full flex-col overflow-hidden">
        <div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
          <div className="flex h-14 items-center gap-2 px-6">
            <Code2 className="h-5 w-5 text-muted-foreground" />
            <h1 className="text-lg font-semibold">Code</h1>
          </div>
        </div>

        <div className="flex-1 overflow-auto p-6">
          <Card className="max-w-2xl mx-auto p-8 text-center">
            <div className="mb-4 rounded-full bg-muted p-4 w-fit mx-auto">
              <Github className="h-8 w-8 text-muted-foreground" />
            </div>
            <h3 className="font-semibold text-lg mb-2">No Repository Connected</h3>
            <p className="text-sm text-muted-foreground mb-4">
              Connect a GitHub repository in the Context section to view your code here
            </p>
            <Button onClick={() => window.location.href = `/${params.workspace}/project/${projectId}/context`}>
              <Github className="h-4 w-4 mr-2" />
              Connect Repository
            </Button>
          </Card>
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-full flex-col overflow-hidden">
      {/* Header */}
      <div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
        <div className="flex h-14 items-center gap-2 px-6">
          <Code2 className="h-5 w-5 text-muted-foreground" />
          <h1 className="text-lg font-semibold">Code</h1>
          <div className="ml-auto flex items-center gap-2">
            <a
              href={project.githubRepoUrl}
              target="_blank"
              rel="noopener noreferrer"
              className="text-sm text-muted-foreground hover:text-foreground flex items-center gap-1"
            >
              <Github className="h-4 w-4" />
              {project.githubRepo}
            </a>
            <Button
              size="sm"
              variant="outline"
              onClick={() => fetchFileTree(project.githubRepo!, project.githubDefaultBranch)}
              disabled={loadingFiles}
            >
              {loadingFiles ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <RefreshCw className="h-4 w-4" />
              )}
            </Button>
          </div>
        </div>
      </div>

      {/* Content */}
      <div className="flex-1 flex overflow-hidden">
        {/* File Tree Sidebar */}
        <div className="w-80 border-r flex flex-col bg-background">
          <div className="p-3 border-b">
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
              <Input
                placeholder="Search files..."
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                className="pl-9"
              />
            </div>
          </div>
          <div className="flex-1 overflow-auto p-2">
            {loadingFiles ? (
              <div className="flex items-center justify-center py-8">
                <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
              </div>
            ) : fileTree.length === 0 ? (
              <div className="text-center py-8 text-sm text-muted-foreground">
                No files found
              </div>
            ) : (
              renderFileTree(fileTree)
            )}
          </div>
        </div>

        {/* Code Viewer */}
        <div className="flex-1 flex flex-col overflow-hidden bg-muted/30">
          {selectedFile ? (
            <>
              <div className="px-4 py-2 border-b bg-background flex items-center gap-2">
                <FileCode className="h-4 w-4 text-muted-foreground" />
                <span className="text-sm font-mono">{selectedFile}</span>
              </div>
              <div className="flex-1 overflow-auto bg-background">
                {loadingContent ? (
                  <div className="flex items-center justify-center h-full">
                    <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
                  </div>
                ) : fileContent ? (
                  <div className="flex">
                    {/* Line Numbers */}
                    <div className="select-none border-r bg-muted/30 px-4 py-4 text-right text-sm font-mono text-muted-foreground">
                      {fileContent.split('\n').map((_, i) => (
                        <div key={i} className="leading-relaxed">
                          {i + 1}
                        </div>
                      ))}
                    </div>
                    {/* Code Content */}
                    <pre className="flex-1 p-4 text-sm font-mono leading-relaxed overflow-x-auto">
                      <code>{fileContent}</code>
                    </pre>
                  </div>
                ) : (
                  <div className="flex items-center justify-center h-full text-muted-foreground">
                    <p className="text-sm">Failed to load file content</p>
                  </div>
                )}
              </div>
            </>
          ) : (
            <div className="flex items-center justify-center h-full text-muted-foreground">
              <div className="text-center">
                <Code2 className="h-12 w-12 mx-auto mb-3 opacity-50" />
                <p className="text-sm">Select a file to view its contents</p>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
