"use client";

import { useEffect, useMemo, useState } from "react";
import type { QuestionField } from "@/lib/schema-adapter";
import { useI18n } from "@/translations/provider";
import { useQuestionAnswers } from "./question-answer-storage";
import QuestionTitle from "./question-title";
import { Input } from "@/components/ui/input";
import { isKnownCountry } from "@/data/countries";
import { resolveDefaultCurrency } from "@/data/currencies";
import { getStoredUserGeoRegion } from "@/lib/geo-region";
import { CurrencySheet } from "./currency-sheet";

type QuestionNumberProps = {
  question: QuestionField;
  disabled?: boolean;
  derivedFromQuestion?: QuestionField;
  derivedFromQuestionIndex?: number;
};

const PERSIAN_DIGITS = ["۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"];
const ARABIC_DIGITS = ["٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"];

export function normalizeNumberString(val: string): string {
  if (!val) return "";
  let result = "";
  for (let i = 0; i < val.length; i++) {
    const char = val[i];
    const pIdx = PERSIAN_DIGITS.indexOf(char);
    if (pIdx !== -1) {
      result += String(pIdx);
      continue;
    }
    const aIdx = ARABIC_DIGITS.indexOf(char);
    if (aIdx !== -1) {
      result += String(aIdx);
      continue;
    }
    if (char === "٫") {
      result += ".";
      continue;
    }
    result += char;
  }
  return result;
}

const NUMBER_INPUT_PATTERN = /^-?\d*\.?\d*$/;

