"use client";

import { fetchOnce } from "@/lib/fetch-once";

import { createContext, useContext, useEffect, useState } from "react";

/** Currencies an admin can pick from. */
export const CURRENCIES = [
  { code: "USD", symbol: "$", label: "US Dollar", suffix: false },
  { code: "GBP", symbol: "£", label: "British Pound", suffix: false },
  { code: "EUR", symbol: "€", label: "Euro", suffix: false },
  { code: "TRY", symbol: "₺", label: "Turkish Lira", suffix: false },
  { code: "JPY", symbol: "¥", label: "Japanese Yen", suffix: false },
];

type Ctx = { symbol: string; suffix: boolean; format: (n: number) => string };

const CurrencyContext = createContext<Ctx>({
  symbol: "$",
  suffix: false,
  format: (n) => `$${n.toLocaleString()}`,
});

export function useCurrency() {
  return useContext(CurrencyContext);
}

/**
 * A price in the reader's own money, alongside the real one.
 *
 * Everything is priced and charged in the site's currency. This is a
 * courtesy so someone in Turkey can tell what $10 means, not a second
 * price — which is why it reads "about" and is never used for a charge.
 */
export function useLocalPrice() {
  const [rate, setRate] = useState<{ to: string; rate: number } | null>(null);

  useEffect(() => {
    // The reader's own currency, from their browser.
    const guess = new Intl.NumberFormat(navigator.language, {
      style: "currency",
      currency: "USD",
    }).resolvedOptions();
    void guess;

    fetch("/api/locale")
      .then((r) => (r.ok ? r.json() : null))
      .then((d) => {
        const want = d?.localCurrency;
        if (!want) return null;
        return fetch(`/api/rates?to=${encodeURIComponent(want)}`)
          .then((r) => (r.ok ? r.json() : null))
          .then((x) => {
            if (x?.converted) setRate({ to: x.to, rate: x.rate });
          });
      })
      .catch(() => {});
  }, []);

  /** Returns something like "≈ ₺340" — or nothing, when there's no rate. */
  return (amount: number) => {
    if (!rate) return null;
    return (
      "≈ " +
      new Intl.NumberFormat(undefined, {
        style: "currency",
        currency: rate.to,
        maximumFractionDigits: 0,
      }).format(amount * rate.rate)
    );
  };
}

/** Reads the admin's chosen currency and formats prices consistently. */
export function CurrencyProvider({ children }: { children: React.ReactNode }) {
  const [symbol, setSymbol] = useState("$");
  const [suffix, setSuffix] = useState(false);

  useEffect(() => {
    // Read fresh, not from the shared cache: this changes rarely but when
    // it does, showing the old one is confusing.
    fetch("/api/settings")
      .then((r) => (r.ok ? r.json() : null))
      .then((d) => {
        if (!d?.currency) return;
        // Older databases may still hold the retired coin — treat as dollars.
        const match = CURRENCIES.find(
          (c) => c.code === d.currency || c.symbol === d.currency
        );
        setSymbol(match?.symbol ?? "$");
        setSuffix(match?.suffix ?? false);
      })
      .catch(() => {});
  }, []);

  const format = (n: number) => {
    const value = n.toLocaleString(undefined, { maximumFractionDigits: 2 });
    return suffix ? `${value} ${symbol}` : `${symbol}${value}`;
  };

  return (
    <CurrencyContext.Provider value={{ symbol, suffix, format }}>
      {children}
    </CurrencyContext.Provider>
  );
}
