import { listen } from "@tauri-apps/api/event";
import { memo, useEffect, useState } from "react";
import { toast } from "@/ui/toast";
import {
  connectRemoteConnection,
  disconnectRemoteConnection,
  loadRemoteConnections,
} from "@/features/remote/services/remote-connection-actions";
import { connectionStore } from "@/features/remote/services/remote-connection-store";
import { getFriendlyRemoteError, isRemoteAuthFailure } from "@/features/remote/utils/remote-errors";
import ConnectionDialog from "./connection-dialog";
import ConnectionList from "./connection-list";
import PasswordPromptDialog from "./password-prompt-dialog";
import type { RemoteConnection, RemoteConnectionFormData } from "./types";

interface RemoteConnectionViewProps {
  onFileSelect?: (path: string, isDir: boolean) => void;
}

const RemoteConnectionView = ({ onFileSelect }: RemoteConnectionViewProps) => {
  const [connections, setConnections] = useState<RemoteConnection[]>([]);
  const [isDialogOpen, setIsDialogOpen] = useState(false);
  const [editingConnection, setEditingConnection] = useState<RemoteConnection | null>(null);
  const [passwordPromptConnection, setPasswordPromptConnection] = useState<RemoteConnection | null>(
    null,
  );
  const [connectingMap, setConnectingMap] = useState<Record<string, boolean>>({});

  // Load connections from Tauri Store
  useEffect(() => {
    const loadConnections = async () => {
      try {
        // First migrate any existing localStorage connections
        await connectionStore.migrateFromLocalStorage();

        // Then load all connections from Tauri Store
        setConnections(await loadRemoteConnections());
      } catch (error) {
        console.error("Error loading remote connections:", error);
      }
    };

    loadConnections();
  }, []);

  // Listen for remote connection disconnection events
  useEffect(() => {
    let unlisten: (() => void) | null = null;

    const setupDisconnectListener = async () => {
      try {
        unlisten = await listen<{ connectionId: string; connected: boolean }>(
          "ssh_connection_status",
          async (event) => {
            await connectionStore.updateConnectionStatus(
              event.payload.connectionId,
              event.payload.connected,
            );
            await refreshConnections();
          },
        );
      } catch (error) {
        console.error("Failed to set up disconnect event listener:", error);
      }
    };

    setupDisconnectListener();

    return () => {
      if (unlisten) {
        unlisten();
      }
    };
  }, []);

  // Update the local state and reload connections
  const refreshConnections = async () => {
    try {
      setConnections(await loadRemoteConnections());
    } catch (error) {
      console.error("Error refreshing connections:", error);
    }
  };

  const handleSaveConnection = async (formData: RemoteConnectionFormData): Promise<boolean> => {
    try {
      if (editingConnection) {
        // Update existing connection
        await connectionStore.saveConnection({
          ...editingConnection,
          ...formData,
        });
      } else {
        // Add new connection
        const newConnection = {
          id: Date.now().toString(),
          ...formData,
          isConnected: false,
        };
        await connectionStore.saveConnection(newConnection);
      }

      // Refresh the local state
      await refreshConnections();
      return true;
    } catch (error) {
      console.error("Error saving connection:", error);
      return false;
    }
  };

  const handleConnect = async (connectionId: string, providedPassword?: string) => {
    const connection = connections.find((conn) => conn.id === connectionId);
    if (!connection) return;

    try {
      if (connection.isConnected) {
        await disconnectRemoteConnection(connection);
        await refreshConnections();
      } else {
        if (connectingMap[connectionId]) return;
        setConnectingMap((prev) => ({ ...prev, [connectionId]: true }));
        await connectRemoteConnection(connection, providedPassword);
        await refreshConnections();
      }
    } catch (error) {
      console.error("Connection error:", error);
      const friendlyError = getFriendlyRemoteError(error);

      if (isRemoteAuthFailure(error) && !providedPassword && !connection.password) {
        setConnectingMap((prev) => ({ ...prev, [connectionId]: false }));
        setPasswordPromptConnection(connection);
        return;
      }

      if (providedPassword) {
        setConnectingMap((prev) => ({ ...prev, [connectionId]: false }));
        throw new Error(friendlyError);
      }

      toast.error(friendlyError);
      setConnectingMap((prev) => ({ ...prev, [connectionId]: false }));
    } finally {
      setConnectingMap((prev) => ({ ...prev, [connectionId]: false }));
    }
  };

  const handleEditConnection = (connection: RemoteConnection) => {
    setEditingConnection(connection);
    setIsDialogOpen(true);
  };

  const handleDeleteConnection = async (connectionId: string) => {
    try {
      await connectionStore.deleteConnection(connectionId);
      await refreshConnections();
    } catch (error) {
      console.error("Error deleting connection:", error);
    }
  };

  const handleAddNew = () => {
    setEditingConnection(null);
    setIsDialogOpen(true);
  };

  const handleCloseDialog = () => {
    setIsDialogOpen(false);
    setEditingConnection(null);
  };

  const handlePasswordPromptConnect = async (connectionId: string, password: string) => {
    await handleConnect(connectionId, password);
    setPasswordPromptConnection(null);
  };

  const handleClosePasswordPrompt = () => {
    setPasswordPromptConnection(null);
  };

  return (
    <>
      <ConnectionList
        connections={connections}
        onConnect={handleConnect}
        connectingMap={connectingMap}
        onEdit={handleEditConnection}
        onDelete={handleDeleteConnection}
        onFileSelect={onFileSelect}
        onAddNew={handleAddNew}
      />

      <ConnectionDialog
        isOpen={isDialogOpen}
        onClose={handleCloseDialog}
        onSave={handleSaveConnection}
        editingConnection={editingConnection}
      />

      <PasswordPromptDialog
        isOpen={!!passwordPromptConnection}
        connection={passwordPromptConnection}
        onClose={handleClosePasswordPrompt}
        onConnect={handlePasswordPromptConnect}
      />
    </>
  );
};

export default memo(RemoteConnectionView);
