"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { COUNTRIES_EN, COUNTRIES_FA } from "@/data/countries";
import { LANGUAGE_EN_TO_FA, LANGUAGES_EN, LANGUAGES_FA } from "@/data/languages";
import type { QuestionField } from "@/lib/schema-adapter";
import { useI18n } from "@/translations/provider";
import { Button } from "./button";
import { ExplanationUiFont } from "./explanation-ui-font";
import { useQuestionAnswers } from "./question-answer-storage";
import QuestionTitle from "./question-title";
import { registerCompactQuestionSheet } from "./question-viewport-coordinator";
import { useSheetScrollLock } from "./use-sheet-scroll-lock";

const EXIT_ANIMATION_MS = 300;
const EMPTY_ARRAY: string[] = [];

export type QuestionSheetProps = {
  question: QuestionField;
  disabled?: boolean;
};

export function QuestionSheet({ question, disabled }: QuestionSheetProps) {
  const { dictionary: t, locale } = useI18n();
  const { getAnswerValue, setAnswerValue } = useQuestionAnswers();
  const rawValue = getAnswerValue(question);

  const isMulti =
    Array.isArray(rawValue) ||
    question.type === "checkbox" ||
    (question.extras?.range && question.extras.range[1] > 1);

  const selectedList = useMemo(() => {
    if (Array.isArray(rawValue)) return rawValue;
    if (typeof rawValue === "string" && rawValue) return [rawValue];
    return EMPTY_ARRAY;
  }, [rawValue]);
  const singleValue = typeof rawValue === "string" ? rawValue : "";

  const [isOpen, setIsOpen] = useState(false);
  const [isClosing, setIsClosing] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");
  const listRef = useRef<HTMLDivElement>(null);
  const sheetRef = useRef<HTMLElement>(null);
  const [localSelectedList, setLocalSelectedList] = useState<string[]>(selectedList);
  const localSelectedListRef = useRef<string[]>(selectedList);

  useEffect(() => {
    localSelectedListRef.current = localSelectedList;
  }, [localSelectedList]);

  useEffect(() => {
    if (!isOpen) {
      setLocalSelectedList(selectedList);
      localSelectedListRef.current = selectedList;
    }
  }, [isOpen, selectedList]);

  const closeSheet = useCallback(() => {
    setIsClosing(true);
    if (isMulti) {
      const currentList = localSelectedListRef.current;
      setAnswerValue(
        question,
        currentList.length > 0 ? currentList : null,
      );
    }
    window.setTimeout(() => {
      setIsOpen(false);
      setIsClosing(false);
      setSearchQuery("");
    }, EXIT_ANIMATION_MS);
  }, [isMulti, question, setAnswerValue]);

  const openSheet = useCallback(() => {
    if (disabled) return;
    setLocalSelectedList(selectedList);
    localSelectedListRef.current = selectedList;
    setIsOpen(true);
    setIsClosing(false);
  }, [disabled, selectedList]);

  useSheetScrollLock(isOpen && !isClosing, { onBack: closeSheet });

  // Handle escape key
  useEffect(() => {
    if (!isOpen) return;

    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === "Escape") {
        closeSheet();
      }
    };

    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [isOpen, closeSheet]);

  const isLanguageQuestion =
    question.id?.toLowerCase().includes("language") ||
    question.id?.toLowerCase().includes("mother_tongue") ||
    question.id?.toLowerCase().includes("other_languages") ||
    question.title?.toLowerCase().includes("language") ||
    question.title?.toLowerCase().includes("tongue") ||
    question.title?.includes("زبان") ||
    question.ui_config?.dataset === "languages";

  const isCountryQuestion =
    question.id?.toLowerCase().includes("nationality") ||
    question.id?.toLowerCase().includes("citizenship") ||
    question.id?.toLowerCase().includes("country") ||
    question.id?.toLowerCase().includes("birthplace") ||
    question.id?.toLowerCase().includes("residence") ||
    question.title?.toLowerCase().includes("nationality") ||
    question.title?.toLowerCase().includes("citizenship") ||
    question.title?.toLowerCase().includes("country") ||
    question.title?.includes("ملیت") ||
    question.title?.includes("تابعیت") ||
    question.title?.includes("کشور") ||
    question.title?.includes("سکونت") ||
    question.ui_config?.dataset === "countries" ||
    question.ui_config?.dataset === "nationalities";

  const options = useMemo(() => {
    const rawOptions = question.options || [];

    if (isLanguageQuestion) {
      const existingByLabel = new Map(
        rawOptions.map((opt) => [opt.label.toLowerCase().trim(), opt]),
      );
      const existingByVal = new Map(
        rawOptions.map((opt) => [String(opt.value).toLowerCase().trim(), opt]),
      );
      const existingById = new Map(
        rawOptions.map((opt) => [opt.id.toLowerCase().trim(), opt]),
      );

      const mergedOptions: typeof rawOptions = [];
      const seenIds = new Set<string>();

      LANGUAGES_EN.forEach((enLang, idx) => {
        const localizedLabel =
          (locale === "fa" || locale === "fa-ir"
            ? (LANGUAGE_EN_TO_FA[enLang] || LANGUAGES_FA[idx])
            : (t as any)[enLang]) || enLang;
        const cleanSlug = enLang
          .toLowerCase()
          .replace(/[^a-z0-9]+/g, "_")
          .replace(/^_+|_+$/g, "");
        const generatedId = `${question.id}.${cleanSlug}`;

        const existing =
          existingByLabel.get(enLang.toLowerCase()) ||
          existingByLabel.get(localizedLabel.toLowerCase()) ||
          existingByVal.get(cleanSlug) ||
          existingById.get(generatedId.toLowerCase());

        const finalId = existing?.id || generatedId;
        if (seenIds.has(finalId)) return;
        seenIds.add(finalId);

        const isPersian = locale === "fa" || locale === "fa-ir";
        const displayLabel = isPersian
          ? (LANGUAGE_EN_TO_FA[enLang] || localizedLabel)
          : enLang;

        mergedOptions.push({
          id: finalId,
          value: existing?.value ?? cleanSlug,
          label: displayLabel,
          order: existing?.order ?? idx,
        });
      });

      rawOptions.forEach((opt) => {
        if (!seenIds.has(opt.id)) {
          seenIds.add(opt.id);
          mergedOptions.push(opt);
        }
      });

      return mergedOptions;
    }

    if (isCountryQuestion) {
      const existingByLabel = new Map(
        rawOptions.map((opt) => [opt.label.toLowerCase().trim(), opt]),
      );
      const existingByVal = new Map(
        rawOptions.map((opt) => [String(opt.value).toLowerCase().trim(), opt]),
      );
      const existingById = new Map(
        rawOptions.map((opt) => [opt.id.toLowerCase().trim(), opt]),
      );

      const mergedOptions: typeof rawOptions = [];
      const seenIds = new Set<string>();

      COUNTRIES_EN.forEach((enCountry, idx) => {
        const localizedLabel =
          (locale === "fa" || locale === "fa-ir"
            ? COUNTRIES_FA[idx]
            : (t as any)[enCountry]) || enCountry;
        const cleanSlug = enCountry
          .toLowerCase()
          .replace(/[^a-z0-9]+/g, "_")
          .replace(/^_+|_+$/g, "");
        const generatedId = `${question.id}.${cleanSlug}`;

        const existing =
          existingByLabel.get(enCountry.toLowerCase()) ||
          existingByLabel.get(localizedLabel.toLowerCase()) ||
          existingByVal.get(cleanSlug) ||
          existingById.get(generatedId.toLowerCase());

        const finalId = existing?.id || generatedId;
        if (seenIds.has(finalId)) return;
        seenIds.add(finalId);

        const isPersian = locale === "fa" || locale === "fa-ir";
        const displayLabel = isPersian
          ? (COUNTRIES_FA[idx] || localizedLabel)
          : enCountry;

        mergedOptions.push({
          id: finalId,
          value: existing?.value ?? cleanSlug,
          label: displayLabel,
          order: existing?.order ?? idx,
        });
      });

      rawOptions.forEach((opt) => {
        if (!seenIds.has(opt.id)) {
          seenIds.add(opt.id);
          mergedOptions.push(opt);
        }
      });

      return mergedOptions;
    }

    return rawOptions;
  }, [question, isLanguageQuestion, isCountryQuestion, locale, t]);

  const COMPACT_OPTIONS_MAX = 6;

  const isCompact = options.length <= COMPACT_OPTIONS_MAX;
  const showSearch =
    !question.extras?.noSearch && options.length > COMPACT_OPTIONS_MAX;

  useEffect(() => {
    if (!isOpen || isClosing || !isCompact) return;

    let unregister: (() => void) | undefined;
    const frame = window.requestAnimationFrame(() => {
      if (sheetRef.current) {
        unregister = registerCompactQuestionSheet(sheetRef.current);
      }
    });

    return () => {
      window.cancelAnimationFrame(frame);
      unregister?.();
    };
  }, [isCompact, isClosing, isOpen]);

  const filteredOptions = options.filter((option) =>
    option.label.toLowerCase().includes(searchQuery.toLowerCase()),
  );

  const getCleanLabel = (optId: string) => {
    const normalized = String(optId || "").toLowerCase().trim();
    const opt = options.find(
      (o) =>
        o.id === optId ||
        o.id.toLowerCase() === normalized ||
        String(o.value).toLowerCase() === normalized ||
        o.id.endsWith(`.${normalized}`),
    );
    if (!opt) return optId;
    return opt.label.split(" - ")[0];
  };

  const isRtl = locale === "fa" || locale === "ar" || locale === "ur";
  const defaultPlaceholder = isRtl ? "انتخاب کنید" : "Select";

  const displayLabel = isMulti
    ? selectedList.length > 0
      ? selectedList.map(getCleanLabel).join(", ")
      : question.extras?.placeHolder || defaultPlaceholder
    : singleValue
      ? getCleanLabel(singleValue)
      : question.extras?.placeHolder || defaultPlaceholder;

  const hasSelectedValue = isMulti
    ? selectedList.length > 0
    : Boolean(singleValue);

  const toggleMultiOption = (optionId: string) => {
    setLocalSelectedList((prev) => {
      let nextValue: string[];
      if (prev.includes(optionId)) {
        nextValue = prev.filter((v) => v !== optionId);
      } else {
        nextValue = [...prev, optionId];
      }
      localSelectedListRef.current = nextValue;
      return nextValue;
    });
  };

  const handleConfirmMulti = () => {
    const currentList = localSelectedListRef.current;
    setAnswerValue(
      question,
      currentList.length > 0 ? currentList : null,
    );
    closeSheet();
  };

  const handleSelectSingle = (optionId: string) => {
    setAnswerValue(question, optionId);
    closeSheet();
  };

  const searchPlaceholder =
    locale === "fa"
      ? "جستجو..."
      : locale === "ar"
        ? "بحث..."
        : locale === "tr"
          ? "Ara..."
          : "Search...";

  const noResultsText =
    locale === "fa"
      ? "موردی یافت نشد"
      : locale === "ar"
        ? "لم يتم العثور على نتائج"
        : "No options found";

  const confirmText = t.Confirm || (isRtl ? "تایید" : "Confirm");

  return (
    <div
      className={[
        "relative flex w-full flex-col gap-2.5 transition-opacity duration-200",
        disabled ? "pointer-events-none opacity-30" : "",
      ].join(" ")}
    >
      <QuestionTitle question={question} />

      {/* Select Trigger Button (Input style) */}
      <button
        type="button"
        disabled={disabled}
        onClick={openSheet}
        className={[
          "flex h-[54px] w-full items-center justify-between rounded-[16px] border bg-white px-4.5 text-start transition-all cursor-pointer outline-none",
          isOpen
            ? "border-[#6F6F6F] ring-1 ring-[#6F6F6F]"
            : "border-[#D0D5DD] hover:border-[#98A2B3]",
        ].join(" ")}
      >
        <span
          className={[
            "text-[15px] font-medium truncate",
            hasSelectedValue ? "text-[#181818]" : "text-[#667085]",
          ].join(" ")}
        >
          {displayLabel}
        </span>
        <svg
          aria-hidden="true"
          width="16"
          height="10"
          viewBox="0 0 16 10"
          fill="none"
          className={[
            "shrink-0 transition-transform duration-200",
            isOpen ? "rotate-180" : "",
          ].join(" ")}
        >
          <path
            d="M14.75 1.25L7.75 8.25L0.75 1.25"
            stroke="#344054"
            strokeWidth="1.75"
            strokeLinecap="round"
            strokeLinejoin="round"
          />
        </svg>
      </button>

      {/* The active field moves up while the options sheet enters from below. */}
      {isOpen &&
        createPortal(
          <div
            className="fixed inset-0 z-50 flex items-end justify-center bg-transparent"
            role="dialog"
            aria-label={question.title}
            onKeyDown={(e) => {
              if (e.key === "Escape") closeSheet();
            }}
            onClick={(event) => {
              if (event.target === event.currentTarget) closeSheet();
            }}
          >
            <section
              ref={sheetRef}
              className={[
                "flex w-full flex-col overflow-hidden rounded-t-[22px] bg-white pb-[env(safe-area-inset-bottom)] shadow-[0_-10px_32px_rgba(0,0,0,0.12)] transition-transform duration-[300ms] ease-out sm:max-w-[375px] animate-in slide-in-from-bottom",
                isCompact && !showSearch
                  ? "h-auto max-h-[82svh]"
                  : "h-[82svh] min-h-[82svh] max-h-[82svh]",
                isClosing ? "translate-y-full" : "translate-y-0",
              ].join(" ")}
            >
              <div className="flex items-center justify-between px-5 pt-2 pb-3 border-b border-[#F2F4F7]">
                <h3 className="text-[17px] font-bold text-[#181818] truncate pr-2">
                  {question.title}
                </h3>
                <button
                  type="button"
                  onClick={closeSheet}
                  className="flex size-8 shrink-0 items-center justify-center rounded-full text-[#667085] hover:bg-[#F2F4F7] hover:text-[#181818] transition-colors cursor-pointer"
                  aria-label="Close"
                >
                  <svg
                    aria-hidden="true"
                    width="18"
                    height="18"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    strokeWidth="2.2"
                    strokeLinecap="round"
                    strokeLinejoin="round"
                  >
                    <line x1="18" y1="6" x2="6" y2="18" />
                    <line x1="6" y1="6" x2="18" y2="18" />
                  </svg>
                </button>
              </div>

              {/* Search Bar */}
              {showSearch && (
                <div className="px-5 pt-3.5 pb-2">
                  <div className="flex h-[46px] w-full items-center gap-2.5 rounded-[14px] bg-[#F2F4F7] px-3.5 transition-colors focus-within:bg-[#EAECF0]">
                    <svg
                      aria-hidden="true"
                      width="18"
                      height="18"
                      viewBox="0 0 18 18"
                      fill="none"
                      className="shrink-0 text-[#667085]"
                    >
                      <path
                        d="M8.25 14.25C11.5637 14.25 14.25 11.5637 14.25 8.25C14.25 4.93629 11.5637 2.25 8.25 2.25C4.93629 2.25 2.25 4.93629 2.25 8.25C2.25 11.5637 4.93629 14.25 8.25 14.25Z"
                        stroke="#667085"
                        strokeWidth="1.75"
                        strokeLinecap="round"
                        strokeLinejoin="round"
                      />
                      <path
                        d="M15.75 15.75L12.5 12.5"
                        stroke="#667085"
                        strokeWidth="1.75"
                        strokeLinecap="round"
                        strokeLinejoin="round"
                      />
                    </svg>
                    <input
                      type="text"
                      name="sheet_search_field"
                      autoComplete="off"
                      autoCorrect="off"
                      autoCapitalize="none"
                      spellCheck="false"
                      aria-autocomplete="none"
                      data-lpignore="true"
                      data-1p-ignore="true"
                      data-bwignore="true"
                      data-form-type="other"
                      value={searchQuery}
                      onChange={(e) => setSearchQuery(e.target.value)}
                      placeholder={searchPlaceholder}
                      className="flex-1 bg-transparent text-[14px] font-medium text-[#181818] outline-none placeholder:text-[#98A2B3]"
                    />
                    {searchQuery ? (
                      <button
                        type="button"
                        onClick={() => setSearchQuery("")}
                        className="text-[#667085] hover:text-[#181818] text-xs font-semibold p-1 cursor-pointer"
                      >
                        ✕
                      </button>
                    ) : null}
                  </div>
                </div>
              )}

              {/* Options List */}
              <div
                ref={listRef}
                onTouchStart={(event) => event.stopPropagation()}
                onTouchMove={(event) => event.stopPropagation()}
                onTouchEnd={(event) => event.stopPropagation()}
                className="flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto overscroll-contain px-5 py-3"
              >
                {filteredOptions.length > 0 ? (
                  filteredOptions.map((option) => {
                    const isSelected = isMulti
                      ? localSelectedList.includes(option.id)
                      : singleValue === option.id;

                    return (
                      <button
                        key={option.id}
                        type="button"
                        onClick={() => {
                          if (isMulti) {
                            toggleMultiOption(option.id);
                          } else {
                            handleSelectSingle(option.id);
                          }
                        }}
                        className={[
                          "flex min-h-12 w-full items-start gap-3 rounded-lg border px-3 py-3 text-start transition-colors cursor-pointer",
                          isSelected
                            ? "bg-[#FFF4F5] border-[#F0445B]/30 text-[#181818]"
                            : "bg-white hover:bg-[#F2F4F7] border-[#EAECF0] text-[#181818]",
                        ].join(" ")}
                      >
                        {/* Indicator Icon */}
                        {isMulti ? (
                          <div
                            className={[
                              "size-[22px] shrink-0 rounded-[6px] transition-all duration-150 mt-0.5 flex items-center justify-center",
                              isSelected
                                ? "bg-[#F0445B] text-white shadow-xs"
                                : "border-[2px] border-[#98A2B3] bg-white",
                            ].join(" ")}
                          >
                            {isSelected && (
                              <svg
                                aria-hidden="true"
                                width="12"
                                height="10"
                                viewBox="0 0 12 10"
                                fill="none"
                              >
                                <path
                                  d="M1.5 5L4.5 8L10.5 2"
                                  stroke="currentColor"
                                  strokeWidth="2"
                                  strokeLinecap="round"
                                  strokeLinejoin="round"
                                />
                              </svg>
                            )}
                          </div>
                        ) : (
                          <div
                            className={[
                              "size-[22px] shrink-0 rounded-full transition-all duration-150 mt-0.5 flex items-center justify-center",
                              isSelected
                                ? "border-[6px] border-[#F0445B] bg-white"
                                : "border-[2px] border-[#98A2B3] bg-white",
                            ].join(" ")}
                          />
                        )}

                        <span className="text-[15px] leading-snug flex-1">
                          {option.label.includes(" - ") ? (
                            (() => {
                              const parts = option.label.split(" - ");
                              const title = parts[0];
                              const description = parts.slice(1).join(" - ");
                              return (
                                <span className="flex flex-col gap-1 text-start">
                                  <span className="font-bold text-[#181818]">
                                    {title}
                                  </span>
                                  <ExplanationUiFont>
                                    {description}
                                  </ExplanationUiFont>
                                </span>
                              );
                            })()
                          ) : (
                            <span
                              className={
                                isSelected
                                  ? "font-bold text-[#181818]"
                                  : "font-semibold text-[#344054]"
                              }
                            >
                              {option.label}
                            </span>
                          )}
                        </span>
                      </button>
                    );
                  })
                ) : (
                  <div className="py-8 text-center text-[14px] text-[#667085]">
                    {noResultsText}
                  </div>
                )}
              </div>

              {/* Bottom Actions for Multi-Select */}
              {isMulti && (
                <div className="border-t border-[#F2F4F7] bg-white p-4 pt-3 pb-[calc(14px+env(safe-area-inset-bottom))]">
                  <Button
                    type="button"
                    variant="default"
                    onClick={handleConfirmMulti}
                    className="w-full h-[50px] rounded-[14px] text-[15px] font-bold shadow-[0_8px_20px_rgba(240,68,91,0.25)] cursor-pointer"
                  >
                    {localSelectedList.length > 0
                      ? `${confirmText} (${localSelectedList.length})`
                      : confirmText}
                  </Button>
                </div>
              )}
            </section>
          </div>,
          document.body,
        )}
    </div>
  );
}

export default QuestionSheet;
