/**
 * 与后端约定：金额存最小货币单位（如 NPR 2 位小数 → 分）；展示时除以 10^displayDecimals。
 * 展示分隔符与 {@link CurrencyFormatter} / 后台「货币格式」设置一致。
 */

import { getCurrencyDisplayFormat } from "@/lib/currency-display-settings";
import { usePlayerSessionStore } from "@/stores/player-session-store";

const DEFAULT_DECIMAL_PLACES = 2;

export function getCurrencyDecimalPlaces(currencyCode: string): number {
  const code = currencyCode.trim().toUpperCase();
  const row = usePlayerSessionStore
    .getState()
    .currencies.find((item) => item.code === code);

  const decimals = row?.decimal_places;
  if (typeof decimals === "number" && Number.isFinite(decimals) && decimals >= 0) {
    return decimals;
  }

  return DEFAULT_DECIMAL_PLACES;
}

function formatIntegerWithThousands(value: number, thousandsSep: string): string {
  const digits = String(Math.trunc(value));
  if (!thousandsSep) return digits;
  return digits.replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSep);
}

function formatMinorWithDisplaySettings(
  minorUnits: number,
  format = getCurrencyDisplayFormat(),
): string {
  const { displayDecimals, decimalSeparator, thousandsSeparator } = format;
  const divisor = Math.max(1, 10 ** displayDecimals);
  const negative = minorUnits < 0;
  const abs = Math.abs(minorUnits);

  const integerPart = Math.floor(abs / divisor);
  const fractionRaw = abs % divisor;
  const fractionPadded = String(fractionRaw).padStart(displayDecimals, "0");
  const integerPartFormatted = formatIntegerWithThousands(
    integerPart,
    thousandsSeparator,
  );

  if (displayDecimals === 0) {
    return `${negative ? "-" : ""}${integerPartFormatted}`;
  }

  return `${negative ? "-" : ""}${integerPartFormatted}${decimalSeparator}${fractionPadded}`;
}

export function formatMinorAsCurrency(
  minor: number | string,
  currencyCode: string,
  decimalPlaces?: number,
): string {
  const n = typeof minor === "string" ? Number(minor) : minor;
  if (!Number.isFinite(n)) return `${currencyCode} —`;

  const format = getCurrencyDisplayFormat();
  const resolvedDisplayDecimals =
    typeof decimalPlaces === "number" &&
    Number.isFinite(decimalPlaces) &&
    decimalPlaces >= 0
      ? Math.min(12, Math.trunc(decimalPlaces))
      : format.displayDecimals;

  const amount = formatMinorWithDisplaySettings(n, {
    ...format,
    displayDecimals: resolvedDisplayDecimals,
  });

  return `${currencyCode} ${amount}`;
}

/**
 * 用户输入如 `1000` 或 `1,000.50` → 最小货币单位整数（按币种实际 decimal_places）。
 */
export function parseDecimalInputToMinor(
  raw: string,
  decimalPlacesOrCurrencyCode?: number | string,
): number | null {
  const decimalPlaces =
    typeof decimalPlacesOrCurrencyCode === "string"
      ? getCurrencyDecimalPlaces(decimalPlacesOrCurrencyCode)
      : typeof decimalPlacesOrCurrencyCode === "number" &&
          Number.isFinite(decimalPlacesOrCurrencyCode) &&
          decimalPlacesOrCurrencyCode >= 0
        ? decimalPlacesOrCurrencyCode
        : decimalPlacesOrCurrencyCode;
  const resolvedDecimalPlaces = decimalPlaces ?? DEFAULT_DECIMAL_PLACES;

  const format = getCurrencyDisplayFormat();
  let cleaned = raw.trim();
  if (format.thousandsSeparator) {
    cleaned = cleaned.split(format.thousandsSeparator).join("");
  }
  if (format.decimalSeparator && format.decimalSeparator !== ".") {
    cleaned = cleaned.replaceAll(format.decimalSeparator, ".");
  }
  cleaned = cleaned.replace(/,/g, "");

  if (cleaned === "") return null;
  const n = Number(cleaned);
  if (!Number.isFinite(n) || n < 0) return null;
  const factor = 10 ** resolvedDecimalPlaces;
  const minor = Math.round(n * factor);
  if (!Number.isSafeInteger(minor)) return null;
  return minor;
}
