import { useState, useEffect } from "react";
import { invoke } from "@tauri-apps/api/core";
import { open } from "@tauri-apps/plugin-dialog";
import { listen, UnlistenFn } from "@tauri-apps/api/event";
import { appDataDir } from '@tauri-apps/api/path'; // Import for data directory (if needed frontend side)
import "./App.css";

type ServerType =
  | 'Paper'
  | 'Spigot'
  | 'Bukkit'
  | 'Vanilla'
  | 'Forge'
  | 'Fabric'
  | 'Velocity'
  | 'BungeeCord'
  | 'Waterfall'
  | 'Unknown';

interface ServerInfo {
  server_type: ServerType;
  minecraft_version?: string;
  plugins_directory: string;
  plugins_count: number;
}

interface Plugin {
  name: string;
  version: string;
  latest_version?: string;
  description?: string;
  authors: string[];
  has_update: boolean;
  api_version?: string;
  main_class?: string;
  depend?: string[] | null;
  soft_depend?: string[] | null;
  load_before?: string[] | null;
  commands?: any;
  permissions?: any;
  file_path: string;
  file_hash: string;
  website?: string;
  changelog?: string;
  repository_source?: string; // Add repository source (string for simplicity)
  repository_id?: string;     // Add repository ID
  repository_url?: string;    // URL to the plugin's repository page
}

interface ScanResult {
  server_info: ServerInfo;
  plugins: Plugin[];
}

interface ScanProgress {
  processed: number;
  total: number;
  current_file: string;
}

// --- New Interfaces for Update Events ---
interface BulkUpdateProgressPayload {
  processed: number;
  total: number;
  current_plugin_name: string;
}

interface SingleUpdateResultPayload {
  original_file_path: string;
  plugin: Plugin | null; // Updated plugin state or null if check failed but wasn't a panic
  error: string | null; // Error message if any
}

// Interface for potential plugin matches for ambiguous plugins
interface PotentialPluginMatch {
  name: string;
  version: string;
  repository: string;
  repository_id: string;
  page_url: string;
  description?: string;
  minecraft_versions: string[];
  download_count?: number;
}

// --- End New Interfaces ---

interface PluginDetailsProps {
  plugin: Plugin;
  onClose: () => void;
}

// Get server type icon
function getServerTypeIcon(serverType: ServerType): string {
  switch (serverType) {
    case 'Paper':
      return '📄';
    case 'Spigot':
      return '🔌';
    case 'Bukkit':
      return '🪣';
    case 'Vanilla':
      return '🧊';
    case 'Forge':
      return '🔨';
    case 'Fabric':
      return '🧵';
    case 'Velocity':
      return '⚡';
    case 'BungeeCord':
      return '🔗';
    case 'Waterfall':
      return '🌊';
    default:
      return '❓';
  }
}

// Get a formatted server type name for display
function getServerTypeName(serverType: ServerType): string {
  return serverType === 'Unknown' ? 'Unknown Server' : serverType;
}

