/* Sparkle Classic Studio — shared data + helpers (no UI). Exposed on window. */

/* ---- roles & permissions ---- */
const ROLES = {
  admin: { label: 'Admin', who: 'Ada (owner)' },
  crp: { label: 'Support / CRP', who: 'Remy' },
};
const PERMS = {
  // true = allowed for that role
  viewOrders:    { admin: true, crp: true },
  downloadPhoto: { admin: true, crp: true },
  uploadSprite:  { admin: true, crp: true },
  publish:       { admin: true, crp: true },
  emailCustomer: { admin: true, crp: true },
  requestRefund: { admin: true, crp: true },
  confirmRefund: { admin: true, crp: false },
  manageTeam:    { admin: true, crp: false },
  editRetention: { admin: true, crp: false },
};
// crp (support) can be granted normally-admin-only perms via admin-set overrides
// (loaded from /api/orders). Defaults to none until set.
let CRP_OVERRIDES = {};
const setCrpOverrides = (o) => { CRP_OVERRIDES = (o && typeof o === 'object') ? o : {}; };
const can = (role, perm) => !!(PERMS[perm] && (PERMS[perm][role] || (role === 'crp' && CRP_OVERRIDES[perm])));

/* ---- statuses ---- */
const ASTATUS = {
  received:  { tone: 'neutral', label: 'Received' },
  art:       { tone: 'neutral', label: 'Art in progress' },
  published: { tone: 'neutral', label: 'Published' },
  ready:     { tone: 'success', label: 'Ready' },
  refunded:  { tone: 'danger',  label: 'Refunded' },
  action:    { tone: 'warning', label: 'Action needed' },
};
const PIPELINE = ['received', 'art', 'published', 'ready'];

/* ---- time-left (24h window) ---- */
function fmtTimeLeft(min) {
  if (min <= 0) {
    const h = Math.round(-min / 60);
    return { text: h >= 1 ? `Overdue ${h}h` : 'Overdue', level: 'urgent', icon: 'alert' };
  }
  const h = Math.floor(min / 60), m = min % 60;
  const text = h >= 1 ? `${h}h ${m}m left` : `${m}m left`;
  const level = min <= 120 ? 'urgent' : min <= 360 ? 'warn' : 'ok';
  return { text, level, icon: 'clock' };
}
const LEVEL_COLOR = { ok: 'var(--plum-accent)', warn: 'var(--warning)', urgent: 'var(--danger)' };

/* ---- sample orders ---- */
const STUDIO_ORDERS = [
  {
    id: 'SPK-4825', petName: 'Buttercup', slug: 'buttercup', customer: 'Priya N.', email: 'priya@email.com',
    kind: 'Golden retriever', world: 'Meadow', artStyle: 'Classic 8-bit', toy: false, amount: '$29',
    paidAt: '40m ago', dueInMin: 80, status: 'received',
    note: 'Buttercup is a big softie who loves tennis balls and belly rubs.',
    photo: { state: 'present', ageHours: 1 }, sprite: { uploaded: false }, game: { published: false },
  },
  {
    id: 'SPK-4824', petName: 'Mochi', slug: 'mochi', customer: 'Lee K.', email: 'lee@email.com',
    kind: 'Cat', world: 'Sky', artStyle: '16-bit deluxe', toy: true, amount: '$34',
    paidAt: '5h ago', dueInMin: 95, status: 'action', actionReason: 'Photo too dark to trace',
    note: 'Mochi naps in the laundry basket. Big personality!',
    photo: { state: 'present', ageHours: 5 }, sprite: { uploaded: false }, game: { published: false },
  },
  {
    id: 'SPK-4823', petName: 'Pippin', slug: 'pippin', customer: 'Dana R.', email: 'dana@email.com',
    kind: 'Corgi', world: 'Meadow', artStyle: 'Classic 8-bit', toy: false, amount: '$29',
    paidAt: '8h ago', dueInMin: 280, status: 'art',
    note: '', photo: { state: 'present', ageHours: 8 }, sprite: { uploaded: false }, game: { published: false },
  },
  {
    id: 'SPK-4822', petName: 'Olive', slug: 'olive', customer: 'Wren P.', email: 'wren@email.com',
    kind: 'Parrot', world: 'Castle', artStyle: 'Game Boy green', toy: false, amount: '$29',
    paidAt: '14h ago', dueInMin: 420, status: 'published',
    note: 'Olive says hello and steals snacks.', photo: { state: 'present', ageHours: 14 },
    sprite: { uploaded: true }, game: { published: true, link: 'sparkleclassic.com/olive' },
  },
  {
    id: 'SPK-4821', petName: 'Biscuit', slug: 'biscuit', customer: 'Sam T.', email: 'sam@email.com',
    kind: 'Beagle', world: 'Desert', artStyle: 'Classic 8-bit', toy: true, amount: '$34',
    paidAt: '22h ago', dueInMin: 30, status: 'art',
    note: 'Biscuit has one floppy ear and a white sock on his left paw.',
    photo: { state: 'present', ageHours: 22 }, sprite: { uploaded: false }, game: { published: false },
  },
  {
    id: 'SPK-4820', petName: 'Juno', slug: 'juno', customer: 'Ira B.', email: 'ira@email.com',
    kind: 'Shiba', world: 'Sky', artStyle: '16-bit deluxe', toy: false, amount: '$29',
    paidAt: '1d ago', dueInMin: 999, status: 'ready',
    note: '', photo: { state: 'deleted', deletedDate: 'Jun 12' }, sprite: { uploaded: true },
    game: { published: true, link: 'sparkleclassic.com/juno' },
  },
  {
    id: 'SPK-4819', petName: 'Tofu', slug: 'tofu', customer: 'Max V.', email: 'max@email.com',
    kind: 'Rabbit', world: 'Meadow', artStyle: 'Classic 8-bit', toy: false, amount: '$29',
    paidAt: '2d ago', dueInMin: 999, status: 'refunded',
    note: '', photo: { state: 'deleted', deletedDate: 'Jun 11' }, sprite: { uploaded: false }, game: { published: false },
  },
];

