import { existsSync, statSync } from "fs";
import { resolve } from "path";
import { homedir } from "os";
import { StoreProvider } from "./state/store.tsx";
import { Layout } from "./components/Layout.tsx";
import { useUnifiedRepos } from "./hooks/useUnifiedRepos.ts";
import { useKeyBindings } from "./hooks/useKeyBindings.ts";
import { useBackgroundFetch } from "./hooks/useBackgroundFetch.ts";
import { saveConfig, findConfigPath } from "./config/loader.ts";
import type { GitforestConfig, UnifiedRepo } from "./types/index.ts";

interface AppContentProps {
  config: GitforestConfig;
}

function AppContent({ config }: AppContentProps) {
  const { loadUnifiedRepos, batchClone } = useUnifiedRepos(config);

  // Clone handler for Layout
  const handleClone = async (repos: UnifiedRepo[], targetDir: string, useSSH: boolean) => {
    await batchClone(repos, targetDir, useSSH);
  };

  // Add directory handler for Layout
  const handleAddDirectory = async (
    rawPath: string,
    maxDepth: number,
    label: string,
  ): Promise<{ success: boolean; error?: string }> => {
    const expanded = rawPath.replace(/^~/, homedir());
    const absPath = resolve(expanded);

    if (!existsSync(absPath)) {
      return { success: false, error: `Directory does not exist: ${absPath}` };
    }

    if (!statSync(absPath).isDirectory()) {
      return { success: false, error: `Not a directory: ${absPath}` };
    }

    // Check for duplicates
    const exists = config.directories.some((d) => {
      const dPath = d.path.replace(/^~/, homedir());
      return resolve(dPath) === absPath;
    });

    if (exists) {
      return { success: false, error: "Directory already configured" };
    }

    // Add to the config object (mutation - stays in memory for this session)
    const newDir: { path: string; maxDepth: number; label?: string } = {
      path: absPath,
      maxDepth,
    };
    if (label) newDir.label = label;
    config.directories.push(newDir);

    // Persist to disk
    try {
      const configPath = findConfigPath() ?? undefined;
      await saveConfig(config, configPath);
      return { success: true };
    } catch (error) {
      return { success: false, error: error instanceof Error ? error.message : String(error) };
    }
  };

  // Set up keyboard bindings
  useKeyBindings({
    config,
    onRefresh: loadUnifiedRepos,
  });

  // Set up background fetch
  useBackgroundFetch(config);

  return (
    <Layout
      config={config}
      onRefresh={loadUnifiedRepos}
      onClone={handleClone}
      onAddDirectory={handleAddDirectory}
    />
  );
}

interface AppProps {
  config: GitforestConfig;
}

export function App({ config }: AppProps) {
  return (
    <StoreProvider>
      <AppContent config={config} />
    </StoreProvider>
  );
}
