import { useCallback, useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";
import { apiClient } from "../../../api/client";
import { EmptyState } from "../../data-states";
import { Icon } from "../../icon";
import type { GitStatus } from "../../../api/git-repositories";

interface FileTreeEntry {
  name: string;
  type: "file" | "directory";
  path: string;
  size?: number;
  mode?: string;
  last_commit?: {
    hash: string;
    message: string;
    author: string;
    date: string;
  } | null;
}

interface Props {
  projectId: string;
  repoId: string;
  gitStatus: GitStatus | null;
}

export const FileBrowser = ({ projectId, repoId, gitStatus }: Props) => {
  const [searchParams, setSearchParams] = useSearchParams();
  const [entries, setEntries] = useState<FileTreeEntry[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const branch = searchParams.get("branch") || "main";
  const path = searchParams.get("path") || "";

  const loadFiles = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const response = await apiClient.get(
        `/projects/${projectId}/repositories/${repoId}/files`,
        { params: { branch, path } }
      );
      setEntries(response.data.entries || []);
    } catch {
      setError("Failed to load files");
    } finally {
      setLoading(false);
    }
  }, [projectId, repoId, branch, path]);

  useEffect(() => {
    void loadFiles();
  }, [loadFiles]);

  useEffect(() => {
    const handleRefresh = () => void loadFiles();
    window.addEventListener("refresh-file-tree", handleRefresh);
    return () => window.removeEventListener("refresh-file-tree", handleRefresh);
  }, [loadFiles]);

  const handleEntryClick = (entry: FileTreeEntry) => {
    if (entry.type === "directory") {
      const newParams = new URLSearchParams(searchParams);
      newParams.set("path", entry.path);
      setSearchParams(newParams);
    } else {
      const newParams = new URLSearchParams(searchParams);
      newParams.set("file", entry.path);
      setSearchParams(newParams);
    }
  };

  const navigateUp = () => {
    if (!path) return;
    const parentPath = path.split("/").slice(0, -1).join("/");
    const newParams = new URLSearchParams(searchParams);
    if (parentPath) {
      newParams.set("path", parentPath);
    } else {
      newParams.delete("path");
    }
    setSearchParams(newParams);
  };

  const getFileStatus = (filePath: string): string | null => {
    if (!gitStatus) return null;
    if (gitStatus.modified.includes(filePath)) return "modified";
    if (gitStatus.added.includes(filePath)) return "added";
    if (gitStatus.deleted.includes(filePath)) return "deleted";
    if (gitStatus.untracked.includes(filePath)) return "untracked";
    return null;
  };

  if (loading) return <p className="muted">Loading files...</p>;
  if (error) return <p className="error-text">{error}</p>;

  return (
    <div className="file-tree">
      {path && (
        <button className="tree-entry tree-up" onClick={navigateUp} type="button">
          <Icon name="folder" size="sm" /> ..
        </button>
      )}
      {entries.length === 0 && (
        <EmptyState message="No files in this repository yet." />
      )}
      {entries.map((entry) => {
        const fileStatus = entry.type === "file" ? getFileStatus(entry.path) : null;
        return (
          <button
            key={entry.path}
            className={`tree-entry ${entry.type === "directory" ? "tree-directory" : "tree-file"} ${fileStatus || ""}`}
            onClick={() => handleEntryClick(entry)}
            type="button"
          >
            <Icon name={entry.type === "directory" ? "folder" : "file"} size="sm" /> {entry.name}
            {fileStatus && (
              <span className={`file-status-indicator ${fileStatus}`}>
                {fileStatus === "modified" && "M"}
                {fileStatus === "added" && "A"}
                {fileStatus === "deleted" && "D"}
                {fileStatus === "untracked" && "?"}
              </span>
            )}
          </button>
        );
      })}
    </div>
  );
};
