import { useEffect, useRef, useState } from "react";
import { Check, Loader2, Pencil, X } from "lucide-react";
import { cn } from "../../lib/utils";

/* ---------- digit helpers (accept both Persian & Latin input) ---------- */

const FA_DIGITS = "۰۱۲۳۴۵۶۷۸۹";
const AR_DIGITS = "٠١٢٣٤٥٦٧٨٩";

function toLatinDigits(input: string): string {
  return input
    .replace(/[۰-۹]/g, (d) => String(FA_DIGITS.indexOf(d)))
    .replace(/[٠-٩]/g, (d) => String(AR_DIGITS.indexOf(d)));
}

/** Extract only the integer digits from any incoming value ("120000.00" -> "120000"). */
function normalizeIncoming(raw: string | null | undefined): string {
  if (raw === null || raw === undefined || raw === "") return "";
  const n = parseFloat(toLatinDigits(String(raw)));
  if (!isFinite(n) || n <= 0) return "";
  return String(Math.round(n));
}

/** Keep only digits typed by the user (drops separators, letters, Persian digits normalized). */
function onlyDigits(input: string): string {
  return toLatinDigits(input).replace(/[^\d]/g, "");
}

/** Group with thousands separators for the edit input ("120000" -> "120,000"). */
function groupLatin(digits: string): string {
  if (!digits) return "";
  return digits.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

/** Persian-grouped display ("120000" -> "۱۲۰٬۰۰۰"). */
function toFaDisplay(digits: string): string {
  if (!digits) return "";
  return Number(digits).toLocaleString("fa-IR");
}

/* ------------------------------- component ------------------------------ */

interface InlinePriceEditorProps {
  /** Current raw price (decimal string) or null/"" when unset. */
  value: string | null | undefined;
  /** Called with the new integer price string, or null when cleared (only if allowEmpty). */
  onSave: (value: string | null) => void;
  isPending?: boolean;
  /** Allow saving an empty value as null (e.g. a variant inheriting the base price). */
  allowEmpty?: boolean;
  /** Muted hint shown when there is no value and we're not editing (e.g. inherited price). */
  placeholder?: string;
  suffix?: string;
  size?: "sm" | "md";
  align?: "start" | "center" | "end";
  ariaLabel?: string;
  className?: string;
}

export function InlinePriceEditor({
  value,
  onSave,
  isPending = false,
  allowEmpty = false,
  placeholder,
  suffix = "تومان",
  size = "md",
  align = "end",
  ariaLabel = "ویرایش قیمت",
  className,
}: InlinePriceEditorProps) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(""); // raw digits while editing
  // Optimistic value shown during the async save so the number doesn't flicker
  // back to the old server value before the refetch lands.
  const [optimistic, setOptimistic] = useState<string | null>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const current = normalizeIncoming(value);

  // Clear the optimistic value once the mutation settles.
  useEffect(() => {
    if (!isPending) setOptimistic(null);
  }, [isPending]);

  useEffect(() => {
    if (editing && inputRef.current) {
      inputRef.current.focus();
      inputRef.current.select();
    }
  }, [editing]);

  const openEditor = () => {
    if (isPending) return;
    setDraft(current);
    setEditing(true);
  };

  const commit = () => {
    const next = onlyDigits(draft);
    // No-op if unchanged.
    if (next === current) {
      setEditing(false);
      return;
    }
    if (!next) {
      if (allowEmpty) {
        setOptimistic("");
        onSave(null);
      } else {
        // Empty not allowed (e.g. base price) → discard.
        setEditing(false);
        return;
      }
    } else {
      setOptimistic(next);
      onSave(next);
    }
    setEditing(false);
  };

  const cancel = () => {
    setDraft(current);
    setEditing(false);
  };

  const sizeText = size === "sm" ? "text-[13px]" : "text-[14px]";
  const alignClass =
    align === "center"
      ? "justify-center text-center"
      : align === "start"
        ? "justify-start text-right"
        : "justify-end text-right";

  /* ------------------------------ edit mode ----------------------------- */
  if (editing) {
    return (
      <div
        className={cn("flex items-center gap-1.5", alignClass, className)}
        dir="ltr"
      >
        <div className="relative flex items-center">
          <input
            ref={inputRef}
            type="text"
            inputMode="numeric"
            aria-label={ariaLabel}
            value={groupLatin(draft)}
            onChange={(e) => setDraft(onlyDigits(e.target.value))}
            onKeyDown={(e) => {
              if (e.key === "Enter") {
                e.preventDefault();
                commit();
              } else if (e.key === "Escape") {
                e.preventDefault();
                cancel();
              }
            }}
            placeholder={allowEmpty ? "پیش‌فرض" : "قیمت"}
            className={cn(
              "w-24 rounded-lg border border-VITROWN_BLUE bg-WHITE px-2 py-2 text-left tabular-nums outline-none",
              "focus:ring-2 focus:ring-VITROWN_BLUE/30 transition-shadow",
              sizeText
            )}
          />
        </div>
        <button
          type="button"
          onClick={commit}
          aria-label="ذخیره قیمت"
          className="flex h-9 w-9 items-center justify-center rounded-lg bg-VITROWN_BLUE text-WHITE transition-colors hover:opacity-90 cursor-pointer"
        >
          <Check className="h-4 w-4" />
        </button>
        <button
          type="button"
          onClick={cancel}
          aria-label="انصراف"
          className="flex h-9 w-9 items-center justify-center rounded-lg bg-WHITE3 text-BLACK2 transition-colors hover:bg-GRAY3 cursor-pointer"
        >
          <X className="h-4 w-4" />
        </button>
      </div>
    );
  }

  /* ---------------------------- display mode ---------------------------- */
  const shown = isPending && optimistic !== null ? optimistic : current;
  const hasValue = shown !== "";

  return (
    <button
      type="button"
      onClick={openEditor}
      disabled={isPending}
      aria-label={ariaLabel}
      // Looks like an editable field (subtle border + grey fill) with an
      // always-visible pencil, so it reads as tappable on touch devices where
      // there is no hover to reveal the affordance.
      className={cn(
        "group inline-flex items-center gap-1.5 rounded-lg border border-GRAY3 bg-WHITE3 px-2.5 py-1.5 min-h-[36px]",
        "transition-colors hover:border-VITROWN_BLUE hover:bg-VITROWN_BLUE/5 active:bg-VITROWN_BLUE/10",
        "cursor-pointer disabled:cursor-default disabled:opacity-70",
        alignClass,
        className
      )}
    >
      {isPending ? (
        <Loader2 className="h-3.5 w-3.5 shrink-0 animate-spin text-VITROWN_BLUE" />
      ) : (
        <Pencil className="h-3.5 w-3.5 shrink-0 text-VITROWN_BLUE/70 transition-colors group-hover:text-VITROWN_BLUE" />
      )}
      {hasValue ? (
        <span className={cn("font-semibold tabular-nums", sizeText)}>
          {toFaDisplay(shown)}
          <span className="mr-1 text-GRAY font-normal">{suffix}</span>
        </span>
      ) : (
        <span className={cn("text-GRAY", sizeText)}>
          {placeholder ?? "افزودن قیمت"}
        </span>
      )}
    </button>
  );
}

export default InlinePriceEditor;
