"use client";

import React, {
  useCallback,
  useLayoutEffect,
  useRef,
  useState,
} from "react";
import { StoryOverlay, StoryTextOverlay, StoryLinkOverlay } from "@/api/fetchStories";
import BoldIcon from "@/components/ui/BoldIcon";
import StoryLinkPicker, { PickedStoryLink } from "@/components/stories/StoryLinkPicker";
import { useTranslation } from "react-i18next";

const LINK_KIND_ICONS: Record<PickedStoryLink["link_kind"], string> = {
  pkg: "teacher",
  project: "briefcase",
  billboard: "flash-circle",
  shop: "shop",
  shopproduct: "box",
  booking: "calendar",
};

const TEXT_COLORS = [
  "#ffffff",
  "#000000",
  "#ff3040",
  "#ffd60a",
  "#0a84ff",
  "#30d158",
  "#ff2d92",
  "#bf5af2",
];

const MIN_FONT = 0.03;
const MAX_FONT = 0.14;

type StoryEditorProps = {
  mediaUrl: string;
  mediaType: "image" | "video";
  overlays: StoryOverlay[];
  onChange: (overlays: StoryOverlay[]) => void;
};

export default function StoryEditor({
  mediaUrl,
  mediaType,
  overlays,
  onChange,
}: StoryEditorProps) {
  const { t } = useTranslation("common");
  const containerRef = useRef<HTMLDivElement>(null);
  const [containerSize, setContainerSize] = useState({ width: 0, height: 0 });
  const [selected, setSelected] = useState<number | null>(null);
  const [textModalOpen, setTextModalOpen] = useState(false);
  const [editingIndex, setEditingIndex] = useState<number | null>(null);
  const [draftText, setDraftText] = useState("");
  const [linkPickerOpen, setLinkPickerOpen] = useState(false);

  const dragState = useRef<{
    index: number;
    moved: boolean;
  } | null>(null);

  useLayoutEffect(() => {
    const el = containerRef.current;
    if (!el) return;
    const update = () =>
      setContainerSize({ width: el.clientWidth, height: el.clientHeight });
    update();
    const ro = new ResizeObserver(update);
    ro.observe(el);
    return () => ro.disconnect();
  }, []);

  const updateOverlay = useCallback(
    (index: number, patch: Partial<StoryTextOverlay>) => {
      onChange(
        overlays.map((o, i) => {
          if (i !== index || o.type === "link") return o;
          return { ...o, ...patch };
        })
      );
    },
    [overlays, onChange]
  );

  // فقط جابجایی — روی هر دو نوع اورلی (متن/لینک) یکسان کار می‌کنه، چون هر دو x/y دارن
  const updateOverlayPosition = useCallback(
    (index: number, x: number, y: number) => {
      onChange(overlays.map((o, i) => (i === index ? { ...o, x, y } : o)));
    },
    [overlays, onChange]
  );

  const removeOverlay = useCallback(
    (index: number) => {
      onChange(overlays.filter((_, i) => i !== index));
      setSelected(null);
    },
    [overlays, onChange]
  );

  const openTextEditor = (index: number | null) => {
    if (index === null) {
      setDraftText("");
    } else {
      const overlay = overlays[index];
      setDraftText(overlay && overlay.type !== "link" ? overlay.text : "");
    }
    setEditingIndex(index);
    setTextModalOpen(true);
  };

  const closeTextEditor = () => {
    setTextModalOpen(false);
    setEditingIndex(null);
    setDraftText("");
  };

  const commitText = () => {
    const text = draftText.trim();
    if (editingIndex === null) {
      if (text) {
        const next: StoryTextOverlay = {
          text,
          x: 0.5,
          y: 0.4,
          font_size: 0.07,
          color: "#ffffff",
          background: "",
          rotation: 0,
          align: "center",
        };
        onChange([...overlays, next]);
        setSelected(overlays.length);
      }
    } else if (text) {
      updateOverlay(editingIndex, { text });
    } else {
      removeOverlay(editingIndex);
    }
    closeTextEditor();
  };

  const handlePointerDown = (
    e: React.PointerEvent<HTMLDivElement>,
    index: number
  ) => {
    e.stopPropagation();
    (e.target as HTMLElement).setPointerCapture?.(e.pointerId);
    dragState.current = { index, moved: false };
    setSelected(index);
  };

  const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {
    const state = dragState.current;
    const rect = containerRef.current?.getBoundingClientRect();
    if (!state || !rect) return;
    state.moved = true;
    const x = Math.min(1, Math.max(0, (e.clientX - rect.left) / rect.width));
    const y = Math.min(1, Math.max(0, (e.clientY - rect.top) / rect.height));
    updateOverlayPosition(state.index, x, y);
  };

  const handlePointerUp = () => {
    dragState.current = null;
  };

  const addLinkOverlay = (item: PickedStoryLink) => {
    const next: StoryLinkOverlay = {
      type: "link",
      link_kind: item.link_kind,
      link_id: item.link_id,
      link_title: item.link_title,
      x: 0.5,
      y: 0.5,
      rotation: 0,
    };
    onChange([...overlays, next]);
    setSelected(overlays.length);
    setLinkPickerOpen(false);
  };

  const selectedOverlay =
    selected !== null ? overlays[selected] : null;

  return (
    <div className="flex w-full flex-col gap-3">
      {/* Canvas frame 9:16 */}
      <div
        ref={containerRef}
        className="relative mx-auto aspect-[9/16] w-full max-w-[340px] overflow-hidden rounded-2xl bg-black"
        onPointerMove={handlePointerMove}
        onPointerUp={handlePointerUp}
        onClick={() => setSelected(null)}
      >
        {mediaType === "video" ? (
          <video
            src={mediaUrl}
            className="absolute inset-0 h-full w-full object-contain"
            playsInline
            muted
            loop
            autoPlay
          />
        ) : (
          // eslint-disable-next-line @next/next/no-img-element
          <img
            src={mediaUrl}
            alt="story"
            className="absolute inset-0 h-full w-full object-contain"
          />
        )}

        {overlays.map((o, index) => {
          if (o.type === "link") {
            return (
              <div
                key={index}
                onClick={(e) => e.stopPropagation()}
                onPointerDown={(e) => handlePointerDown(e, index)}
                style={{
                  position: "absolute",
                  left: `${o.x * 100}%`,
                  top: `${o.y * 100}%`,
                  transform: `translate(-50%, -50%) rotate(${o.rotation ?? 0}deg)`,
                  display: "flex",
                  alignItems: "center",
                  gap: 6,
                  padding: "0.4em 0.7em",
                  borderRadius: 999,
                  background: "rgba(0,0,0,0.55)",
                  color: "#fff",
                  fontSize: 13,
                  fontWeight: 700,
                  maxWidth: "80%",
                  whiteSpace: "nowrap",
                  overflow: "hidden",
                  textOverflow: "ellipsis",
                  cursor: "move",
                  touchAction: "none",
                  userSelect: "none",
                  outline:
                    selected === index ? "2px dashed rgba(255,255,255,0.7)" : "none",
                  outlineOffset: 4,
                }}
              >
                <BoldIcon name={LINK_KIND_ICONS[o.link_kind]} size={14} tinted className="text-white" />
                <span className="truncate">{o.link_title}</span>
              </div>
            );
          }

          const fontPx = Math.max(
            10,
            o.font_size * (containerSize.width || 300)
          );
          return (
            <div
              key={index}
              onClick={(e) => e.stopPropagation()}
              onPointerDown={(e) => handlePointerDown(e, index)}
              onDoubleClick={() => openTextEditor(index)}
              style={{
                position: "absolute",
                left: `${o.x * 100}%`,
                top: `${o.y * 100}%`,
                transform: `translate(-50%, -50%) rotate(${o.rotation ?? 0}deg)`,
                color: o.color,
                fontSize: `${fontPx}px`,
                lineHeight: 1.2,
                fontWeight: 700,
                textAlign: (o.align ?? "center") as React.CSSProperties["textAlign"],
                background: o.background || "transparent",
                padding: o.background ? "0.15em 0.35em" : 0,
                borderRadius: o.background ? "0.35em" : 0,
                maxWidth: "90%",
                whiteSpace: "pre-wrap",
                wordBreak: "break-word",
                cursor: "move",
                touchAction: "none",
                userSelect: "none",
                textShadow: o.background
                  ? "none"
                  : "0 1px 3px rgba(0,0,0,0.55)",
                outline:
                  selected === index ? "2px dashed rgba(255,255,255,0.7)" : "none",
                outlineOffset: 4,
              }}
            >
              {o.text}
            </div>
          );
        })}

        {/* Add-text / Add-link FABs */}
        <div className="absolute right-2 top-2 z-10 flex flex-col items-end gap-2">
          <button
            type="button"
            onClick={(e) => {
              e.stopPropagation();
              openTextEditor(null);
            }}
            className="flex items-center gap-1 rounded-full bg-black/55 px-3 py-1.5 text-xs font-semibold text-white backdrop-blur"
          >
            <BoldIcon name="add" size={16} tinted className="text-white" />
            {t("stories.addText")}
          </button>
          <button
            type="button"
            onClick={(e) => {
              e.stopPropagation();
              setLinkPickerOpen(true);
            }}
            className="flex items-center gap-1 rounded-full bg-black/55 px-3 py-1.5 text-xs font-semibold text-white backdrop-blur"
          >
            <BoldIcon name="link" size={16} tinted className="text-white" />
            {t("stories.attachLink")}
          </button>
        </div>
      </div>

      {linkPickerOpen && (
        <StoryLinkPicker onSelect={addLinkOverlay} onClose={() => setLinkPickerOpen(false)} />
      )}

      {/* Toolbar for selected overlay */}
      {selectedOverlay && selectedOverlay.type === "link" && (
        <div className="mx-auto flex w-full max-w-[340px] items-center justify-between rounded-xl border border-neutral-200 p-3 dark:border-neutral-800">
          <span className="text-xs font-semibold text-neutral-500">
            {selectedOverlay.link_title}
          </span>
          <button
            type="button"
            onClick={() => selected !== null && removeOverlay(selected)}
            className="rounded-md bg-red-50 px-2 py-1 text-xs text-red-600 dark:bg-red-950/40"
          >
            {t("stories.remove")}
          </button>
        </div>
      )}

      {selectedOverlay && selectedOverlay.type !== "link" && (
        <div className="mx-auto w-full max-w-[340px] space-y-3 rounded-xl border border-neutral-200 p-3 dark:border-neutral-800">
          <div className="flex items-center justify-between">
            <span className="text-xs font-semibold text-neutral-500">
              {t("stories.editText")}
            </span>
            <div className="flex items-center gap-2">
              <button
                type="button"
                onClick={() => openTextEditor(selected)}
                className="rounded-md bg-neutral-100 px-2 py-1 text-xs dark:bg-neutral-800"
              >
                {t("stories.changeText")}
              </button>
              <button
                type="button"
                onClick={() => selected !== null && removeOverlay(selected)}
                className="rounded-md bg-red-50 px-2 py-1 text-xs text-red-600 dark:bg-red-950/40"
              >
                {t("stories.remove")}
              </button>
            </div>
          </div>

          {/* Colors */}
          <div className="flex flex-wrap items-center gap-2">
            {TEXT_COLORS.map((c) => (
              <button
                key={c}
                type="button"
                onClick={() =>
                  selected !== null && updateOverlay(selected, { color: c })
                }
                className={`h-7 w-7 rounded-full border ${
                  selectedOverlay.color === c
                    ? "ring-2 ring-offset-2 ring-[#0095f6] dark:ring-offset-neutral-900"
                    : "border-neutral-300 dark:border-neutral-600"
                }`}
                style={{ backgroundColor: c }}
                aria-label={c}
              />
            ))}
          </div>

          {/* Highlight background toggle */}
          <button
            type="button"
            onClick={() =>
              selected !== null &&
              updateOverlay(selected, {
                background: selectedOverlay.background ? "" : "#000000",
              })
            }
            className="rounded-md bg-neutral-100 px-3 py-1 text-xs dark:bg-neutral-800"
          >
            {selectedOverlay.background ? t("stories.removeTextBg") : t("stories.addTextBg")}
          </button>

          {/* Font size */}
          <label className="flex items-center gap-3 text-xs text-neutral-500">
            {t("stories.fontSize")}
            <input
              type="range"
              min={MIN_FONT}
              max={MAX_FONT}
              step={0.005}
              value={selectedOverlay.font_size}
              onChange={(e) =>
                selected !== null &&
                updateOverlay(selected, {
                  font_size: parseFloat(e.target.value),
                })
              }
              className="flex-1 accent-[#0095f6]"
            />
          </label>
        </div>
      )}

      {/* Text input modal */}
      {textModalOpen && (
        <div className="glass-modal-overlay glass-modal-overlay--dark fixed inset-0 z-[1001] flex flex-col p-6">
          <div className="flex items-center justify-between">
            <button
              type="button"
              onClick={closeTextEditor}
              className="text-sm text-white/70"
            >
              {t("stories.cancel")}
            </button>
            <button
              type="button"
              onClick={commitText}
              className="text-sm font-semibold text-[#0095f6]"
            >
              {t("stories.confirm")}
            </button>
          </div>
          <div className="flex flex-1 items-center justify-center">
            <textarea
              autoFocus
              value={draftText}
              onChange={(e) => setDraftText(e.target.value)}
              placeholder={t("stories.storyTextPlaceholder")}
              rows={3}
              className="w-full max-w-sm resize-none bg-transparent text-center text-2xl font-bold text-white outline-none placeholder:text-white/40"
            />
          </div>
        </div>
      )}
    </div>
  );
}