export default function QuestionNumber({
  question,
  disabled,
  derivedFromQuestion,
  derivedFromQuestionIndex,
}: QuestionNumberProps) {
  const { dictionary: t, locale } = useI18n();
  const { getAnswerValue, setAnswerValue } = useQuestionAnswers();
  const value = getAnswerValue(question);

  const derivedValue =
    derivedFromQuestion && derivedFromQuestionIndex !== undefined
      ? getAnswerValue(derivedFromQuestion)
      : null;

  useEffect(() => {
    if (derivedFromQuestion && typeof derivedValue === "string") {
      const age = calculateAge(derivedValue);
      if (age !== String(value)) {
        setAnswerValue(question, age);
      }
    }
  }, [
    derivedFromQuestion,
    derivedValue,
    question,
    setAnswerValue,
    value,
  ]);

  useEffect(() => {
    if (typeof value === "string" && value.length > 0) {
      const normalized = normalizeNumberString(value);
      console.log(
        `[NUM_LOG] useEffect normalize: id=${question.id}, value="${value}", normalized="${normalized}"`,
      );
      if (!NUMBER_INPUT_PATTERN.test(normalized)) {
        console.log(
          `[NUM_LOG] useEffect clearing invalid value: id=${question.id}, value="${value}"`,
        );
        setAnswerValue(question, null);
      } else if (normalized !== value) {
        const parsed = parseFloat(normalized);
        console.log(
          `[NUM_LOG] useEffect updating normalized: id=${question.id}, parsed=${parsed}`,
        );
        setAnswerValue(
          question,
          Number.isNaN(parsed) ? normalized : parsed,
        );
      }
    }
  }, [question, setAnswerValue, value]);

  const [min, max] = question.extras.range;

  const numValue =
    typeof value === "number"
      ? value
      : typeof value === "string"
        ? parseFloat(normalizeNumberString(value))
        : NaN;
  const isOutOfRange = useMemo(() => {
    if (Number.isNaN(numValue)) return false;
    if (min !== 0 && numValue < min) return true;
    if (max !== 0 && numValue > max) return true;
    return false;
  }, [numValue, min, max]);

  const rawInputValue = value == null ? "" : String(value);
  const normalizedRaw = normalizeNumberString(rawInputValue);
  const inputValue = NUMBER_INPUT_PATTERN.test(normalizedRaw)
    ? normalizedRaw
    : "";

  console.log(
    `[NUM_LOG] Render: id=${question.id}, value=${JSON.stringify(value)}, inputValue="${inputValue}", isOutOfRange=${isOutOfRange}`,
  );

  const isMonthlyIncome = question.ui_config?.currency_enabled === true;
  const currencyStorageKey =
    question.ui_config?.currency_storage_key || "marriage:income:currency";

  const countryName = useMemo(() => getCountryFromStorage(), []);

  const [currencyCode, setCurrencyCode] = useState(() => {
    if (typeof window !== "undefined") {
      const stored = window.localStorage.getItem(currencyStorageKey);
      if (stored) return stored;
    }
    const geo = getStoredUserGeoRegion();
    return resolveDefaultCurrency({
      countryCode: geo?.countryCode,
      countryName: countryName || geo?.country,
      fallbackLocale: locale,
    });
  });

  const [isCurrencySheetOpen, setIsCurrencySheetOpen] = useState(false);

  useEffect(() => {
    if (typeof window !== "undefined") {
      const stored = window.localStorage.getItem(currencyStorageKey);
      if (stored) {
        setCurrencyCode(stored);
        return;
      }
    }
    const geo = getStoredUserGeoRegion();
    const derived = resolveDefaultCurrency({
      countryCode: geo?.countryCode,
      countryName: countryName || geo?.country,
      fallbackLocale: locale,
    });
    setCurrencyCode(derived);
  }, [countryName, currencyStorageKey, locale]);

  const placeholderCurrency = useMemo(() => {
    if (currencyCode === "TOMAN") {
      return locale === "fa" || locale === "fa-ir" ? "تومان" : "TOMAN";
    }
    return currencyCode;
  }, [currencyCode, locale]);

  const dynamicPlaceholder = useMemo(() => {
    if (!isMonthlyIncome) {
      return question.extras.placeHolder;
    }
    return locale === "fa" || locale === "fa-ir"
      ? `مثال: ۴۰۰۰ ${placeholderCurrency}`
      : `e.g. 4000 ${placeholderCurrency}`;
  }, [
    isMonthlyIncome,
    question.extras.placeHolder,
    placeholderCurrency,
    locale,
  ]);

  const [localTextValue, setLocalTextValue] = useState(() =>
    formatNumberWithCommas(inputValue),
  );

  useEffect(() => {
    const formatted = formatNumberWithCommas(
      value == null ? "" : String(value),
    );
    const cleanLocal = localTextValue.replace(/,/g, "");
    const cleanFormatted = formatted.replace(/,/g, "");
    if (cleanFormatted !== cleanLocal) {
      setLocalTextValue(formatted);
    }
  }, [value, localTextValue]);

  if (isMonthlyIncome) {
    return (
      <div
        className={[
          "flex w-full flex-col gap-2 transition-opacity duration-200",
          disabled ? "pointer-events-none opacity-30" : "",
        ].join(" ")}
      >
        <QuestionTitle question={question} />
        <div className="flex gap-3 w-full relative">
          <div className="flex-1 min-w-0">
            <Input
              type="text"
              inputMode="decimal"
              required={question.required && !disabled}
              disabled={disabled || Boolean(derivedFromQuestion)}
              placeholder={dynamicPlaceholder}
              value={localTextValue}
              onChange={(event) => {
                const nextValue = event.target.value;
                const normalized = normalizeNumberString(nextValue);
                const cleanValue = normalized.replace(/,/g, "");

                if (
                  cleanValue !== "" &&
                  cleanValue !== "-" &&
                  !NUMBER_INPUT_PATTERN.test(cleanValue)
                ) {
                  return;
                }

                const formatted = formatNumberWithCommas(cleanValue);
                const finalFormatted = normalized.endsWith(".")
                  ? `${formatted}.`
                  : formatted;
                setLocalTextValue(finalFormatted);

                if (cleanValue === "" || cleanValue === "-") {
                  setAnswerValue(question, null);
                } else {
                  const parsed = parseFloat(cleanValue);
                  setAnswerValue(
                    question,
                    Number.isNaN(parsed) ? cleanValue : parsed,
                  );
                }
              }}
              className={[
                "h-[54px] w-full rounded-[16px] border px-4.5 text-[15px] font-medium text-[#181818] outline-none transition-all placeholder:text-[#98A2B3] focus:border-[#6F6F6F] focus:ring-1 focus:ring-[#6F6F6F] disabled:bg-[#F5F2F1] disabled:text-[#7C7472]",
                isOutOfRange
                  ? "border-[#F2465F] ring-1 ring-[#F2465F]"
                  : "border-[#D0D5DD] hover:border-[#98A2B3] bg-white",
              ].join(" ")}
            />
          </div>
          <div className="w-[110px] shrink-0 relative">
            <button
              type="button"
              disabled={disabled}
              onClick={() => setIsCurrencySheetOpen(true)}
              className={[
                "flex h-[54px] w-full items-center justify-between rounded-[16px] border bg-white px-3.5 text-start transition-all cursor-pointer outline-none",
                isCurrencySheetOpen
                  ? "border-[#6F6F6F] ring-1 ring-[#6F6F6F]"
                  : "border-[#D0D5DD] hover:border-[#98A2B3]",
              ].join(" ")}
            >
              <span className="text-[15px] font-medium text-[#181818] truncate">
                {placeholderCurrency}
              </span>
              <svg
                width="12"
                height="8"
                viewBox="0 0 16 10"
                fill="none"
                role="img"
                aria-label="Dropdown chevron"
                className={[
                  "shrink-0 transition-transform duration-200 text-[#344054] ml-1",
                  isCurrencySheetOpen ? "rotate-180" : "",
                ].join(" ")}
              >
                <path
                  d="M14.75 1.25L7.75 8.25L0.75 1.25"
                  stroke="currentColor"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                />
              </svg>
            </button>
          </div>
        </div>

        <CurrencySheet
          isOpen={isCurrencySheetOpen}
          onClose={() => setIsCurrencySheetOpen(false)}
          selectedCurrency={currencyCode}
          onSelectCurrency={(code) => {
            setCurrencyCode(code);
            if (typeof window !== "undefined") {
              window.localStorage.setItem(currencyStorageKey, code);
            }
          }}
        />

        {isOutOfRange ? (
          <span className="block text-[10px] font-semibold text-[#F2465F]">
            {t[
              "The value entered seems incorrect. Please provide a realistic value."
            ] || `Please enter a value between ${min} and ${max}`}
          </span>
        ) : null}
      </div>
    );
  }

  return (
    <div
      className={[
        "flex w-full flex-col gap-2 transition-opacity duration-200",
        disabled ? "pointer-events-none opacity-30" : "",
      ].join(" ")}
    >
      <QuestionTitle question={question} />
      <Input
        type="text"
        inputMode="numeric"
        required={question.required && !disabled}
        disabled={disabled || Boolean(derivedFromQuestion)}
        placeholder={question.extras.placeHolder}
        value={inputValue}
        onChange={(event) => {
          const raw = event.target.value;
          const normalized = normalizeNumberString(raw);
          const cleaned = normalized.replace(/[^0-9.-]/g, "");

          console.log(
            `[NUM_LOG] onChange: id=${question.id}, raw="${raw}", normalized="${normalized}", cleaned="${cleaned}"`,
          );

          if (cleaned === "" || cleaned === "-") {
            console.log(`[NUM_LOG] onChange clearing value (empty)`);
            setAnswerValue(question, null);
            return;
          }

          if (!NUMBER_INPUT_PATTERN.test(cleaned)) {
            console.log(`[NUM_LOG] onChange rejected pattern: "${cleaned}"`);
            return;
          }

          const parsed = parseFloat(cleaned);
          console.log(
            `[NUM_LOG] onChange calling setAnswerValue with:`,
            Number.isNaN(parsed) ? cleaned : parsed,
          );
          setAnswerValue(
            question,
            Number.isNaN(parsed) ? cleaned : parsed,
          );
        }}
        className={[
          "h-[54px] w-full rounded-[16px] border px-4.5 text-[15px] font-medium text-[#181818] outline-none transition-all placeholder:text-[#98A2B3] focus:border-[#6F6F6F] focus:ring-1 focus:ring-[#6F6F6F] disabled:bg-[#F5F2F1] disabled:text-[#7C7472]",
          isOutOfRange
            ? "border-[#F2465F] ring-1 ring-[#F2465F]"
            : "border-[#D0D5DD] hover:border-[#98A2B3] bg-white",
        ].join(" ")}
      />
      {isOutOfRange ? (
        <span className="block text-[10px] font-semibold text-[#F2465F]">
          {t[
            "The value entered seems incorrect. Please provide a realistic value."
          ] || `Please enter a value between ${min} and ${max}`}
        </span>
      ) : null}
    </div>
  );
}

