import Button from "@/components/Button";
import ColorPicker from "@/components/ColorPicker";
import Radio from "@/components/Radio";
import { extractErrorMessage } from "@/config/func";
import type { ErrorType } from "@/helpers/types";
import { clx } from "@/helpers/utils";
import DesignSlider from "@/pages/settings/components/DesignSlider";
import { getBackgroundPatternUrl, PATTERN_BACKGROUND_OPACITY, useBackgroundPatterns } from "@/pages/settings/hooks/usePatterns";
import { useGetBackgrounds, useGetRestaurant, useSetBackground, useUpdateRestaurant } from "@/pages/settings/hooks/useSettingData";
import type { BackgroundItemType, SetBackgroundType } from "@/pages/settings/types/Types";
import { useSingleUpload } from "@/pages/uploader/hooks/useUploaderData";
import { DocumentUpload, Gallery, TickCircle, Trash } from "iconsax-react";
import { useCallback, useEffect, useMemo, useState, type FC } from "react";
import { useDropzone } from "react-dropzone";
import { toast } from "react-toastify";

const COLOR_APPLY_DELAY_MS = 500;
type BackgroundType = "pattern" | "custom";

const UPLOAD_BOX_CLASS = "w-[200px] h-[362px] rounded-2xl border border-dashed border-description";

const getPatternBgUrl = (item: BackgroundItemType) => item.url ?? item.bgUrl ?? "";

const normalizeBgUrl = (url: string) => {
  if (!url) return "";
  if (url.startsWith("http")) return url;
  return `${import.meta.env.VITE_BASE_URL}${url.startsWith("/") ? url : `/${url}`}`;
};