function PluginDetails({ plugin, onClose }: PluginDetailsProps) {
  return (
    <div className="plugin-details-modal">
      <div className="plugin-details-content">
        <button className="close-button" onClick={onClose}>&times;</button>
        <h2>{plugin.name}</h2>
        <div className="plugin-version-display">Version: {plugin.version} {plugin.latest_version && plugin.has_update && <span className="update-available-badge">(Update available: {plugin.latest_version})</span>}</div>

        {plugin.description && (
          <div className="plugin-description">{plugin.description}</div>
        )}

        {plugin.website && (
            <div className="plugin-website">
                <div className="section-label">Website:</div>
                <a href={plugin.website} target="_blank" rel="noopener noreferrer">
                    {plugin.website}
                </a>
            </div>
        )}

        {plugin.authors && plugin.authors.length > 0 && (
          <div className="plugin-authors">
            <div className="section-label">Authors:</div>
            <div>{plugin.authors.join(", ")}</div>
          </div>
        )}

        {plugin.depend && plugin.depend.length > 0 && (
          <div className="plugin-dependencies">
            <div className="section-label">Dependencies:</div>
            <div>{plugin.depend.join(", ")}</div>
          </div>
        )}

        {plugin.soft_depend && plugin.soft_depend.length > 0 && (
          <div className="plugin-soft-dependencies">
            <div className="section-label">Soft Dependencies:</div>
            <div>{plugin.soft_depend.join(", ")}</div>
          </div>
        )}

        {plugin.changelog && plugin.has_update && (
          <div className="plugin-changelog">
            <div className="section-label">Changelog:</div>
            <div className="changelog-content">{plugin.changelog}</div>
          </div>
        )}

        <div className="plugin-file-info">
          <div className="section-label">File Path:</div>
          <div className="file-path">{plugin.file_path}</div>

          <div className="section-label">File Hash (SHA-256):</div>
          <div className="file-hash">{plugin.file_hash}</div>
        </div>

        {plugin.has_update && plugin.latest_version && (
          <div className="update-actions">
            <button
              className="update-button detail-update-button"
              onClick={() => window.dispatchEvent(new CustomEvent('update-plugin', { detail: plugin }))}
            >
              Update to version {plugin.latest_version}
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

// Add this component after the PluginDetails component and before the App component
function ServerInfoDisplay({ serverInfo }: { serverInfo: ServerInfo | null }) {
  if (!serverInfo) return null;

  return (
    <div className="server-info">
      <h2>Server Information</h2>
      <div className="server-type">
        <span className="server-icon">{getServerTypeIcon(serverInfo.server_type)}</span>
        <span className="server-type-name">{getServerTypeName(serverInfo.server_type)}</span>
      </div>
      <div className="minecraft-version">
        <span className="version-label">Minecraft Version</span>
        <span className="version-value">{serverInfo.minecraft_version || "Unknown"}</span>
      </div>
      <div className="plugins-path">
        <span className="path-label">Plugins Directory</span>
        <span className="path-value">{serverInfo.plugins_directory || "Unknown"}</span>
      </div>
      <div className="plugins-count">
        <b>{serverInfo.plugins_count}</b> plugins found
      </div>
    </div>
  );
}

// Add this new component after PluginDetails
function WarningModal({ message, onClose }: { message: string, onClose: () => void }) {
  return (
    <div className="modal-backdrop">
      <div className="warning-modal">
        <h3>⚠️ Warning</h3>
        <p>{message}</p>
        <button onClick={onClose}>Close</button>
      </div>
    </div>
  );
}

// Component for selecting the correct plugin from potential matches
function PluginMatchSelector({
  plugin,
  potentialMatches,
  onSelect,
  onCancel
}: {
  plugin: Plugin,
  potentialMatches: PotentialPluginMatch[],
  onSelect: (match: PotentialPluginMatch) => void,
  onCancel: () => void
}) {
  return (
    <div className="modal-backdrop">
      <div className="plugin-match-modal">
        <h3>Multiple Matches Found</h3>
        <p>We found several potential matches for <strong>{plugin.name}</strong>. Please select the correct one:</p>

        <div className="matches-list">
          {potentialMatches.map((match, index) => (
            <div key={`${match.repository}-${match.repository_id}`} className="match-item">
              <div className="match-details">
                <h4>{match.name}</h4>
                <p className="match-version">Version: {match.version}</p>
                {match.description && <p className="match-description">{match.description}</p>}
                <div className="match-meta">
                  <span className="match-repo">Source: {match.repository}</span>
                  {match.download_count && <span className="match-downloads">Downloads: {match.download_count.toLocaleString()}</span>}
                  <span className="match-mc-version">MC: {match.minecraft_versions.join(', ')}</span>
                </div>
              </div>
              <div className="match-actions">
                <button className="select-match-button" onClick={() => onSelect(match)}>
                  Select This Match
                </button>
                <a
                  href={match.page_url}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="view-page-link"
                >
                  View Page
                </a>
              </div>
            </div>
          ))}
        </div>

        <div className="match-selector-footer">
          <button className="cancel-button" onClick={onCancel}>Cancel</button>
        </div>
      </div>
    </div>
  );
}

function App() {
  const [serverPath, setServerPath] = useState("");
  const [serverInfo, setServerInfo] = useState<ServerInfo | null>(null);
  const [plugins, setPlugins] = useState<Plugin[]>([]);
  const [isScanning, setIsScanning] = useState(false);
  const [scanComplete, setScanComplete] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [selectedPlugin, setSelectedPlugin] = useState<Plugin | null>(null);
  const [scanProgress, setScanProgress] = useState<ScanProgress | null>(null);
  const [isCheckingUpdates, setIsCheckingUpdates] = useState(false);
  const [updateError, setUpdateError] = useState<string | null>(null);
  // --- New State Variables ---
  const [pluginLoadingStates, setPluginLoadingStates] = useState<Record<string, boolean>>({});
  const [bulkUpdateProgress, setBulkUpdateProgress] = useState<BulkUpdateProgressPayload | null>(null);
  const [warningMessage, setWarningMessage] = useState<string | null>(null);
  const [potentialMatches, setPotentialMatches] = useState<PotentialPluginMatch[]>([]);
  // --- New state for match selector ---
  const [showMatchSelector, setShowMatchSelector] = useState(false);
  const [pluginToDisambiguate, setPluginToDisambiguate] = useState<Plugin | null>(null);
  // --- End New state for match selector ---
  // --- End New State Variables ---
  const [serverType, setServerType] = useState<ServerType>('Unknown');

  useEffect(() => {
    let unlistenScanStarted: UnlistenFn | undefined;
    let unlistenScanProgress: UnlistenFn | undefined;
    let unlistenScanCompleted: UnlistenFn | undefined;
    let unlistenScanError: UnlistenFn | undefined;
    let unlistenBulkUpdateStart: UnlistenFn | undefined;
    let unlistenUpdateCheckProgress: UnlistenFn | undefined;
    let unlistenSingleUpdateCheckStarted: UnlistenFn | undefined;
    let unlistenSingleUpdateCheckCompleted: UnlistenFn | undefined;

    const setupListeners = async () => {
      unlistenScanStarted = await listen("scan_started", () => {
        console.log("Scan started event received");
        setIsScanning(true);
        setScanProgress(null);
        setError(null);
      });

      unlistenScanProgress = await listen<ScanProgress>("scan_progress", (event) => {
        console.log("Scan progress event received:", event.payload);
        setScanProgress(event.payload);
      });

      unlistenScanCompleted = await listen<ScanResult>("scan_completed", (event) => {
        console.log("Scan completed event received with payload:", event.payload);
        try {
          console.log("Server info:", event.payload.server_info);
          console.log("Plugins count:", event.payload.plugins.length);

          // Update state in a specific order to ensure UI updates properly
          setIsScanning(false);
          setScanComplete(true);
          setServerInfo(event.payload.server_info);
          setPlugins(event.payload.plugins);
          setServerType(event.payload.server_info.server_type);

          // Add a slight delay and verify the state was updated
          setTimeout(() => {
            console.log("Verifying state updates after scan:");
            console.log("- scanComplete:", scanComplete);
            console.log("- serverInfo:", serverInfo);
            console.log("- plugins count:", plugins.length);

            // Force a state update if plugins length is still 0 but we got plugins
            if (plugins.length === 0 && event.payload.plugins.length > 0) {
              console.log("Forcing state update because plugins array is empty");
              setPlugins([...event.payload.plugins]);
            }
          }, 100);

          console.log("State updated after scan completion");
        } catch (err) {
          console.error("Error handling scan completion:", err);
          setError(`Error handling scan completion: ${err}`);
          setIsScanning(false);
        }
      });

      unlistenScanError = await listen<string>("scan_error", (event) => {
        console.log("Scan error event received:", event.payload);
        setIsScanning(false);
        setError(event.payload);
      });

      unlistenBulkUpdateStart = await listen<number>("bulk_update_start", (event) => {
        console.log("Bulk update start event received, total plugins:", event.payload);
        setIsCheckingUpdates(true);
        setUpdateError(null);
        setBulkUpdateProgress({
          processed: 0,
          total: event.payload,
          current_plugin_name: "Starting update check..."
        });
      });

      unlistenUpdateCheckProgress = await listen<BulkUpdateProgressPayload>("update_check_progress", (event) => {
        console.log("Update check progress event received:", event.payload);
        setBulkUpdateProgress(event.payload);
      });

      unlistenSingleUpdateCheckStarted = await listen<string>("single_update_check_started", (event) => {
        console.log("Single update check started for:", event.payload);
      });

      unlistenSingleUpdateCheckCompleted = await listen<SingleUpdateResultPayload>("single_update_check_completed", (event) => {
        console.log("Single update check completed, result:", event.payload);
        const { original_file_path, plugin, error } = event.payload;

        setPluginLoadingStates(prev => ({ ...prev, [original_file_path]: false }));

        if (error) {
          setUpdateError(`Error checking for updates: ${error}`);
          return;
        }

        if (plugin) {
          setPlugins(prevPlugins => prevPlugins.map(p => {
            if (p.file_path === original_file_path) {
              return plugin;
            }
            return p;
          }));

          if (serverPath) {
            invoke("save_plugin_data", {
              plugins: plugins.map(p => p.file_path === original_file_path ? plugin : p),
              serverPath
            }).catch(err => {
              console.error("Error saving plugin data after single update:", err);
            });
          }
        }
      });

      window.addEventListener('update-plugin', ((e: CustomEvent<Plugin>) => {
        if (e.detail) {
          updatePlugin(e.detail);
        }
      }) as EventListener);
    };

    setupListeners();

    return () => {
      unlistenScanStarted?.();
      unlistenScanProgress?.();
      unlistenScanCompleted?.();
      unlistenScanError?.();
      unlistenBulkUpdateStart?.();
      unlistenUpdateCheckProgress?.();
      unlistenSingleUpdateCheckStarted?.();
      unlistenSingleUpdateCheckCompleted?.();
      window.removeEventListener('update-plugin', (() => {}) as EventListener);
    };
  }, []);

  async function selectDirectory() {
    try {
      const selected = await open({
        directory: true,
        multiple: false,
        title: "Select Minecraft Server Folder",
      });

      if (selected && typeof selected === "string") {
        console.log(`Directory selected: ${selected}`);
        setServerPath(selected);
        setServerInfo(null);
        setPlugins([]);
        setIsScanning(false);
        setScanComplete(false);
        setError(null);
        setScanProgress(null);
        setIsCheckingUpdates(false);
        setUpdateError(null);
        setPluginLoadingStates({});
        setBulkUpdateProgress(null);

        try {
          console.log(`Attempting to load persisted data for: ${selected}`);
          const loadedPlugins: Plugin[] = await invoke("load_plugin_data", { serverPath: selected });
          if (loadedPlugins && loadedPlugins.length > 0) {
            console.log(`Loaded ${loadedPlugins.length} plugins from persistence.`);
            setPlugins(loadedPlugins);
            setScanComplete(true);
            setError(null);
          } else {
            console.log("No persisted plugin data found for this server.");
          }
        } catch (loadError) {
          console.error("Error loading persisted plugin data:", loadError);
          setError(`Failed to load previous plugin data: ${loadError}`);
        }
      } else {
        console.log("Directory selection cancelled.");
      }
    } catch (err) {
      console.error("Error selecting directory:", err);
      setError(`Error selecting directory: ${err}`);
    }
  }

  async function scanForPlugins() {
    if (!serverPath || isScanning) return;

    try {
      console.log("Starting scan for plugins in:", serverPath);
      setIsScanning(true);
      setScanComplete(false);
      setPlugins([]);
      setServerInfo(null);
      setScanProgress(null);
      setError(null);

      await invoke("scan_server_dir", { path: serverPath });
      console.log("Scan server dir command invoked successfully");

    } catch (err) {
      console.error("Error invoking scan command:", err);
      setError(`Failed to start scan: ${err as string}`);
      setIsScanning(false);
    }
  }

  async function checkForUpdates() {
    if (!plugins.length || isCheckingUpdates) return;

    setIsCheckingUpdates(true);
    setUpdateError(null);
    setBulkUpdateProgress(null);
    console.log("Invoking bulk check_plugin_updates...");

    try {
      const repositoriesToCheck = ['SpigotMC', 'Modrinth', 'GitHub'];

      const pluginsToSend = plugins.map(p => ({
        name: p.name,
        version: p.version,
        authors: p.authors || [],
        file_path: p.file_path,
        file_hash: p.file_hash,
        website: p.website,
        description: p.description,
        api_version: p.api_version,
        main_class: p.main_class,
        depend: p.depend,
        soft_depend: p.soft_depend,
        load_before: p.load_before,
        commands: p.commands,
        permissions: p.permissions,
        has_update: p.has_update || false,
        repository_source: p.repository_source,
        repository_id: p.repository_id,
        repository_url: p.repository_url,
      }));

      console.log("Sending plugin data to backend, count:", pluginsToSend.length);

      const updatedPlugins = await invoke<Plugin[]>("check_plugin_updates", {
        plugins: pluginsToSend,
        repositories: repositoriesToCheck,
      });

      console.log("Bulk update check completed successfully, updating state.");
      setPlugins(updatedPlugins);

      if (serverPath) {
        try {
          console.log("[checkForUpdates] Saving plugin data...");
          await invoke("save_plugin_data", { plugins: updatedPlugins, serverPath });
          console.log("[checkForUpdates] Plugin data saved successfully.");
        } catch (saveError) {
          console.error("Error saving plugin data after bulk update:", saveError);
          setUpdateError(`Update check complete, but failed to save plugin data: ${saveError}`);
        }
      }
    } catch (err) {
      const errorMessage = `Error during bulk update check: ${err instanceof Error ? err.message : String(err)}`;
      console.error(errorMessage);
      setUpdateError(errorMessage);
    } finally {
      setIsCheckingUpdates(false);
      setBulkUpdateProgress(null);
    }
  }

  async function checkSinglePlugin(plugin: Plugin) {
    if (isScanning || isCheckingUpdates || pluginLoadingStates[plugin.file_path]) return;

    console.log(`Invoking single check for: ${plugin.name} (${plugin.file_path})`);
    setPluginLoadingStates(prev => ({ ...prev, [plugin.file_path]: true }));
    setUpdateError(null);

    try {
      const repositoriesToCheck = ['SpigotMC', 'Modrinth', 'GitHub'];

      const pluginToSend = {
        name: plugin.name,
        version: plugin.version,
        authors: plugin.authors || [],
        file_path: plugin.file_path,
        file_hash: plugin.file_hash,
        website: plugin.website,
        description: plugin.description,
        api_version: plugin.api_version,
        main_class: plugin.main_class,
        depend: plugin.depend,
        soft_depend: plugin.soft_depend,
        load_before: plugin.load_before,
        commands: plugin.commands,
        permissions: plugin.permissions,
        has_update: plugin.has_update,
      };

      await invoke("check_single_plugin_update_command", {
        plugin: pluginToSend,
        repositoriesToCheck,
      });
    } catch (err) {
      const errorMessage = `Error invoking single update command for ${plugin.name}: ${err instanceof Error ? err.message : String(err)}`;
      console.error(errorMessage);
      setUpdateError(errorMessage);
      setPluginLoadingStates(prev => ({ ...prev, [plugin.file_path]: false }));
    }
  }

  async function updatePlugin(plugin: Plugin) {
    if (!plugin.has_update || !plugin.latest_version || !plugin.repository_source || !plugin.repository_id) {
      setUpdateError(`Cannot update ${plugin.name}: Missing required update information`);
      return;
    }

    setPluginLoadingStates(prev => ({ ...prev, [plugin.file_path]: true }));
    setUpdateError(null);

    try {
      console.log(`Updating plugin: ${plugin.name} to version ${plugin.latest_version}`);

      const newFilePath = await invoke<string>("replace_plugin", {
        pluginId: plugin.repository_id,
        version: plugin.latest_version,
        repository: plugin.repository_source,
        currentFilePath: plugin.file_path,
        serverInfo: serverInfo
      });

      console.log(`Update successful for ${plugin.name}, new file path: ${newFilePath}`);

      setPlugins(currentPlugins => currentPlugins.map(p => {
        if (p.file_path === plugin.file_path) {
          return {
            ...p,
            version: p.latest_version || p.version,
            has_update: false,
            latest_version: p.latest_version,
            file_path: newFilePath
          };
        }
        return p;
      }));

      if (serverPath) {
        await invoke("save_plugin_data", {
          plugins: plugins.map(p => {
            if (p.file_path === plugin.file_path) {
              return {
                ...p,
                version: p.latest_version || p.version,
                has_update: false,
                file_path: newFilePath
              };
            }
            return p;
          }),
          serverPath
        });
      }
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : String(err);
      console.error(`Error updating ${plugin.name}:`, errorMessage);

      if (errorMessage.includes("in use") ||
          errorMessage.includes("server running") ||
          errorMessage.includes("being used by another process")) {
        setWarningMessage(`Cannot update ${plugin.name}: The Minecraft server appears to be running. Please stop your server before updating plugins.`);
      } else if (errorMessage.includes("download failed")) {
        setUpdateError(`Failed to download update for ${plugin.name}. Please check your internet connection and try again.`);
      } else if (errorMessage.includes("Critical error")) {
        setWarningMessage(`${errorMessage} A backup of your original plugin is available in the backups folder.`);
      } else {
        setUpdateError(`Error updating ${plugin.name}: ${errorMessage}`);
      }
    } finally {
      setPluginLoadingStates(prev => ({ ...prev, [plugin.file_path]: false }));
    }
  }

  const showPluginDetails = (plugin: Plugin) => {
    setSelectedPlugin(plugin);
  };

  const closePluginDetails = () => {
    setSelectedPlugin(null);
  };

  const handleSelectMatch = async (selectedMatch: PotentialPluginMatch) => {
    if (!pluginToDisambiguate || !serverPath) return;

    console.log(`User selected match: ${selectedMatch.name} from ${selectedMatch.repository}`);
    setShowMatchSelector(false);
    setPluginLoadingStates(prev => ({ ...prev, [pluginToDisambiguate.file_path]: true }));

    try {
      const updatedPlugin: Plugin = await invoke("set_plugin_repository", {
        pluginFilePath: pluginToDisambiguate.file_path,
        repository: selectedMatch.repository,
        repositoryId: selectedMatch.repository_id,
        pageUrl: selectedMatch.page_url,
        serverPath: serverPath,
      });

      setPlugins(currentPlugins =>
        currentPlugins.map(p =>
          p.file_path === updatedPlugin.file_path ? updatedPlugin : p
        )
      );
      console.log(`Successfully set repository source for ${updatedPlugin.name}`);

    } catch (err) {
      console.error("Error setting plugin repository source:", err);
      setUpdateError(`Failed to set repository source for ${pluginToDisambiguate.name}: ${err}`);
    } finally {
      setPluginLoadingStates(prev => ({ ...prev, [pluginToDisambiguate.file_path]: false }));
      setPluginToDisambiguate(null);
      setPotentialMatches([]);
    }
  };

  const handleCancelMatchSelection = () => {
    setShowMatchSelector(false);
    setPluginToDisambiguate(null);
    setPotentialMatches([]);
    if (pluginToDisambiguate) {
        setPluginLoadingStates(prev => ({ ...prev, [pluginToDisambiguate.file_path]: false }));
    }
  };

  return (
    <div className="app-container">
      <header className="app-header">
        <h1>🔧 PlugSnatcher</h1>
        <p>Minecraft Plugin Manager</p>
      </header>

      <main className="app-content">
        <section className="server-selector">
          <h2>Select Server Directory</h2>
          <div className="input-group">
            <input
              type="text"
              value={serverPath}
              onChange={(e) => setServerPath(e.target.value)}
              placeholder="Enter server directory path..."
            />
            <button onClick={selectDirectory}>Browse</button>
          </div>
          <button
            className="scan-button"
            onClick={scanForPlugins}
            disabled={isScanning || !serverPath}
          >
            {isScanning ? "Scanning..." : "Scan for Plugins"}
          </button>

          {isScanning && scanProgress && (
            <div className="scan-progress">
              <p>Scanning: {scanProgress.current_file}</p>
              <progress value={scanProgress.processed} max={scanProgress.total}></progress>
              <span>{scanProgress.processed} / {scanProgress.total}</span>
            </div>
          )}

          {error && (
            <div className="error-message">
              {error}
            </div>
          )}
        </section>

        {serverInfo && (
          <ServerInfoDisplay serverInfo={serverInfo} />
        )}

        {serverInfo && plugins.length > 0 && (
          <div className="update-controls">
              <button
                  onClick={checkForUpdates}
                  disabled={isScanning || isCheckingUpdates || Object.values(pluginLoadingStates).some(isLoading => isLoading) || plugins.length === 0}
                  className="action-button update-check-button"
              >
                  {isCheckingUpdates ? 'Checking All...' : 'Check All for Updates'}
              </button>
                {isCheckingUpdates && bulkUpdateProgress && (
                  <div className="bulk-update-progress">
                      Checking {bulkUpdateProgress.processed}/{bulkUpdateProgress.total}: {bulkUpdateProgress.current_plugin_name}
                      <progress value={bulkUpdateProgress.processed} max={bulkUpdateProgress.total}></progress>
                  </div>
                )}
              {updateError && (
                  <div className="error-message update-error">{updateError}</div>
              )}
          </div>
        )}

        {plugins.length > 0 && (
          <section className="plugins-list">
              <h2>Installed Plugins ({plugins.length})</h2>
              <div className="plugins-header">
                <span>Name</span>
                <span>Current Version</span>
                <span>Latest Version</span>
                <span>Actions</span>
              </div>
              {plugins.map((plugin) => (
                <div key={plugin.file_path} className={`plugin-item ${plugin.has_update ? 'has-update' : ''}`}>
                  <div className="plugin-name">{plugin.name}</div>
                  <div className="plugin-version">{plugin.version}</div>
                  <div className="plugin-latest-version">
                    {plugin.repository_url && plugin.latest_version ? (
                      <a href={plugin.repository_url} target="_blank" rel="noopener noreferrer" className="version-link">
                        {plugin.latest_version}
                      </a>
                    ) : (
                      plugin.latest_version || 'N/A'
                    )}
                  </div>
                  <div className="plugin-actions">
                    <button
                      className="action-button check-single-button"
                      onClick={() => checkSinglePlugin(plugin)}
                      disabled={isScanning || isCheckingUpdates || pluginLoadingStates[plugin.file_path]}
                    >
                      {pluginLoadingStates[plugin.file_path] ? 'Checking...' : 'Check'}
                    </button>
                    {plugin.has_update && (
                      <button
                        className="update-button"
                        onClick={() => updatePlugin(plugin)}
                        disabled={isScanning || isCheckingUpdates || pluginLoadingStates[plugin.file_path]}
                      >
                        {pluginLoadingStates[plugin.file_path] ? 'Updating...' : 'Update'}
                      </button>
                    )}
                    <button className="info-button" onClick={() => showPluginDetails(plugin)}>Info</button>
                  </div>
                </div>
              ))}
          </section>
        )}

        {scanComplete && plugins.length === 0 && (
          <section className="plugins-list">
            <h2>Installed Plugins (0)</h2>
            <p>No plugins found in this directory.</p>
          </section>
        )}

        {selectedPlugin && (
          <PluginDetails plugin={selectedPlugin} onClose={closePluginDetails} />
        )}

        {warningMessage && (
          <WarningModal
            message={warningMessage}
            onClose={() => setWarningMessage(null)}
          />
        )}

        {showMatchSelector && pluginToDisambiguate && (
          <PluginMatchSelector
            plugin={pluginToDisambiguate}
            potentialMatches={potentialMatches}
            onSelect={handleSelectMatch}
            onCancel={handleCancelMatchSelection}
          />
        )}

      </main>

      <footer className="app-footer">
        <p>PlugSnatcher v0.1.0 - Developed with 💻 and ☕</p>
      </footer>
    </div>
  );
}

export default App;
