import { Button } from "@/components/ui/button";
import { SearchInput } from "@/components/ui/search-input";
import { AccessControlsStore, ToolGroup } from "@/store";
import { CircleX, CopyPlus, Edit, Plus, Trash2 } from "lucide-react";
import { useMemo, useRef, useState } from "react";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "../ui/card";
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
import { ToolGroupModal } from "./ToolGroupModal";

export function ToolGroups({
  isPendingUpdateAppConfig,
  mcpServers,
  setProfiles,
  setToolGroups,
  toolGroups,
}: {
  isPendingUpdateAppConfig: boolean;
  mcpServers: {
    name: string;
    tools: {
      name: string;
      description: string | undefined;
    }[];
  }[];
  setProfiles: AccessControlsStore["setProfiles"];
  setToolGroups: AccessControlsStore["setToolGroups"];
  toolGroups: ToolGroup[];
}) {
  const [showToolGroupModal, setShowToolGroupModal] = useState(false);
  const [toolGroupModalInitialData, setToolGroupModalInitialData] =
    useState<ToolGroup | null>(null);
  const inputRef = useRef<HTMLInputElement | null>(null);
  const [search, setSearch] = useState("");
  const displayedToolGroups = useMemo(
    () =>
      toolGroups.filter(
        (group) =>
          group.name.toLowerCase().includes(search.toLowerCase()) ||
          Object.entries(group.services).some(
            ([serviceName, tools]) =>
              serviceName.toLowerCase().includes(search.toLowerCase()) ||
              tools.some((tool) =>
                tool.toLowerCase().includes(search.toLowerCase()),
              ),
          ),
      ),
    [search, toolGroups],
  );

  const saveToolGroup = (group: ToolGroup) => {
    const isExistingGroup =
      toolGroupModalInitialData && toolGroups.some((tg) => tg.id === group.id);
    if (isExistingGroup) {
      const { id: existingGroupId } = toolGroupModalInitialData;
      // Reset the modal state
      setToolGroupModalInitialData(null);
      // Update the existing group
      setToolGroups((prev) =>
        prev.map((p) => (p.id === existingGroupId ? group : p)),
      );

      const oldName = toolGroups.find((tg) => tg.id === existingGroupId)?.name;
      if (oldName === group.name) return;

      // Update the tool group name in profiles that have it
      setProfiles((prev) =>
        prev.map((p) =>
          p.toolGroups?.includes(existingGroupId)
            ? {
                ...p,
                toolGroups: p.toolGroups.map((tg) =>
                  tg === existingGroupId ? group.id : tg,
                ),
              }
            : p,
        ),
      );
      return;
    }

    setToolGroups((prev) => [
      ...prev,
      { ...group, id: `tool_group_${toolGroups.length}` },
    ]);
  };

  const removeToolGroup = (group: ToolGroup) => {
    const { id } = group;

    setToolGroups((prev) => prev.filter((p) => p.id !== id));

    setProfiles((prev) =>
      prev.map((p) =>
        // Remove the tool group from profiles that have it
        p.toolGroups?.includes(id)
          ? {
              ...p,
              toolGroups: p.toolGroups.filter((tg) => tg !== id),
            }
          : p,
      ),
    );
  };

  const openCreateModal = () => {
    setToolGroupModalInitialData(null);
    setShowToolGroupModal(true);
  };

  const openEditModal = (group: ToolGroup) => {
    setToolGroupModalInitialData(group);
    setShowToolGroupModal(true);
  };

  const duplicateToolGroup = (group: ToolGroup) => {
    const newGroup = {
      ...group,
      id: `tool_group_${toolGroups.length}`,
      name: `${group.name}_Copy`,
    };
    openEditModal(newGroup);
  };

  const resetSearch = () => {
    setSearch("");
    inputRef.current?.focus();
  };

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        {toolGroups.length > 0 && (
          <>
            <h3 className="text-lg font-medium">Tool Groups</h3>
            <Button
              onClick={() => openCreateModal()}
              size="sm"
              variant="secondary"
              className="px-2 border-ring text-primary hover:bg-accent hover:text-primary/80 focus:text-primary/80 focus:bg-accent"
              disabled={isPendingUpdateAppConfig}
            >
              <Plus className="w-4 h-4 mr-2" />
              Add Tool Group
            </Button>
          </>
        )}
      </div>
      {toolGroups.length === 0 && (
        <div className="flex flex-col text-lg text-muted-foreground justify-center items-center gap-4 h-64">
          <span>No tool groups found</span>
          <Button
            onClick={() => openCreateModal()}
            variant="secondary"
            className="px-2 border-ring text-primary hover:bg-accent hover:text-primary/80 focus:text-primary/80 focus:bg-accent"
            disabled={isPendingUpdateAppConfig}
          >
            <Plus className="w-4 h-4 mr-2" />
            Add Tool Group
          </Button>
        </div>
      )}
      {toolGroups.length > 0 && (
        <div className="flex items-center focus-within:border-(--color-border-secondary) focus-within:border-solid self-start">
          <SearchInput
            className="bg-background shadow-none rounded-md border border-ring focus-visible:ring-0 font-normal text-sm h-7.5 w-[180px]"
            placeholder="Search tool groups..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            ref={inputRef}
          />
          <Tooltip>
            <TooltipTrigger asChild>
              <Button
                onClick={resetSearch}
                variant="ghost"
                className="background-transparent focus-visible:ring-0 hover:text-primary focus:text-primary focus-visible:bg-popover h-7 w-4 rounded-none"
              >
                <CircleX />
              </Button>
            </TooltipTrigger>
            <TooltipContent
              align="center"
              className="shadow-sm bg-card text-muted-foreground text-xs"
            >
              Clear search
            </TooltipContent>
          </Tooltip>
        </div>
      )}
      {search && displayedToolGroups.length === 0 && toolGroups.length > 0 && (
        <div className="flex flex-col text-lg text-muted-foreground justify-center items-center gap-4 h-64">
          <span>No matches</span>
          <Button
            onClick={resetSearch}
            variant="secondary"
            className="px-2 border-ring text-primary hover:bg-accent hover:text-primary/80 focus:text-primary/80 focus:bg-accent"
          >
            <CircleX className="w-4 h-4 mr-2" />
            Clear Search
          </Button>
        </div>
      )}
      {displayedToolGroups.length > 0 && (
        <div className="flex flex-wrap items-start gap-4">
          {displayedToolGroups.map((group) => (
            <Card
              key={group.id}
              className="bg-card border-primary/80 w-64 group"
            >
              <CardHeader className="flex flex-row gap-2 items-start justify-between relative h-20 pb-3">
                <CardTitle className="flex justify-end items-center gap-1.5 font-semibold line-clamp-2 leading-tight">
                  {group.name}
                </CardTitle>
                <div className="flex justify-end items-start gap-1.5 absolute top-2 right-4 bg-card rounded-md">
                  <Tooltip disableHoverableContent>
                    <TooltipTrigger asChild>
                      <Button
                        onClick={() => openEditModal(group)}
                        size="icon"
                        variant="secondary"
                        className="hidden group-hover:flex"
                        disabled={isPendingUpdateAppConfig}
                      >
                        <Edit className="w-4 h-4" />
                      </Button>
                    </TooltipTrigger>
                    <TooltipContent
                      align="center"
                      className="shadow-sm bg-card text-muted-foreground text-xs"
                      sideOffset={10}
                    >
                      Edit Group
                    </TooltipContent>
                  </Tooltip>
                  <Tooltip disableHoverableContent>
                    <TooltipTrigger asChild>
                      <Button
                        onClick={() => duplicateToolGroup(group)}
                        size="icon"
                        variant="secondary"
                        className="hover:shadow-md hidden group-hover:flex"
                        disabled={isPendingUpdateAppConfig}
                      >
                        <CopyPlus className="w-4 h-4" />
                      </Button>
                    </TooltipTrigger>
                    <TooltipContent
                      align="center"
                      className="shadow-sm bg-card text-muted-foreground text-xs"
                      sideOffset={10}
                    >
                      Duplicate Group
                    </TooltipContent>
                  </Tooltip>
                  <Tooltip disableHoverableContent>
                    <TooltipTrigger asChild>
                      <Button
                        onClick={() => removeToolGroup(group)}
                        size="icon"
                        variant="secondary"
                        className="hidden group-hover:flex"
                        disabled={isPendingUpdateAppConfig}
                      >
                        <Trash2 className="w-4 h-4" />
                      </Button>
                    </TooltipTrigger>
                    <TooltipContent
                      align="center"
                      className="shadow-sm bg-card text-muted-foreground text-xs"
                      sideOffset={10}
                    >
                      Delete Group
                    </TooltipContent>
                  </Tooltip>
                </div>
              </CardHeader>
              <CardContent className="h-52">
                {Object.keys(group.services).length &&
                Object.values(group.services).some((tools) => tools?.length) ? (
                  <div>
                    <div className="flex flex-col gap-2 bg-transparent">
                      <div className="text-sm grid grid-cols-[minmax(0,1fr)_auto] gap-2 py-2 rounded-md">
                        <strong className="text-ellipsis whitespace-nowrap overflow-hidden">
                          Service
                        </strong>
                        <span className="ml-4"># Tools</span>
                      </div>
                    </div>
                    <div className="flex flex-col gap-2">
                      {Object.entries(group.services)
                        .filter(([, tools]) => tools?.length)
                        .sort(
                          ([, toolsA], [, toolsB]) =>
                            toolsB.length - toolsA.length,
                        )
                        .slice(0, 3)
                        .flatMap(([service, tools]) => (
                          <div
                            key={service}
                            className="text-sm grid grid-cols-[minmax(0,1fr)_auto] gap-2 bg-secondary p-2 rounded-md"
                          >
                            <strong className="text-ellipsis whitespace-nowrap overflow-hidden">
                              {service}
                            </strong>
                            <span className="ml-4">{tools.length}</span>
                          </div>
                        ))}
                    </div>
                    {Object.entries(group.services).filter(
                      ([, tools]) => tools?.length,
                    ).length > 3 && (
                      <CardDescription className="mt-2 text-xs">
                        <span className="">
                          +{" "}
                          {Object.entries(group.services).filter(
                            ([, tools]) => tools?.length,
                          ).length - 3}{" "}
                          more service
                          {Object.entries(group.services).filter(
                            ([, tools]) => tools?.length,
                          ).length -
                            3 >
                          1
                            ? "s"
                            : ""}{" "}
                          with{" "}
                          {Object.entries(group.services)
                            .sort(
                              ([, toolsA], [, toolsB]) =>
                                toolsB.length - toolsA.length,
                            )
                            .filter(([_, tools]) => tools?.length)
                            .slice(3)
                            .reduce(
                              (acc, [, tools]) => acc + tools.length,
                              0,
                            )}{" "}
                          tool
                          {Object.entries(group.services)
                            .sort(
                              ([, toolsA], [, toolsB]) =>
                                toolsB.length - toolsA.length,
                            )
                            .filter(([_, tools]) => tools?.length)
                            .slice(1)
                            .reduce(
                              (acc, [, tools]) => acc + tools.length,
                              0,
                            ) !== 0
                            ? "s"
                            : ""}
                        </span>
                      </CardDescription>
                    )}
                  </div>
                ) : (
                  <div className="flex flex-col items-center justify-center h-full">
                    <CardDescription className="text-muted-foreground">
                      No tools selected in this group.
                    </CardDescription>
                    <CardDescription className="text-muted-foreground flex items-center">
                      Click
                      <Button
                        className="p-2 text-primary hover:text-primary/80 focus:text-primary/80"
                        onClick={() => openEditModal(group)}
                      >
                        <Edit className="w-4 h-4" />
                      </Button>
                      to add some.
                    </CardDescription>
                  </div>
                )}
              </CardContent>
            </Card>
          ))}
        </div>
      )}

      {showToolGroupModal && (
        <ToolGroupModal
          initialData={toolGroupModalInitialData}
          mcpServers={mcpServers}
          onClose={() => setShowToolGroupModal(false)}
          saveToolGroup={saveToolGroup}
          toolGroups={toolGroups}
        />
      )}
    </div>
  );
}
