import { PencilIcon, TrashIcon } from "lucide-react";
import { DynamicIcon } from "lucide-react/dynamic";
import type React from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import {
  invalidateAgentQueries,
  useDeleteAgent,
  useGetAgentsSuspenseInfinite,
} from "@/api/agent";
import type { AgentBrief } from "@/api/generated/schemas";
import { ConfirmDeleteDialog } from "@/components/custom/dialog/ConfirmDeteteDialog";
import { InfiniteVirtualScroll } from "@/components/custom/InfiniteScroll";
import {
  ActionableItem,
  ActionableItemIcon,
  ActionableItemInfo,
  ActionableItemMenu,
  ActionableItemMenuItem,
  ActionableItemTrigger,
} from "@/components/custom/item/ActionableItem";
import { PAGINATED_QUERY_DEFAULT_OPTIONS, SIDEBAR_QUERY_GC_TIME } from "@/constants/query-options";
import { useAsyncConfirm } from "@/hooks/use-async-confirm";
import { i18n } from "@/i18n";
import { SIDEBAR_NAMESPACE } from "@/i18n/resources";
import { resolveIconName } from "@/lib/resolve-iconname";
import { useTabsStore } from "@/stores/tabs-store";
import type { Tab } from "@/types/tab";

function createAgentEditTab(agentId: number, agentName: string): Tab {
  return {
    type: "agent",
    title: i18n.t("agents.tab.edit_title_with_name", {
      ns: SIDEBAR_NAMESPACE,
      name: agentName,
    }),
    icon: "bot",
    metadata: { mode: "edit", id: agentId },
  };
}

type OpenAgentEditTabParams = {
  agentId: number;
  agentName: string;
};

function openAgentEditTab({ agentId, agentName }: OpenAgentEditTabParams) {
  const {
    tabs,
    add: addTab,
    setActive: setActiveTab,
  } = useTabsStore.getState();
  const existingTab = tabs.find(
    (tab) =>
      tab.type === "agent" &&
      tab.metadata.mode === "edit" &&
      tab.metadata.id === agentId,
  );

  if (existingTab) {
    setActiveTab(existingTab.id);
  } else {
    const newTab = createAgentEditTab(agentId, agentName);
    addTab(newTab);
  }
}

type AgentItemProps = {
  agent: AgentBrief;
  index: number;
  ref?: React.Ref<HTMLDivElement>;
  onDelete?: (agent: AgentBrief) => void;
};

function AgentItem({ agent, index, ref, onDelete }: AgentItemProps) {
  const { t } = useTranslation(SIDEBAR_NAMESPACE);

  const handleEdit = (e: React.MouseEvent) => {
    e.stopPropagation();
    openAgentEditTab({
      agentId: agent.id,
      agentName: agent.name,
    });
  };
  return (
    <ActionableItem>
      <ActionableItemTrigger ref={ref} data-index={index}>
        <ActionableItemIcon seed={agent.name}>
          <DynamicIcon name={resolveIconName(agent.icon_name, "bot")} />
        </ActionableItemIcon>
        <ActionableItemInfo
          title={agent.name}
          description={agent.model?.name ?? t("agents.list.no_model")}
        />
      </ActionableItemTrigger>
      <ActionableItemMenu>
        <ActionableItemMenuItem onClick={handleEdit}>
          <PencilIcon />
          <span>{t("agents.menu.edit")}</span>
        </ActionableItemMenuItem>
        <ActionableItemMenuItem
          variant="destructive"
          onClick={() => onDelete?.(agent)}
        >
          <TrashIcon />
          <span>{t("agents.menu.delete")}</span>
        </ActionableItemMenuItem>
      </ActionableItemMenu>
    </ActionableItem>
  );
}

export function AgentList() {
  const { t } = useTranslation(SIDEBAR_NAMESPACE);
  const removeTabs = useTabsStore((state) => state.remove);

  const query = useGetAgentsSuspenseInfinite(undefined, {
    query: { ...PAGINATED_QUERY_DEFAULT_OPTIONS, gcTime: SIDEBAR_QUERY_GC_TIME },
  });

  const deleteAgentMutation = useDeleteAgent({
    mutation: {
      async onSuccess(_, variables) {
        removeTabs(
          (tab) =>
            tab.type === "agent" &&
            tab.metadata.mode === "edit" &&
            tab.metadata.id === variables.agentId,
        );
        await invalidateAgentQueries(variables.agentId);
        toast.success(t("agents.toast.delete_success_title"), {
          description: t("agents.toast.delete_success_description"),
        });
      },
    },
  });

  const asyncConfirm = useAsyncConfirm<AgentBrief>({
    async onConfirm(agent) {
      await deleteAgentMutation.mutateAsync({ agentId: agent.id });
    },
  });

  return (
    <>
      <InfiniteVirtualScroll
        query={query}
        className="limit-width"
        selectItems={(page) => page.items}
        getItemKey={(item) => item.id}
        itemHeight={69}
        overscan={3}
        itemRender={({ item, key, ref, index }) => (
          <AgentItem
            key={key}
            ref={ref}
            index={index}
            agent={item}
            onDelete={asyncConfirm.trigger}
          />
        )}
      />
      <ConfirmDeleteDialog
        open={asyncConfirm.isOpen}
        description={t("agents.dialog.delete_description_with_name", {
          name: asyncConfirm.pendingData?.name ?? "",
        })}
        onConfirm={asyncConfirm.confirm}
        onCancel={asyncConfirm.cancel}
        isDeleting={asyncConfirm.isPending}
      />
    </>
  );
}
