// ARS Mobile Services — data layer + persistence
// All pricing is editable in Admin mode and persists to localStorage.

const PRICING_KEY = "ars_pricing_v3";
const BOOKINGS_KEY = "ars_bookings_v3";
const APPTS_KEY = "ars_appointments_v3";
const BLOCKED_KEY = "ars_blocked_v3";
const ADMIN_PIN = "1990"; // demo PIN — owner can change in code

// Bookable time windows — one appointment per window per day
const WINDOWS = [
  { id: "am", label: "Morning", time: "8–11 AM" },
  { id: "mid", label: "Midday", time: "11 AM–2 PM" },
  { id: "pm", label: "Afternoon", time: "2–6 PM" },
  { id: "eve", label: "Evening", time: "After 6 PM" },
];

let __id = 0;
const uid = (p) => `${p}_${Date.now().toString(36)}_${(__id++).toString(36)}`;

const DEFAULT_DATA = {
  labor: [
    { id: "lab_nextday", name: "Next-Day Homebase", desc: "Drop at homebase, ready next day", price: 15, unit: "/ racquet" },
    { id: "lab_sameday", name: "Same-Day Homebase", desc: "Drop at homebase, same-day turnaround", price: 18, unit: "/ racquet" },
    { id: "lab_mobile1", name: "Mobile Express — 1 Racquet", desc: "We come to your location", price: 25, unit: "flat" },
    { id: "lab_mobile2", name: "Mobile Express — 2–7 Racquets", desc: "We come to your location", price: 20, unit: "/ racquet" },
    { id: "lab_mobile8", name: "Mobile Express — 8+ Racquets", desc: "10% volume discount", price: 18, unit: "/ racquet" },
  ],
  fees: [
    { id: "fee_pickup", name: "Pick-Up / Delivery", desc: "Each direction", price: 3, unit: "ea. way" },
    { id: "fee_emergency", name: "Emergency (after 6pm)", desc: "Added on top of labor", price: 5, unit: "/ racquet" },
    { id: "fee_stencil", name: "Stenciling", desc: "Red & black available on request", price: 3, unit: "/ racquet" },
  ],
  strings: [
    {
      id: "cat_poly", category: "Polyester", blurb: "Control & spin",
      items: [
        { id: uid("s"), name: "Solinco Hyper-G", detail: "Green · multi-gauge", price: 13 },
        { id: uid("s"), name: "Yonex PolyTour Pro", detail: "Yellow · 17g", price: 20 },
        { id: uid("s"), name: "Babolat RPM Blast", detail: "Black · 16/17/18g", price: 19 },
        { id: uid("s"), name: "Solinco Tour Bite Soft", detail: "Grey · 16L", price: 13 },
      ],
    },
    {
      id: "cat_multi", category: "Multifilament", blurb: "Comfort & power",
      items: [
        { id: uid("s"), name: "Wilson NXT", detail: "Natural · 16/17g", price: 20 },
        { id: uid("s"), name: "Wilson NXT Power", detail: "Natural · 16/17/18g", price: 20 },
        { id: uid("s"), name: "Volkl Power Fiber II", detail: "Natural · 17g", price: 13 },
        { id: uid("s"), name: "Tecnifibre Triax", detail: "Natural · 16g", price: 22 },
      ],
    },
    {
      id: "cat_syn", category: "Synthetic Gut", blurb: "All-around value",
      items: [
        { id: uid("s"), name: "Wilson Synthetic Gut Power", detail: "White/Black/Pink · 16/17g", price: 5 },
        { id: uid("s"), name: "Prince Synthetic Gut w/ Duraflex", detail: "Multicolor · 16g", price: 9 },
        { id: uid("s"), name: "Head Synthetic Gut", detail: "White/Black/Yellow · 16/17g", price: 5 },
      ],
    },
  ],
  otherLabor: [
    { id: uid("o"), name: "Replacement Grip Install", desc: "", price: 2 },
    { id: uid("o"), name: "Overgrip Install", desc: "With grip purchase", price: 0 },
    { id: uid("o"), name: "Grip Build-Up Sleeve", desc: "Per size · max 2 advised", price: 7 },
    { id: uid("o"), name: "Grommet Install", desc: "", price: 3 },
    { id: uid("o"), name: "Butt-Cap Replacement", desc: "", price: 10 },
  ],
  grips: [
    {
      id: "cat_repl", category: "Replacement Grips", blurb: "Base / bottom grips",
      items: [
        { id: uid("g"), name: "Head Hydrosorb Comfort", detail: "Black", price: 9 },
        { id: uid("g"), name: "Volkl Cushtac", detail: "Black", price: 8 },
        { id: uid("g"), name: "Wilson Contour Cushion Pro", detail: "Black", price: 10 },
        { id: uid("g"), name: "Head Leather Grip", detail: "Tan leather", price: 18 },
      ],
    },
    {
      id: "cat_over", category: "Overgrips", blurb: "Top wraps",
      items: [
        { id: uid("g"), name: "Wilson Pro", detail: "White/Pink/Yellow/Black", price: 2 },
        { id: uid("g"), name: "Tournagrip XL", detail: "Blue", price: 2 },
        { id: uid("g"), name: "Yonex Super Grap", detail: "Black/Red/Purple", price: 2 },
      ],
    },
  ],
};

