import { PencilIcon, ScrollTextIcon, TrashIcon } from "lucide-react";
import type React from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import {
  invalidateSkillQueries,
  useDeleteSkill,
  useGetSkillsSuspenseInfinite,
} from "@/api/skill";
import type { SkillBrief } 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 { useTabsStore } from "@/stores/tabs-store";
import type { Tab } from "@/types/tab";

function createSkillEditTab(skillId: number, skillName: string): Tab {
  return {
    type: "skill",
    title: i18n.t("skills.tab.edit_title_with_name", {
      ns: SIDEBAR_NAMESPACE,
      name: skillName,
    }),
    icon: "scroll-text",
    metadata: { mode: "edit", id: skillId },
  };
}

function openSkillEditTab(skillId: number, skillName: string) {
  const {
    tabs,
    add: addTab,
    setActive: setActiveTab,
  } = useTabsStore.getState();
  const existingTab = tabs.find(
    (tab) =>
      tab.type === "skill" &&
      tab.metadata.mode === "edit" &&
      tab.metadata.id === skillId,
  );

  if (existingTab) {
    setActiveTab(existingTab.id);
  } else {
    const newTab = createSkillEditTab(skillId, skillName);
    addTab(newTab);
  }
}

type SkillItemProps = {
  skill: SkillBrief;
  index: number;
  ref?: React.Ref<HTMLDivElement>;
  onDelete?: (skill: SkillBrief) => void;
};

function SkillItem({ skill, index, ref, onDelete }: SkillItemProps) {
  const { t } = useTranslation(SIDEBAR_NAMESPACE);

  const handleEdit = (e: React.MouseEvent) => {
    e.stopPropagation();
    openSkillEditTab(skill.id, skill.name);
  };

  return (
    <ActionableItem>
      <ActionableItemTrigger ref={ref} data-index={index}>
        <ActionableItemIcon seed={skill.name}>
          <ScrollTextIcon />
        </ActionableItemIcon>
        <ActionableItemInfo
          title={skill.name}
          description={skill.description || t("skills.list.no_description")}
        />
      </ActionableItemTrigger>
      <ActionableItemMenu>
        <ActionableItemMenuItem onClick={handleEdit}>
          <PencilIcon />
          <span>{t("skills.menu.edit")}</span>
        </ActionableItemMenuItem>
        <ActionableItemMenuItem
          variant="destructive"
          onClick={() => onDelete?.(skill)}
        >
          <TrashIcon />
          <span>{t("skills.menu.delete")}</span>
        </ActionableItemMenuItem>
      </ActionableItemMenu>
    </ActionableItem>
  );
}

type SkillListProps = {
  searchQuery?: string;
};

export function SkillList({ searchQuery }: SkillListProps) {
  const { t } = useTranslation(SIDEBAR_NAMESPACE);
  const removeTabs = useTabsStore((state) => state.remove);

  const trimmedQuery = searchQuery?.trim();
  const query = useGetSkillsSuspenseInfinite(
    trimmedQuery ? { query: trimmedQuery } : undefined,
    {
      query: {
        ...PAGINATED_QUERY_DEFAULT_OPTIONS,
        gcTime: SIDEBAR_QUERY_GC_TIME,
      },
    },
  );

  const deleteSkillMutation = useDeleteSkill({
    mutation: {
      async onSuccess(_, variables) {
        removeTabs(
          (tab) =>
            tab.type === "skill" &&
            tab.metadata.mode === "edit" &&
            tab.metadata.id === variables.skillId,
        );
        await invalidateSkillQueries(variables.skillId);
        toast.success(t("skills.toast.delete_success_title"), {
          description: t("skills.toast.delete_success_description"),
        });
      },
    },
  });

  const asyncConfirm = useAsyncConfirm<SkillBrief>({
    async onConfirm(skill) {
      await deleteSkillMutation.mutateAsync({ skillId: skill.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 }) => (
          <SkillItem
            key={key}
            ref={ref}
            index={index}
            skill={item}
            onDelete={asyncConfirm.trigger}
          />
        )}
      />
      <ConfirmDeleteDialog
        open={asyncConfirm.isOpen}
        description={t("skills.dialog.delete_description_with_name", {
          name: asyncConfirm.pendingData?.name ?? "",
        })}
        onConfirm={asyncConfirm.confirm}
        onCancel={asyncConfirm.cancel}
        isDeleting={asyncConfirm.isPending}
      />
    </>
  );
}
