import { prisma } from './db.js';
import { OSU_TOPUPS, formatFiat } from './shopCatalog.js';

export const OSU_SECTION_KEY = 'shop.osuTopupsEnabled';

function serializePack(row) {
  if (!row) return null;
  return {
    id: row.id,
    name: row.name,
    osu: row.osu,
    priceCents: row.priceCents,
    currency: row.currency || 'eur',
    badge: row.badge || null,
    blurb: row.blurb || '',
    perOsuLabel: row.perOsuLabel || '',
    enabled: Boolean(row.enabled),
    sortOrder: row.sortOrder ?? 0,
    displayPrice: formatFiat(row.priceCents, row.currency),
    updatedAt: row.updatedAt || null,
  };
}

/** Seed missing packs from code defaults (does not overwrite existing rows). */
export async function ensureShopOsuPacks() {
  const existing = await prisma.shopOsuPack.findMany({ select: { id: true } });
  const have = new Set(existing.map((r) => r.id));

  let order = 0;
  for (const pack of OSU_TOPUPS) {
    if (have.has(pack.id)) continue;
    await prisma.shopOsuPack.create({
      data: {
        id: pack.id,
        name: pack.name,
        osu: pack.osu,
        priceCents: pack.priceCents,
        currency: pack.currency || 'eur',
        badge: pack.badge || '',
        blurb: pack.blurb || '',
        perOsuLabel: pack.perOsuLabel || '',
        enabled: true,
        sortOrder: order,
      },
    });
    order += 1;
  }

  const setting = await prisma.appSetting.findUnique({ where: { key: OSU_SECTION_KEY } });
  if (!setting) {
    await prisma.appSetting.create({
      data: { key: OSU_SECTION_KEY, value: '1' },
    });
  }
}

export async function isOsuTopupsSectionEnabled() {
  const setting = await prisma.appSetting.findUnique({ where: { key: OSU_SECTION_KEY } });
  if (!setting) return true;
  return setting.value !== '0' && setting.value !== 'false';
}

export async function setOsuTopupsSectionEnabled(enabled) {
  await prisma.appSetting.upsert({
    where: { key: OSU_SECTION_KEY },
    create: { key: OSU_SECTION_KEY, value: enabled ? '1' : '0' },
    update: { value: enabled ? '1' : '0' },
  });
  return isOsuTopupsSectionEnabled();
}

export async function listShopOsuPacksAdmin() {
  await ensureShopOsuPacks();
  const rows = await prisma.shopOsuPack.findMany({ orderBy: [{ sortOrder: 'asc' }, { id: 'asc' }] });
  const sectionEnabled = await isOsuTopupsSectionEnabled();
  return {
    sectionEnabled,
    packs: rows.map(serializePack),
  };
}

/** Public catalog: only when section on + pack enabled. */
export async function listEnabledShopOsuPacks() {
  await ensureShopOsuPacks();
  if (!(await isOsuTopupsSectionEnabled())) return [];
  const rows = await prisma.shopOsuPack.findMany({
    where: { enabled: true },
    orderBy: [{ sortOrder: 'asc' }, { id: 'asc' }],
  });
  return rows.map(serializePack);
}

/** For checkout — must be enabled and section on. */
export async function getPurchasableOsuPack(packId) {
  await ensureShopOsuPacks();
  if (!(await isOsuTopupsSectionEnabled())) return null;
  const row = await prisma.shopOsuPack.findUnique({ where: { id: String(packId || '') } });
  if (!row || !row.enabled) return null;
  return serializePack(row);
}

export async function updateShopOsuPack(id, body) {
  const existing = await prisma.shopOsuPack.findUnique({ where: { id: String(id) } });
  if (!existing) {
    throw Object.assign(new Error('Pack not found'), { status: 404 });
  }

  const data = {};
  if (body.name !== undefined) {
    const name = String(body.name || '').trim();
    if (!name) throw Object.assign(new Error('Name is required'), { status: 400 });
    data.name = name;
  }
  if (body.osu !== undefined) {
    const osu = Number(body.osu);
    if (!Number.isInteger(osu) || osu < 1) {
      throw Object.assign(new Error('osu must be a positive integer'), { status: 400 });
    }
    data.osu = osu;
  }
  if (body.priceCents !== undefined) {
    const priceCents = Number(body.priceCents);
    if (!Number.isInteger(priceCents) || priceCents < 0) {
      throw Object.assign(new Error('priceCents must be a non-negative integer'), { status: 400 });
    }
    data.priceCents = priceCents;
  }
  if (body.currency !== undefined) {
    data.currency = String(body.currency || 'eur').toLowerCase().slice(0, 8) || 'eur';
  }
  if (body.badge !== undefined) {
    data.badge = body.badge == null ? '' : String(body.badge).trim();
  }
  if (body.blurb !== undefined) {
    data.blurb = String(body.blurb || '').trim();
  }
  if (body.perOsuLabel !== undefined) {
    data.perOsuLabel = String(body.perOsuLabel || '').trim();
  }
  if (body.enabled !== undefined) {
    data.enabled = Boolean(body.enabled);
  }
  if (body.sortOrder !== undefined) {
    const sortOrder = Number(body.sortOrder);
    if (!Number.isInteger(sortOrder)) {
      throw Object.assign(new Error('sortOrder must be an integer'), { status: 400 });
    }
    data.sortOrder = sortOrder;
  }

  if (!Object.keys(data).length) {
    throw Object.assign(new Error('No changes provided'), { status: 400 });
  }

  const updated = await prisma.shopOsuPack.update({
    where: { id: existing.id },
    data,
  });
  return serializePack(updated);
}
