import {
  type CreateLevelsDto,
  type MembershipLevelListItem,
  useCreateMembershipLevelMutation,
  useUpdateMembershipLevelMutation,
} from "@buildingai/services/console";
import { Button } from "@buildingai/ui/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@buildingai/ui/components/ui/dialog";
import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@buildingai/ui/components/ui/form";
import { ImageUpload } from "@buildingai/ui/components/ui/image-upload";
import { Input } from "@buildingai/ui/components/ui/input";
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@buildingai/ui/components/ui/input-group";
import { ScrollArea } from "@buildingai/ui/components/ui/scroll-area";
import { Textarea } from "@buildingai/ui/components/ui/textarea";
import {
  closestCenter,
  DndContext,
  type DragEndEvent,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
} from "@dnd-kit/core";
import {
  SortableContext,
  sortableKeyboardCoordinates,
  useSortable,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { zodResolver } from "@hookform/resolvers/zod";
import { GripVertical, Loader2, Plus, Trash2 } from "lucide-react";
import { useEffect } from "react";
import type { Control, Resolver } from "react-hook-form";
import { useFieldArray, useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";

const benefitSchema = z.object({
  icon: z.string().optional(),
  content: z.string().optional(),
});

const formSchema = z.object({
  name: z.string().min(1, "等级名称必须填写").max(64, "等级名称不能超过64个字符"),
  level: z
    .union([z.number(), z.string()])
    .transform((v) => (typeof v === "string" ? Number(v) : v))
    .pipe(z.number().int().min(1, "等级级别必须大于等于1")),
  icon: z.string().optional(),
  givePower: z
    .union([z.number(), z.string()])
    .transform((v) => (typeof v === "string" ? Number(v) : v))
    .pipe(z.number().int().min(0, "每月赠送积分不能为负数"))
    .optional(),
  storageCapacity: z
    .union([z.number(), z.string()])
    .transform((v) => (typeof v === "string" ? Number(v) : v))
    .pipe(z.number().int().min(0, "赠送知识库空间不能为负数"))
    .optional(),
  description: z.string().max(255).optional(),
  benefits: z.array(benefitSchema).optional(),
});

type FormValues = z.infer<typeof formSchema>;

type LevelFormDialogProps = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  level?: MembershipLevelListItem | null;
  onSuccess?: () => void;
};

const defaultBenefit = { icon: "", content: "" };

type SortableBenefitItemProps = {
  id: string;
  index: number;
  control: Control<FormValues>;
  canRemove: boolean;
  onRemove: (index: number) => void;
};

function SortableBenefitItem({
  id,
  index,
  control,
  canRemove,
  onRemove,
}: SortableBenefitItemProps) {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
    id,
  });

  return (
    <div
      ref={setNodeRef}
      style={{
        transform: CSS.Transform.toString(transform),
        transition,
      }}
      className={`flex flex-wrap items-center gap-2 rounded-lg border p-3 ${
        isDragging ? "bg-background relative z-20 shadow-md" : ""
      }`}
    >
      <button
        type="button"
        className="text-muted-foreground hover:text-foreground flex size-8 shrink-0 cursor-grab items-center justify-center rounded-md active:cursor-grabbing"
        aria-label="拖拽排序"
        {...attributes}
        {...listeners}
      >
        <GripVertical className="size-4" />
      </button>
      <FormField
        control={control}
        name={`benefits.${index}.icon`}
        render={({ field: iconField }) => (
          <FormItem>
            <FormLabel className="text-xs">图标</FormLabel>
            <FormControl>
              <ImageUpload
                className="h-10 w-10"
                size="sm"
                value={iconField.value || undefined}
                onChange={(url) => iconField.onChange(url ?? "")}
                forceMobile
              />
            </FormControl>
          </FormItem>
        )}
      />
      <FormField
        control={control}
        name={`benefits.${index}.content`}
        render={({ field: contentField }) => (
          <FormItem className="flex-1">
            <FormLabel className="text-xs">权益内容</FormLabel>
            <FormControl>
              <Input placeholder="权益描述" className="h-10" {...contentField} />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />
      <Button
        type="button"
        variant="ghost"
        size="icon"
        className="text-muted-foreground hover:text-destructive mt-6 size-8 shrink-0"
        onClick={() => onRemove(index)}
        disabled={!canRemove}
      >
        <Trash2 className="size-4" />
      </Button>
    </div>
  );
}

export const LevelFormDialog = ({ open, onOpenChange, level, onSuccess }: LevelFormDialogProps) => {
  const isEditMode = !!level;

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema) as Resolver<FormValues>,
    defaultValues: {
      name: "",
      level: 1,
      icon: "",
      givePower: 0,
      storageCapacity: 0,
      description: "",
      benefits: [defaultBenefit],
    },
  });

  const { fields, append, remove, move } = useFieldArray({
    control: form.control,
    name: "benefits",
  });
  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    }),
  );

  useEffect(() => {
    if (open) {
      if (level) {
        form.reset({
          name: level.name,
          level: level.level,
          icon: level.icon ?? "",
          givePower: level.givePower ?? 0,
          storageCapacity: level.storageCapacity ?? 0,
          description: level.description ?? "",
          benefits:
            level.benefits && level.benefits.length > 0
              ? level.benefits.map((b) => ({ icon: b.icon ?? "", content: b.content ?? "" }))
              : [defaultBenefit],
        });
      } else {
        form.reset({
          name: "",
          level: 1,
          icon: "",
          givePower: 0,
          description: "",
          benefits: [defaultBenefit],
        });
      }
    }
  }, [open, level, form]);

  const createMutation = useCreateMembershipLevelMutation({
    onSuccess: () => {
      toast.success("等级创建成功");
      onOpenChange(false);
      onSuccess?.();
    },
  });

  const updateMutation = useUpdateMembershipLevelMutation({
    onSuccess: () => {
      toast.success("等级更新成功");
      onOpenChange(false);
      onSuccess?.();
    },
  });

  const isPending = createMutation.isPending || updateMutation.isPending;

  const handleBenefitDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;
    if (!over || active.id === over.id) return;

    const oldIndex = fields.findIndex((field) => field.id === active.id);
    const newIndex = fields.findIndex((field) => field.id === over.id);
    if (oldIndex === -1 || newIndex === -1) return;

    move(oldIndex, newIndex);
  };

  const handleSubmit = (values: FormValues) => {
    const body: CreateLevelsDto = {
      name: values.name,
      level: values.level,
      icon: values.icon || undefined,
      givePower: values.givePower ?? 0,
      storageCapacity: values.storageCapacity ?? 0,
      description: values.description || undefined,
      benefits: values.benefits?.filter((b) => b.content?.trim())?.length
        ? values.benefits
            ?.filter((b) => b.content?.trim())
            .map((b) => ({ icon: b.icon ?? "", content: b.content!.trim() }))
        : undefined,
    };
    if (isEditMode && level) {
      updateMutation.mutate({ id: level.id, body });
    } else {
      createMutation.mutate(body);
    }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="gap-0 p-0 sm:max-w-lg">
        <DialogHeader className="p-4">
          <DialogTitle>{isEditMode ? "编辑等级" : "新增等级"}</DialogTitle>
          <DialogDescription>
            {isEditMode ? "修改会员等级信息" : "添加一个新的会员等级"}
          </DialogDescription>
        </DialogHeader>

        <ScrollArea className="max-h-[80vh]">
          <Form {...form}>
            <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4 p-4 pt-0 pb-17">
              <FormField
                control={form.control}
                name="name"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>等级名称</FormLabel>
                    <FormControl>
                      <Input placeholder="请输入等级名称" {...field} />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <FormField
                control={form.control}
                name="level"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>等级级别</FormLabel>
                    <FormControl>
                      <Input type="number" min={1} placeholder="数值越大等级越高" {...field} />
                    </FormControl>
                    <FormDescription>等级数值越大表示等级越高</FormDescription>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <FormField
                control={form.control}
                name="icon"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>等级图标</FormLabel>
                    <FormControl>
                      <ImageUpload
                        size="lg"
                        value={field.value || undefined}
                        onChange={(url) => field.onChange(url ?? "")}
                      />
                    </FormControl>
                    <FormDescription>推荐尺寸: 100x100px，支持 PNG、JPG、JPEG</FormDescription>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <FormField
                control={form.control}
                name="givePower"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>每月赠送积分</FormLabel>
                    <FormControl>
                      <Input type="number" min={0} placeholder="0" {...field} />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <FormField
                control={form.control}
                name="storageCapacity"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>赠送知识库空间</FormLabel>
                    <FormControl>
                      <InputGroup>
                        <InputGroupInput
                          id="inline-end-input"
                          type="number"
                          min={0}
                          placeholder="0"
                          {...field}
                        />
                        <InputGroupAddon align="inline-end">MB</InputGroupAddon>
                      </InputGroup>
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <FormField
                control={form.control}
                name="description"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>等级描述</FormLabel>
                    <FormControl>
                      <Textarea
                        placeholder="简要描述该等级权益"
                        className="min-h-[80px] resize-none"
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <div className="space-y-3">
                <div className="bg-background sticky top-0 z-10 flex items-center justify-between">
                  <FormLabel>会员权益</FormLabel>
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="h-8"
                    onClick={() => append(defaultBenefit)}
                  >
                    <Plus className="mr-1 size-4" />
                    添加权益
                  </Button>
                </div>
                <p className="text-muted-foreground text-sm">
                  每条权益由图标与文本组成，可添加多条，拖动左侧手柄调整展示顺序
                </p>
                <DndContext
                  sensors={sensors}
                  collisionDetection={closestCenter}
                  onDragEnd={handleBenefitDragEnd}
                >
                  <SortableContext
                    items={fields.map((field) => field.id)}
                    strategy={verticalListSortingStrategy}
                  >
                    <div className="space-y-3">
                      {fields.map((field, index) => (
                        <SortableBenefitItem
                          key={field.id}
                          id={field.id}
                          index={index}
                          control={form.control}
                          canRemove={fields.length > 1}
                          onRemove={remove}
                        />
                      ))}
                    </div>
                  </SortableContext>
                </DndContext>
              </div>

              <DialogFooter className="bg-background absolute bottom-0 left-0 w-full flex-row justify-end rounded-lg p-4">
                <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
                  取消
                </Button>
                <Button type="submit" disabled={isPending}>
                  {isPending && <Loader2 className="animate-spin" />}
                  {isEditMode ? "保存" : "新增"}
                </Button>
              </DialogFooter>
            </form>
          </Form>
        </ScrollArea>
      </DialogContent>
    </Dialog>
  );
};