function deepClone(o) { return JSON.parse(JSON.stringify(o)); }

function loadPricing() {
  try {
    const raw = localStorage.getItem(PRICING_KEY);
    if (raw) return JSON.parse(raw);
  } catch (e) {}
  return deepClone(DEFAULT_DATA);
}
function savePricing(data) {
  try { localStorage.setItem(PRICING_KEY, JSON.stringify(data)); } catch (e) {}
}
function resetPricing() {
  try { localStorage.removeItem(PRICING_KEY); } catch (e) {}
  return deepClone(DEFAULT_DATA);
}

function loadBookings() {
  try {
    const raw = localStorage.getItem(BOOKINGS_KEY);
    if (raw) return JSON.parse(raw);
  } catch (e) {}
  return [];
}
function saveBookings(list) {
  try { localStorage.setItem(BOOKINGS_KEY, JSON.stringify(list)); } catch (e) {}
}

// Manual appointments added by the owner (separate from customer bookings)
function loadAppointments() {
  try { const raw = localStorage.getItem(APPTS_KEY); if (raw) return JSON.parse(raw); } catch (e) {}
  return [];
}
function saveAppointments(list) {
  try { localStorage.setItem(APPTS_KEY, JSON.stringify(list)); } catch (e) {}
}
// Days the owner has blocked off (array of ISO yyyy-mm-dd strings)
function loadBlocked() {
  try { const raw = localStorage.getItem(BLOCKED_KEY); if (raw) return JSON.parse(raw); } catch (e) {}
  return [];
}
function saveBlocked(list) {
  try { localStorage.setItem(BLOCKED_KEY, JSON.stringify(list)); } catch (e) {}
}

// ---- date helpers ----
function isoOf(date) {
  const y = date.getFullYear(), m = String(date.getMonth() + 1).padStart(2, "0"), d = String(date.getDate()).padStart(2, "0");
  return `${y}-${m}-${d}`;
}
function windowLabel(id) { const w = WINDOWS.find((x) => x.id === id); return w ? w.label : id; }

// Combine customer bookings + owner appointments into one list for a given ISO date
function apptsForDate(bookings, appts, iso) {
  const out = [];
  (bookings || []).forEach((b) => {
    if (b.dateISO === iso) out.push({ id: b.id, window: b.window || "am", name: b.name, type: "booking",
      detail: `${b.count} racquet${b.count > 1 ? "s" : ""} · ${b.service}`, note: b.notes, total: b.total });
  });
  (appts || []).forEach((a) => {
    if (a.dateISO === iso) out.push({ id: a.id, window: a.window, name: a.title, type: "manual", detail: a.detail || "Personal appointment", note: a.note });
  });
  return out;
}
// Which windows are taken on a date; returns Set of window ids
function takenWindows(bookings, appts, iso) {
  const s = new Set();
  apptsForDate(bookings, appts, iso).forEach((a) => s.add(a.window));
  return s;
}

window.ARS = window.ARS || {};
Object.assign(window.ARS, {
  DEFAULT_DATA, deepClone, uid,
  loadPricing, savePricing, resetPricing,
  loadBookings, saveBookings,
  loadAppointments, saveAppointments,
  loadBlocked, saveBlocked,
  WINDOWS, isoOf, windowLabel, apptsForDate, takenWindows,
  ADMIN_PIN,
});
