import { ActionPanel, Button, Dialog, useNavigate } from "@tailor-platform/app-shell";
import { Pencil, Trash2, ArrowRightLeft } from "lucide-react";
import { useState } from "react";
import { useMutation, useQuery } from "urql";
import { graphql, type FragmentOf, readFragment } from "@/graphql";
import { useToast } from "@/hooks/use-toast";

const DeleteCategoryMutation = graphql(`
  mutation DeleteCategory($id: ID!) {
    deleteCategory(id: $id) {
      id
    }
  }
`);

const MoveCategoryMutation = graphql(`
  mutation MoveCategory($id: ID!, $newParentId: ID) {
    moveCategory(id: $id, newParentId: $newParentId) {
      id
    }
  }
`);

const CategoriesForMoveQuery = graphql(`
  query CategoriesForMove {
    productCategories {
      edges {
        node {
          id
          name
        }
      }
    }
  }
`);

export const CategoryActionsFragment = graphql(`
  fragment CategoryActions on ProductCategory {
    id
    parentId
  }
`);

interface CategoryActionsProps {
  category: FragmentOf<typeof CategoryActionsFragment>;
}

type DialogType = "move" | null;

export const CategoryActions = ({ category: categoryFragment }: CategoryActionsProps) => {
  const category = readFragment(CategoryActionsFragment, categoryFragment);
  const navigate = useNavigate();
  const toast = useToast();
  const [{ fetching: deleting }, deleteCategory] = useMutation(DeleteCategoryMutation);
  const [{ fetching: moving }, moveCategory] = useMutation(MoveCategoryMutation);

  const [{ data: categoriesData }] = useQuery({ query: CategoriesForMoveQuery });

  const [openDialog, setOpenDialog] = useState<DialogType>(null);
  const [selectedParentId, setSelectedParentId] = useState("");

  const categories =
    categoriesData?.productCategories.edges
      .map((e) => e.node)
      .filter((c) => c.id !== category.id) ?? [];

  const handleMove = () => {
    void moveCategory(
      { id: category.id, newParentId: selectedParentId || undefined },
      { additionalTypenames: ["ProductCategory"] },
    ).then((result) => {
      if (result.error) {
        toast.error(result.error);
        return;
      }
      toast.success("Category moved");
      setOpenDialog(null);
    });
  };

  return (
    <>
      <ActionPanel
        title="Actions"
        actions={[
          {
            key: "edit",
            label: "Edit Category",
            icon: <Pencil />,
            onClick: () => navigate("edit"),
          },
          {
            key: "delete",
            label: "Delete Category",
            icon: <Trash2 />,
            variant: "destructive",
            loading: deleting,
            onClick: () =>
              void deleteCategory(
                { id: category.id },
                { additionalTypenames: ["ProductCategory"] },
              ).then((result) => {
                if (result.error) {
                  toast.error(result.error);
                  return;
                }
                toast.success("Category deleted successfully");
                void navigate("/product/category");
              }),
          },
          {
            key: "move",
            label: "Move Category",
            icon: <ArrowRightLeft />,
            onClick: () => {
              setSelectedParentId(category.parentId ?? "");
              setOpenDialog("move");
            },
          },
        ]}
      />

      <Dialog.Root
        open={openDialog === "move"}
        onOpenChange={(open) => !open && setOpenDialog(null)}
      >
        <Dialog.Content>
          <Dialog.Header>
            <Dialog.Title>Move Category</Dialog.Title>
            <Dialog.Description>
              Select a new parent category, or leave empty for root.
            </Dialog.Description>
          </Dialog.Header>
          <div className="py-4">
            <select
              className="w-full rounded-md border px-3 py-2 text-sm"
              value={selectedParentId}
              onChange={(e) => setSelectedParentId(e.target.value)}
            >
              <option value="">(Root - no parent)</option>
              {categories.map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name}
                </option>
              ))}
            </select>
          </div>
          <Dialog.Footer>
            <Button variant="outline" onClick={() => setOpenDialog(null)}>
              Cancel
            </Button>
            <Button onClick={handleMove} disabled={moving}>
              {moving ? "Moving..." : "Move"}
            </Button>
          </Dialog.Footer>
        </Dialog.Content>
      </Dialog.Root>
    </>
  );
};