const DesignSettings: FC = () => {
  const [menuColor, setMenuColor] = useState("#000000");
  const [appliedColor, setAppliedColor] = useState("#000000");
  const [selectedPatternId, setSelectedPatternId] = useState<string | null>(null);
  const [backgroundType, setBackgroundType] = useState<BackgroundType>("pattern");
  const [customImage, setCustomImage] = useState<File | null>(null);
  const [customImagePreview, setCustomImagePreview] = useState<string | null>(null);
  const [existingBgUrl, setExistingBgUrl] = useState<string | null>(null);
  const [imageOpacity, setImageOpacity] = useState(100);
  const [imageBlur, setImageBlur] = useState(0);
  const [overlayDarkness, setOverlayDarkness] = useState(0);
  const [isInitialized, setIsInitialized] = useState(false);
  const { data: backgrounds } = useGetBackgrounds();
  const { mutate: setBackground, isPending: isSavingBackground } = useSetBackground();
  const { mutate: updateRestaurant, isPending: isUpdatingRestaurant } = useUpdateRestaurant();
  const { mutate: singleUpload, isPending: isUploadingImage } = useSingleUpload();
  const { patterns, isLoading: isPatternsLoading, isError: isPatternsError } = useBackgroundPatterns(appliedColor);
  const { data: restaurant, refetch } = useGetRestaurant();
  const backgroundItems = useMemo(() => backgrounds?.data ?? [], [backgrounds]);
  const isSaving = isSavingBackground || isUploadingImage || isUpdatingRestaurant;

  useEffect(() => {
    if (!restaurant?.data || isInitialized) return;

    const restaurantData = restaurant.data;
    const savedBgUrl = restaurantData.bgUrl;

    if (savedBgUrl && backgroundItems.length === 0) return;

    const color = restaurantData.menuColor || "#000000";
    setMenuColor(color);
    setAppliedColor(color);

    if (savedBgUrl) {
      const matchingPattern = backgroundItems.find((item) => getBackgroundPatternUrl(item) === normalizeBgUrl(savedBgUrl) || getPatternBgUrl(item) === savedBgUrl);

      if (matchingPattern) {
        setBackgroundType("pattern");
        setSelectedPatternId(matchingPattern.id);
      } else {
        setBackgroundType("custom");
        setExistingBgUrl(savedBgUrl);
        setCustomImagePreview(normalizeBgUrl(savedBgUrl));
        setImageOpacity(Number(restaurantData.bgOpacity) || 100);
        setImageBlur(Number(restaurantData.bgBlur) || 0);
        setOverlayDarkness(Number(restaurantData.bgOverlay) || 0);
      }
    } else {
      setSelectedPatternId("0");
    }

    setIsInitialized(true);
  }, [restaurant, backgroundItems, isInitialized]);

  useEffect(() => {
    const timer = setTimeout(() => setAppliedColor(menuColor), COLOR_APPLY_DELAY_MS);
    return () => clearTimeout(timer);
  }, [menuColor]);

  useEffect(() => {
    if (!customImage) return;

    const previewUrl = URL.createObjectURL(customImage);
    setCustomImagePreview(previewUrl);

    return () => URL.revokeObjectURL(previewUrl);
  }, [customImage]);

  const onDrop = useCallback((acceptedFiles: File[]) => {
    if (acceptedFiles[0]) {
      setCustomImage(acceptedFiles[0]);
    }
  }, []);

  const { getRootProps, getInputProps } = useDropzone({
    onDrop,
    accept: { "image/*": [] },
    multiple: false,
  });

  const handleRemoveImage = () => {
    setCustomImage(null);
    setExistingBgUrl(null);
    setCustomImagePreview(null);
    setImageOpacity(100);
    setImageBlur(0);
    setOverlayDarkness(0);
  };

  const saveCustomBackground = (bgUrl: string) => {
    const backgroundPayload: SetBackgroundType = {
      bgUrl,
      bgBlur: String(imageBlur ?? 0),
      bgOverlay: String(overlayDarkness ?? 0),
    };

    if (imageOpacity) {
      backgroundPayload.bgOpacity = String(imageOpacity);
    }

    setBackground(backgroundPayload, {
      onSuccess: () => {
        toast.success("تنظیمات طراحی با موفقیت ذخیره شد");
        refetch();
      },
      onError: (error: unknown) => {
        toast.error(extractErrorMessage(error as ErrorType, "خطا در ذخیره تنظیمات طراحی"));
      },
    });
  };

  const handleApplyChanges = () => {
    updateRestaurant(
      { menuColor },
      {
        onSuccess: () => {
          if (backgroundType === "pattern") {
            let bgUrl = "";

            if (selectedPatternId !== "0") {
              const selectedItem = backgroundItems.find((item) => item.id === selectedPatternId);
              bgUrl = selectedItem ? getPatternBgUrl(selectedItem) : "";

              if (!bgUrl) {
                toast.error("لطفاً یک پترن انتخاب کنید");
                return;
              }
            }

            setBackground(
              { bgUrl },
              {
                onSuccess: () => {
                  toast.success("تنظیمات طراحی با موفقیت ذخیره شد");
                  refetch();
                },
                onError: (error: unknown) => {
                  toast.error(extractErrorMessage(error as ErrorType, "خطا در ذخیره تنظیمات طراحی"));
                },
              },
            );
            return;
          }

          if (customImage) {
            singleUpload(customImage, {
              onSuccess: (response) => {
                const bgUrl = response?.data?.url ?? "";

                if (!bgUrl) {
                  toast.error("خطا در آپلود تصویر");
                  return;
                }

                saveCustomBackground(bgUrl);
              },
              onError: (error: ErrorType) => {
                toast.error(extractErrorMessage(error, "خطا در آپلود تصویر"));
              },
            });
            return;
          }

          if (existingBgUrl) {
            saveCustomBackground(existingBgUrl);
            return;
          }

          toast.error("لطفاً تصویر پس‌زمینه را آپلود کنید");
        },
        onError: (error: unknown) => {
          toast.error(extractErrorMessage(error as ErrorType, "خطا در ذخیره تنظیمات طراحی"));
        },
      },
    );
  };

  const isApplyDisabled = isSaving || (backgroundType === "pattern" ? !selectedPatternId : !customImage && !existingBgUrl);

  return (
    <div className="bg-white rounded-4xl p-8">
      <div className="text-lg font-light">تنظیمات طراحی</div>

      <div className="flex mt-5">
        <div className="max-w-[506px] w-full">
          <ColorPicker label="رنگ منو" value={menuColor} onChange={setMenuColor} />

          <div className="mt-7">
            <div className="flex gap-2 items-center">
              <Radio isActive={backgroundType === "pattern"} value="pattern" onChange={(value) => setBackgroundType(value as BackgroundType)} />
              <div className="text-sm">انتخاب پس زمینه</div>
            </div>

            {backgroundType === "pattern" && (
              <div className="mt-2 flex gap-3 flex-wrap">
                {isPatternsLoading && Array.from({ length: 6 }).map((_, index) => <div key={index} className="w-16 h-[139px] rounded-lg bg-secondary animate-pulse" />)}
                {!isPatternsLoading && isPatternsError && <div className="text-sm text-description">خطا در بارگذاری پترن‌ها</div>}
                {!isPatternsLoading && !isPatternsError && patterns.length === 0 && <div className="text-sm text-description">پترنی یافت نشد</div>}
                <button
                  onClick={() => setSelectedPatternId("0")}
                  type="button"
                  className={clx("relative w-16 h-[139px] rounded-lg bg-white border overflow-hidden", selectedPatternId === "0" ? "border-black" : "border-border")}
                >
                  <div className="absolute inset-0" style={{ backgroundColor: appliedColor, opacity: PATTERN_BACKGROUND_OPACITY }} />
                </button>
                {patterns.map((pattern) => (
                  <button
                    key={pattern.id}
                    type="button"
                    onClick={() => setSelectedPatternId(pattern.id)}
                    className={clx("relative w-16 h-[139px] rounded-lg bg-white border overflow-hidden", selectedPatternId === pattern.id ? "border-black" : "border-border")}
                  >
                    <div className="absolute inset-0" style={{ backgroundColor: appliedColor, opacity: PATTERN_BACKGROUND_OPACITY }} />
                    <img src={pattern.image} alt="" className="relative scale-200 w-full h-full object-cover" />
                  </button>
                ))}
              </div>
            )}
          </div>

          <div className="mt-7">
            <div className="flex gap-2 items-center">
              <Radio isActive={backgroundType === "custom"} value="custom" onChange={(value) => setBackgroundType(value as BackgroundType)} />
              <div className="text-sm">تصویر پس زمینه دلخواه</div>
            </div>

            {backgroundType === "custom" && (
              <div className="mt-2">
                {!customImagePreview ? (
                  <div {...getRootProps()} className={clx(UPLOAD_BOX_CLASS, "flex flex-col items-center justify-center gap-3 cursor-pointer bg-white")}>
                    <input {...getInputProps()} />
                    <Gallery className="size-8" color="#8C90A3" />
                    <div className="text-description text-xs text-center leading-5 px-4">تصویر مورد نظر را آپلود کنید</div>
                    <div className="flex items-center gap-1">
                      <DocumentUpload className="size-4" color="black" />
                      <div className="text-xs">آپلود</div>
                    </div>
                  </div>
                ) : (
                  <div className="flex gap-8 items-start">
                    <div className={clx(UPLOAD_BOX_CLASS, "relative shrink-0 overflow-hidden")}>
                      <img
                        src={customImagePreview}
                        alt="پس‌زمینه دلخواه"
                        className="w-full h-full object-cover"
                        style={{
                          opacity: imageOpacity / 100,
                          filter: `blur(${imageBlur * 0.2}px)`,
                        }}
                      />
                      {overlayDarkness > 0 && <div className="absolute inset-0 bg-black pointer-events-none" style={{ opacity: overlayDarkness / 100 }} />}
                      <button
                        type="button"
                        onClick={handleRemoveImage}
                        className="absolute top-1.5 right-1.5 size-5 rounded-full bg-white shadow-sm flex items-center justify-center cursor-pointer z-10"
                      >
                        <Trash size={12} color="#EF4444" variant="Bold" />
                      </button>
                    </div>

                    <div className="flex-1 min-w-0">
                      <div className="text-sm font-normal mb-4">تنظیمات</div>
                      <DesignSlider label="شفافیت تصویر" value={imageOpacity} onChange={setImageOpacity} />
                      <DesignSlider label="محوشدگی تصویر" value={imageBlur} onChange={setImageBlur} />
                      <DesignSlider label="تیرگی روکش پس زمینه" value={overlayDarkness} onChange={setOverlayDarkness} />
                    </div>
                  </div>
                )}
              </div>
            )}
          </div>
          <div className="mt-8 flex justify-end">
            <Button type="button" className="w-fit px-6" isloading={isSaving} disabled={isApplyDisabled} onClick={handleApplyChanges}>
              <div className="flex gap-2 items-center">
                <TickCircle size={20} color="#fff" />
                <span>اعمال تغییرات</span>
              </div>
            </Button>
          </div>
        </div>
      </div>
    </div>
  );
};

export default DesignSettings;