/* slugs already in use (for the rename / collision check) */
const TAKEN_SLUGS = ['buttercup', 'mochi', 'pippin', 'olive', 'biscuit', 'juno', 'tofu', 'luna', 'max', 'bella', 'rocky'];

/* team accounts (A3) */
const TEAM = [
  { name: 'Ada Sparkle', email: 'ada@sparkleclassic.com', role: 'admin', you: true },
  { name: 'Remy Cruz', email: 'remy@sparkleclassic.com', role: 'crp' },
  { name: 'Jordan Lee', email: 'jordan@sparkleclassic.com', role: 'crp' },
];

const RETENTION_RULE = 'A pet photo is kept up to 48 hours after the game is delivered (so a sprite can be re-made), then auto-deleted. Abandoned carts are cleared after 7 days.';

/* sprite-sheet checklist for A2 */
const SPRITE_STEPS = [
  'Download the customer\u2019s photo.',
  'Combine it with the bowie_sprite template in the image tool.',
  'Export a 3\u00d73 sprite sheet \u2014 rows: idle, walk, jump.',
  'Upload the sheet below.',
];

/* ---- real API wiring ---- */
async function apiFetch(path, opts) {
  const res = await fetch(path, Object.assign({ credentials: 'same-origin', headers: { 'Content-Type': 'application/json' } }, opts || {}));
  let data = null; try { data = await res.json(); } catch (e) { /* non-JSON */ }
  if (!res.ok) { const err = new Error((data && data.error) || ('HTTP ' + res.status)); err.status = res.status; throw err; }
  return data;
}

function fmtAgo(ts) {
  if (!ts) return '';
  const iso = String(ts).replace(' ', 'T');
  const t = Date.parse(iso.endsWith('Z') ? iso : iso + 'Z');
  if (isNaN(t)) return String(ts);
  const s = Math.max(0, (Date.now() - t) / 1000);
  if (s < 90) return 'just now';
  const m = Math.round(s / 60); if (m < 60) return m + 'm ago';
  const h = Math.round(m / 60); if (h < 48) return h + 'h ago';
  return Math.round(h / 24) + 'd ago';
}

const API_STATUS = { paid: 'received', in_progress: 'published', ready: 'ready', refunded: 'refunded', needs_info: 'action' };

/* Map a backend order row (list or detail) into the Studio's shape. */
function studioOrderFromApi(o) {
  const paid = o.paid_at || o.created_at;
  const iso = paid ? String(paid).replace(' ', 'T') : '';
  const t = paid ? Date.parse(iso.endsWith('Z') ? iso : iso + 'Z') : NaN;
  const settled = o.status === 'ready' || o.status === 'refunded';
  const dueInMin = (!settled && !isNaN(t)) ? Math.round((24 * 60) - (Date.now() - t) / 60000) : 999;
  return {
    id: o.id,
    petName: o.pet_name,
    slug: o.pet_slug,
    customer: o.customer_name || (o.email ? o.email.split('@')[0] : '—'),
    email: o.email,
    kind: o.pet_type ? (o.pet_type === 'dog' ? 'Dog' : 'Cat') : 'Pet',
    spriteScale: o.sprite_scale || 1,
    toy: !!o.addon_toy,
    amount: '$' + Math.round((o.amount_cents || 0) / 100),
    paidAt: fmtAgo(paid),
    dueInMin,
    status: (o.status === 'in_progress' && !o.published) ? 'art' : (API_STATUS[o.status] || 'received'),
    note: o.notes || '',
    photo: { state: o.has_photo ? 'present' : 'deleted', deletedDate: o.photo_deleted_at ? fmtAgo(o.photo_deleted_at) : '' },
    hasToyPhoto: !!o.has_toy_photo,
    sprite: { uploaded: !!o.has_sprite },
    game: { published: !!o.published, link: o.game_url || '' },
  };
}

Object.assign(window, {
  ROLES, PERMS, can, setCrpOverrides, ASTATUS, PIPELINE, fmtTimeLeft, LEVEL_COLOR,
  TAKEN_SLUGS, TEAM, RETENTION_RULE, SPRITE_STEPS,
  apiFetch, fmtAgo, studioOrderFromApi,
});
