import { toCentsBigInt } from './cents.js';

/**
 * Shop catalogs.
 * - OSU_TOPUPS: real-money → osu (premium currency)
 * - CREDIT_PACKS: osu → in-game credits (scaled to player balance)
 *
 * Fiat prices are in minor units (EUR cents). Swap provider later via PAYMENTS_PROVIDER.
 */

/** @typedef {{ id: string, name: string, osu: number, priceCents: number, currency: string, badge?: string|null, blurb: string, perOsuLabel: string }} OsuTopup */

/** @type {OsuTopup[]} */
export const OSU_TOPUPS = [
  {
    id: 'osu_50',
    name: 'Spark',
    osu: 50,
    priceCents: 499,
    currency: 'eur',
    badge: null,
    blurb: 'A light top-up to open a few cases',
    perOsuLabel: '€0.10 / osu',
  },
  {
    id: 'osu_150',
    name: 'Pulse',
    osu: 150,
    priceCents: 1299,
    currency: 'eur',
    badge: 'Popular',
    blurb: '150 osu · better rate than Spark',
    perOsuLabel: '€0.087 / osu',
  },
  {
    id: 'osu_400',
    name: 'Orbit',
    osu: 400,
    priceCents: 2999,
    currency: 'eur',
    badge: null,
    blurb: 'Solid stack for grinding cases & vault',
    perOsuLabel: '€0.075 / osu',
  },
  {
    id: 'osu_1000',
    name: 'Nova',
    osu: 1000,
    priceCents: 6499,
    currency: 'eur',
    badge: 'Best value',
    blurb: '1000 osu · lowest price per osu',
    perOsuLabel: '€0.065 / osu',
  },
  {
    id: 'osu_2500',
    name: 'Eclipse',
    osu: 2500,
    priceCents: 14999,
    currency: 'eur',
    badge: null,
    blurb: 'Whale pack for long prestige runs',
    perOsuLabel: '€0.060 / osu',
  },
];

/**
 * Credit packs priced in osu. Rewards scale with the buyer's credit balance:
 * credits = max(minCredits, balance * balancePct / 100).
 * Larger packs grant a higher % of balance per osu.
 */
export const CREDIT_PACKS = [
  {
    id: 'cr_spark',
    name: 'Credit Spark',
    osuCost: 10,
    balancePct: 20,
    minCredits: 5000,
    tag: null,
  },
  {
    id: 'cr_boost',
    name: 'Credit Boost',
    osuCost: 25,
    balancePct: 55,
    minCredits: 15000,
    tag: null,
  },
  {
    id: 'cr_surge',
    name: 'Credit Surge',
    osuCost: 60,
    balancePct: 140,
    minCredits: 40000,
    tag: 'Fair',
  },
  {
    id: 'cr_nova',
    name: 'Credit Nova',
    osuCost: 150,
    balancePct: 400,
    minCredits: 110000,
    tag: 'Popular',
  },
  {
    id: 'cr_orbit',
    name: 'Credit Orbit',
    osuCost: 400,
    balancePct: 1200,
    minCredits: 320000,
    tag: null,
  },
  {
    id: 'cr_eclipse',
    name: 'Credit Eclipse',
    osuCost: 1000,
    balancePct: 3500,
    minCredits: 900000,
    tag: 'Best rate',
  },
];

/** @deprecated use CREDIT_PACKS */
export const SHOP_PACKAGES = CREDIT_PACKS;

export function getOsuTopup(id) {
  return OSU_TOPUPS.find((p) => p.id === String(id || ''));
}

export function getCreditPack(id) {
  return CREDIT_PACKS.find((p) => p.id === String(id || ''));
}

/** Resolve pack payout for a player's current balance (cents → string cents). */
export function scaleCreditPack(pack, balanceCents) {
  const bal = toCentsBigInt(balanceCents);
  const pct = Math.max(0, Math.floor(Number(pack.balancePct) || 0));
  const fromPct = pct > 0 ? (bal * BigInt(pct)) / 100n : 0n;
  const min = BigInt(Math.max(0, Math.floor(Number(pack.minCredits) || 0)));
  const credits = fromPct > min ? fromPct : min;
  return {
    id: pack.id,
    name: pack.name,
    osuCost: pack.osuCost,
    baseOsuCost: pack.osuCost,
    balancePct: pct,
    minCredits: min.toString(),
    credits: credits.toString(),
    tag: pack.tag ?? null,
    scaled: fromPct > min,
  };
}

export function scaleCreditPacks(balanceCents) {
  return CREDIT_PACKS.map((pack) => scaleCreditPack(pack, balanceCents));
}

export function formatFiat(priceCents, currency = 'eur') {
  const n = Number(priceCents) || 0;
  const major = n / 100;
  try {
    return new Intl.NumberFormat('fr-FR', {
      style: 'currency',
      currency: String(currency || 'eur').toUpperCase(),
    }).format(major);
  } catch {
    return `€${major.toFixed(2)}`;
  }
}

export function paymentsProvider() {
  const raw = String(process.env.PAYMENTS_PROVIDER || 'mock').toLowerCase();
  if (raw === 'stripe' && process.env.STRIPE_SECRET_KEY) return 'stripe';
  return 'mock';
}
