import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { SearchInput } from "@/components/ui/search-input";
import { Label } from "@/components/ui/label";
import ArrowRightIcon from "@/icons/arrow_line_rigth.svg?react";
import { Separator } from "@/components/ui/separator";
import {
  Sheet,
  SheetContent,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import { VisuallyHidden as VisuallyHiddenPrimitive } from "radix-ui";
const VisuallyHidden = VisuallyHiddenPrimitive.Root;
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip";
import { Hexagon, Eraser } from "lucide-react";
import { useState, useMemo, useCallback, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { routes } from "@/routes";
import { useSocketStore } from "@/store";
import { toast, useToast } from "@/components/ui/use-toast";
import { useResetSetup, useSaveSetup } from "@/data/saved-setups";
import { McpxData } from "./SystemConnectivity/types";
import { type AppConfig } from "@mcpx/shared-model";
import { getMcpServerStatusFromTargetServer } from "./helpers";
import { McpxServerCard } from "./McpxServerCard";
import { ServerStatusBadge } from "./ServerStatusBadge";
import type { McpServerStatus } from "@/types";
import { ServerMetricCard } from "./ServerMetricCards";

const DRAWER_CLOSING_DELAY_MS = 100;

interface McpxDetailsModalProps {
  mcpxData: McpxData | null;
  isOpen: boolean;
  onClose: () => void;
}

type StartFreshStep = "confirm" | "save";

export const McpxDetailsModal = ({
  mcpxData,
  isOpen,
  onClose,
}: McpxDetailsModalProps) => {
  const [searchQuery, setSearchQuery] = useState("");
  const [pendingServerToggles, setPendingServerToggles] = useState<
    Map<string, boolean>
  >(new Map());
  const [startFreshStep, setStartFreshStep] = useState<StartFreshStep | null>(
    null,
  );
  const [saveDescription, setSaveDescription] = useState("");

  const navigate = useNavigate();
  const resetMutation = useResetSetup();
  const saveMutation = useSaveSetup();

  const { dismiss } = useToast();
  const [internalOpen, setInternalOpen] = useState(false);

  useEffect(() => {
    if (isOpen) {
      dismiss();
      setPendingServerToggles(new Map());
    }
    setInternalOpen(isOpen);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isOpen]);

  const { systemState } = useSocketStore((s) => ({
    systemState: s.systemState,
  }));

  const hasChanges = useMemo(() => {
    return pendingServerToggles.size > 0;
  }, [pendingServerToggles]);

  const getVersionNumber = (version: string) => {
    if (!version) return "Unknown";
    return version.split("-")[0];
  };

  const mcpxStatus = useMemo<McpServerStatus>(() => {
    if (!mcpxData?.status) return "connected_stopped";
    return mcpxData.status === "running"
      ? "connected_running"
      : "connected_stopped";
  }, [mcpxData?.status]);

  const serversList = useMemo(() => {
    if (!systemState?.targetServers) return [];
    return systemState.targetServers
      .map((server) => ({
        name: server.name,
        toolsCount: server.tools?.length || 0,
        icon: server.icon,
        status: getMcpServerStatusFromTargetServer(server),
        type: server._type,
        command: server._type === "stdio" ? server.command : undefined,
      }))
      .sort((a, b) =>
        a.name.localeCompare(b.name, undefined, { sensitivity: "base" }),
      );
  }, [systemState?.targetServers]);

  const filteredServers = useMemo(() => {
    return serversList.filter((server) =>
      server.name.toLowerCase().includes(searchQuery.toLowerCase()),
    );
  }, [serversList, searchQuery]);

  const { appConfig, emitPatchAppConfig } = useSocketStore((s) => ({
    appConfig: s.appConfig,
    emitPatchAppConfig: s.emitPatchAppConfig,
  }));

  const saveConfiguration = useCallback(async () => {
    if (!mcpxData) {
      toast({
        title: "Error",
        description: "MCPX data is missing",
        variant: "destructive",
      });
      return;
    }

    if (pendingServerToggles.size === 0 || !appConfig) {
      return;
    }

    try {
      const appConfigTyped = appConfig as AppConfig & {
        targetServerAttributes?: Record<string, { inactive: boolean }>;
      };
      const currentTargetServerAttributes =
        appConfigTyped.targetServerAttributes ?? {};

      const updatedTargetServerAttributes = {
        ...currentTargetServerAttributes,
      };

      pendingServerToggles.forEach((isActive, serverName) => {
        const normalizedName = serverName.toLowerCase().trim();
        updatedTargetServerAttributes[normalizedName] = {
          ...updatedTargetServerAttributes[normalizedName],
          inactive: !isActive,
        };
      });

      const updatedConfig = {
        ...appConfig,
        targetServerAttributes: updatedTargetServerAttributes,
      };
      emitPatchAppConfig(updatedConfig);

      setPendingServerToggles(new Map());

      toast({
        title: "Success",
        description: "MCPX configuration updated successfully",
      });

      setTimeout(() => {
        onClose();
      }, DRAWER_CLOSING_DELAY_MS);
    } catch (error) {
      const errorMessage =
        error instanceof Error
          ? error.message
          : "Failed to update MCPX configuration";
      toast({
        title: "Error",
        description: errorMessage,
        variant: "destructive",
      });
    }
  }, [mcpxData, pendingServerToggles, appConfig, emitPatchAppConfig, onClose]);

  const handleClose = () => {
    dismiss();
    setInternalOpen(false);
    setTimeout(() => onClose(), 300);
  };

  const currentSetupSummary = useMemo(() => {
    const serverCount = systemState?.targetServers?.length ?? 0;
    const toolGroupCount = appConfig?.toolGroups?.length ?? 0;
    const parts: string[] = [];
    if (serverCount > 0) {
      parts.push(`${serverCount} server${serverCount !== 1 ? "s" : ""}`);
    }
    if (toolGroupCount > 0) {
      parts.push(
        `${toolGroupCount} tool group${toolGroupCount !== 1 ? "s" : ""}`,
      );
    }
    return parts.length > 0 ? parts.join(" and ") : "";
  }, [systemState?.targetServers?.length, appConfig?.toolGroups?.length]);

  const handleStartFreshClick = () => {
    setStartFreshStep("confirm");
  };

  const handleJustReset = () => {
    resetMutation.mutate(undefined, {
      onSuccess: () => {
        toast({
          title: "Setup reset",
          description: "Your setup has been cleared",
        });
        setStartFreshStep(null);
      },
      onError: () => {
        toast({
          title: "Error",
          description: "Failed to reset setup",
          variant: "destructive",
        });
      },
    });
  };

  const handleSaveAndReset = () => {
    setStartFreshStep("save");
  };

  const handleSaveSetupThenReset = () => {
    if (!saveDescription.trim()) return;
    saveMutation.mutate(saveDescription.trim(), {
      onSuccess: (result) => {
        if (result.success) {
          toast({
            title: "Setup saved",
            description: `Saved as "${result.description}"`,
          });
          setSaveDescription("");
          setStartFreshStep(null);
          resetMutation.mutate(undefined, {
            onSuccess: () => {
              handleClose();
              navigate(routes.savedSetups);
            },
          });
        } else {
          toast({
            title: "Failed to save",
            description: result.error,
            variant: "destructive",
          });
        }
      },
      onError: () => {
        toast({
          title: "Error",
          description: "Failed to save setup",
          variant: "destructive",
        });
      },
    });
  };

  const closeStartFreshDialogs = () => {
    setStartFreshStep(null);
    setSaveDescription("");
  };

  return (
    <>
      {!isOpen || !mcpxData ? null : (
        <Sheet
          open={internalOpen}
          onOpenChange={(open: boolean) => !open && handleClose()}
        >
          <SheetContent
            side="right"
            aria-describedby={undefined}
            className="w-[600px]! max-w-[600px]! gap-0 border-l border-border bg-background p-0 flex flex-col [&>button]:hidden"
          >
            <VisuallyHidden>
              <SheetTitle>MCPX</SheetTitle>
            </VisuallyHidden>
            <SheetHeader className="px-6 pt-4 pb-4 flex flex-row justify-between items-center border-b border-border gap-2 space-y-0">
              <div className="flex items-center gap-2">
                <ServerStatusBadge status={mcpxStatus} />
              </div>
              <div className="flex space-y-0 gap-1.5 items-center text-muted-foreground">
                <Tooltip>
                  <TooltipTrigger asChild>
                    <Button
                      variant="ghost"
                      size="icon-sm"
                      onClick={handleStartFreshClick}
                    >
                      <Eraser />
                    </Button>
                  </TooltipTrigger>
                  <TooltipContent side="bottom">Start Fresh</TooltipContent>
                </Tooltip>
                <Button variant="ghost" size="icon-sm" onClick={handleClose}>
                  <ArrowRightIcon />
                </Button>
              </div>
            </SheetHeader>

            <div className="px-6 py-2 flex flex-col overflow-y-auto">
              <div className="flex items-end gap-2 text-lg font-semibold mt-2 mb-1">
                <div className="w-12 h-12 rounded-[12px] flex items-center justify-center bg-linear-to-b from-primary to-(--color-fg-primary-accent)">
                  <Hexagon className="text-white w-6 h-6" strokeWidth={1} />
                </div>
                <div className="flex flex-col items-start">
                  <p className="text-2xl font-medium capitalize">MCPX</p>
                  <div className="flex items-center px-1 text-[10px] h-[20px] rounded-[4px] border border-border text-muted-foreground">
                    <span>
                      Version {getVersionNumber(mcpxData.version || "Unknown")}
                    </span>
                  </div>
                </div>
              </div>
            </div>

            <div className="px-6">
              <div className="flex gap-2">
                <ServerMetricCard
                  label="Agents"
                  value={systemState?.connectedClientClusters?.length || 0}
                />
                <ServerMetricCard
                  label="Servers"
                  value={systemState?.targetServers?.length || 0}
                />
              </div>
            </div>

            <div className="px-6 flex-1 flex flex-col overflow-hidden">
              <Separator className="my-4" />
              <div className="text-lg font-semibold mb-2">Servers</div>

              <div className="flex gap-4 items-center mb-3 shrink-0 px-1">
                <SearchInput
                  placeholder="Search..."
                  value={searchQuery}
                  onChange={(e) => setSearchQuery(e.target.value)}
                  wrapperClassName="flex-1 shrink-0"
                  className="bg-background"
                />
              </div>

              <div className="space-y-3 overflow-y-auto px-1 pt-1 flex-1 min-h-0 pb-4">
                {filteredServers.length === 0 ? (
                  <div className="rounded-lg border border-border bg-muted/20 py-8 text-center">
                    <h4 className="mb-2 font-semibold text-foreground">
                      No Servers
                    </h4>
                    <p className="mb-4 text-muted-foreground">
                      No servers are currently connected.
                    </p>
                  </div>
                ) : (
                  filteredServers.map((server) => (
                    <McpxServerCard
                      key={server.name}
                      server={server}
                      pendingToggle={pendingServerToggles.get(server.name)}
                      onToggleChange={(checked) => {
                        setPendingServerToggles((prev) => {
                          const newMap = new Map(prev);
                          if (checked === undefined) {
                            newMap.delete(server.name);
                          } else {
                            newMap.set(server.name, checked);
                          }
                          return newMap;
                        });
                      }}
                    />
                  ))
                )}
              </div>
            </div>

            <div className="shrink-0 border-t border-border bg-background p-4">
              <div className="flex gap-3 justify-end">
                <Button onClick={saveConfiguration} disabled={!hasChanges}>
                  Save
                </Button>
              </div>
            </div>
          </SheetContent>
        </Sheet>
      )}

      <Dialog
        open={startFreshStep === "confirm"}
        onOpenChange={(open) => !open && closeStartFreshDialogs()}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Start Fresh</DialogTitle>
            <DialogDescription>
              {currentSetupSummary
                ? `Starting fresh will reset all servers and configuration. Your current setup has ${currentSetupSummary}. Would you like to save it first?`
                : "Starting fresh will reset all servers and configuration. Would you like to save your current setup first?"}
            </DialogDescription>
          </DialogHeader>
          <DialogFooter className="flex-col sm:flex-row gap-2">
            <Button variant="secondary" onClick={closeStartFreshDialogs}>
              Cancel
            </Button>
            <Button
              variant="destructive"
              onClick={handleJustReset}
              disabled={resetMutation.isPending}
            >
              {resetMutation.isPending ? "Resetting..." : "Just Reset"}
            </Button>
            <Button
              onClick={handleSaveAndReset}
              className="bg-primary hover:bg-primary/80 text-primary-foreground"
            >
              Save & Reset
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog
        open={startFreshStep === "save"}
        onOpenChange={(open) => !open && closeStartFreshDialogs()}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Save Current Setup</DialogTitle>
            <DialogDescription>
              Give your setup a description so you can identify it later.
            </DialogDescription>
          </DialogHeader>
          <div className="py-4">
            <Label htmlFor="start-fresh-description">Description</Label>
            <Input
              id="start-fresh-description"
              value={saveDescription}
              onChange={(e) => setSaveDescription(e.target.value)}
              placeholder="e.g., Production config with GitHub and Slack"
              className="mt-2"
              onKeyDown={(e) => {
                if (e.key === "Enter" && saveDescription.trim()) {
                  handleSaveSetupThenReset();
                }
              }}
            />
          </div>
          <DialogFooter>
            <Button variant="secondary" onClick={closeStartFreshDialogs}>
              Cancel
            </Button>
            <Button
              onClick={handleSaveSetupThenReset}
              disabled={
                !saveDescription.trim() ||
                saveMutation.isPending ||
                resetMutation.isPending
              }
              className="bg-primary hover:bg-primary/80 text-primary-foreground"
            >
              {saveMutation.isPending || resetMutation.isPending
                ? "Saving..."
                : "Save & Reset"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
};