function calculateAge(dateOfBirth: string) {
  const birthDate = new Date(dateOfBirth);

  if (Number.isNaN(birthDate.getTime())) {
    return "";
  }

  const today = new Date();
  let age = today.getFullYear() - birthDate.getFullYear();
  const monthDifference = today.getMonth() - birthDate.getMonth();

  if (
    monthDifference < 0 ||
    (monthDifference === 0 && today.getDate() < birthDate.getDate())
  ) {
    age -= 1;
  }

  return String(Math.max(age, 0));
}

function getCountryFromStorage(): string {
  if (typeof window === "undefined") return "";
  try {
    const rawValue = window.localStorage.getItem(
      "marriage:sections:contact_residence_family_communication:answers",
    );
    if (!rawValue) return "";
    const storedValue = JSON.parse(rawValue);
    const field = storedValue.fields?.find(
      (f: { type?: string; key?: string; value?: unknown }) =>
        f.type === "birthplace" ||
        f.key?.includes("current_residence") ||
        f.key?.includes("mhl_skwnt_fly"),
    );
    const value = field?.value;
    if (typeof value === "object" && value !== null) {
      const obj = value as { country?: string; city?: string };
      if (typeof obj.country === "string" && obj.country.trim()) {
        return obj.country.trim();
      }
    }
    if (typeof value === "string") {
      const parts = value.split(",").map((p) => p.trim());
      if (parts.length >= 2) {
        if (isKnownCountry(parts[1])) return parts[1];
        if (isKnownCountry(parts[0])) return parts[0];
        return parts[1];
      }
      return parts[0] || "";
    }
  } catch {
    // Ignore
  }
  return "";
}

function formatNumberWithCommas(val: string): string {
  if (!val) return "";
  const parts = val.split(".");
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  return parts.join(".");
}
