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

const UpdateAttributeMutation = graphql(`
  mutation UpdateAttribute($id: ID!, $name: String, $values: [UpdateAttributeInputValues!]) {
    updateAttribute(id: $id, name: $name, values: $values) {
      id
    }
  }
`);

const DeleteAttributeMutation = graphql(`
  mutation DeleteAttribute($id: ID!) {
    deleteAttribute(id: $id) {
      id
    }
  }
`);

export const AttributeActionsFragment = graphql(`
  fragment AttributeActions on ProductAttribute {
    id
    name
    productAttributeValues {
      edges {
        node {
          id
          label
        }
      }
    }
  }
`);

interface AttributeActionsProps {
  attribute: FragmentOf<typeof AttributeActionsFragment>;
}

interface ExistingValue {
  id: string;
  label: string;
}

interface NewValue {
  tempId: string;
  label: string;
}

export const AttributeActions = ({ attribute: attributeFragment }: AttributeActionsProps) => {
  const attribute = readFragment(AttributeActionsFragment, attributeFragment);
  const navigate = useNavigate();
  const toast = useToast();
  const [{ fetching: updating }, updateAttribute] = useMutation(UpdateAttributeMutation);
  const [{ fetching: deleting }, deleteAttribute] = useMutation(DeleteAttributeMutation);

  const [editOpen, setEditOpen] = useState(false);
  const [editName, setEditName] = useState("");
  const [existingValues, setExistingValues] = useState<ExistingValue[]>([]);
  const [newValues, setNewValues] = useState<NewValue[]>([]);
  const [newLabelInput, setNewLabelInput] = useState("");

  const openEditDialog = () => {
    const currentValues = attribute.productAttributeValues?.edges?.map((e) => e.node) ?? [];
    setEditName(attribute.name);
    setExistingValues(currentValues.map((v) => ({ id: v.id, label: v.label })));
    setNewValues([]);
    setNewLabelInput("");
    setEditOpen(true);
  };

  const updateExistingLabel = (id: string, label: string) => {
    setExistingValues((prev) => prev.map((v) => (v.id === id ? { ...v, label } : v)));
  };

  const removeExistingValue = (id: string) => {
    setExistingValues((prev) => prev.filter((v) => v.id !== id));
  };

  const addNewValue = () => {
    const label = newLabelInput.trim();
    if (!label) return;
    setNewValues((prev) => [...prev, { tempId: crypto.randomUUID(), label }]);
    setNewLabelInput("");
  };

  const removeNewValue = (tempId: string) => {
    setNewValues((prev) => prev.filter((v) => v.tempId !== tempId));
  };

  const handleSave = () => {
    const values = [
      ...existingValues.map((v) => ({ id: v.id, label: v.label })),
      ...newValues.map((v) => ({ label: v.label })),
    ];
    void updateAttribute(
      {
        id: attribute.id,
        name: editName !== attribute.name ? editName : undefined,
        values,
      },
      { additionalTypenames: ["ProductAttribute", "ProductAttributeValue"] },
    ).then((result) => {
      if (result.error) {
        toast.error(result.error);
        return;
      }
      toast.success("Attribute updated");
      setEditOpen(false);
    });
  };

  return (
    <>
      <ActionPanel
        title="Actions"
        actions={[
          {
            key: "edit",
            label: "Edit Attribute",
            icon: <Pencil />,
            onClick: openEditDialog,
          },
          {
            key: "delete",
            label: "Delete Attribute",
            icon: <Trash2 />,
            variant: "destructive",
            loading: deleting,
            onClick: () =>
              void deleteAttribute(
                { id: attribute.id },
                { additionalTypenames: ["ProductAttribute"] },
              ).then((result) => {
                if (result.error) {
                  toast.error(result.error);
                  return;
                }
                toast.success("Attribute deleted successfully");
                void navigate("/product/attribute");
              }),
          },
        ]}
      />

      <Dialog.Root open={editOpen} onOpenChange={(open) => !open && setEditOpen(false)}>
        <Dialog.Content>
          <Dialog.Header>
            <Dialog.Title>Edit Attribute</Dialog.Title>
            <Dialog.Description>Update name and manage values.</Dialog.Description>
          </Dialog.Header>
          <div className="space-y-4 py-4">
            <div>
              <label className="mb-1 block text-sm font-medium">Name</label>
              <Input value={editName} onChange={(e) => setEditName(e.target.value)} />
            </div>

            <div>
              <label className="mb-1 block text-sm font-medium">Values</label>
              <div className="space-y-1">
                {existingValues.map((v) => (
                  <div key={v.id} className="flex items-center gap-2 rounded border px-2 py-1">
                    <Input
                      className="h-7 flex-1 text-sm"
                      value={v.label}
                      onChange={(e) => updateExistingLabel(v.id, e.target.value)}
                    />
                    <button
                      type="button"
                      onClick={() => removeExistingValue(v.id)}
                      className="text-muted-foreground hover:text-destructive"
                    >
                      <X className="h-4 w-4" />
                    </button>
                  </div>
                ))}
                {newValues.map((v) => (
                  <div
                    key={v.tempId}
                    className="flex items-center gap-2 rounded border border-dashed px-2 py-1"
                  >
                    <span className="flex-1 text-sm">
                      {v.label} <span className="text-muted-foreground">(new)</span>
                    </span>
                    <button
                      type="button"
                      onClick={() => removeNewValue(v.tempId)}
                      className="text-muted-foreground hover:text-destructive"
                    >
                      <X className="h-4 w-4" />
                    </button>
                  </div>
                ))}
                {existingValues.length === 0 && newValues.length === 0 && (
                  <p className="text-muted-foreground text-sm">No values</p>
                )}
              </div>
              <div className="mt-2 flex gap-2">
                <Input
                  placeholder="New value label"
                  value={newLabelInput}
                  onChange={(e) => setNewLabelInput(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === "Enter") {
                      e.preventDefault();
                      addNewValue();
                    }
                  }}
                />
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  onClick={addNewValue}
                  disabled={!newLabelInput.trim()}
                >
                  <Plus className="h-4 w-4" />
                </Button>
              </div>
            </div>
          </div>
          <Dialog.Footer>
            <Button variant="outline" onClick={() => setEditOpen(false)}>
              Cancel
            </Button>
            <Button onClick={handleSave} disabled={updating || !editName}>
              {updating ? "Saving..." : "Save"}
            </Button>
          </Dialog.Footer>
        </Dialog.Content>
      </Dialog.Root>
    </>
  );
};
