/* Shared store — used by both customer site and admin dashboard.
   Persists in localStorage. Seeded with demo data on first load. */

const STORE_KEYS = {
  requests:    'prestige.requests',
  session:     'prestige.adminSession',
  users:       'prestige.users',
  seedVersion: 'prestige.seedVersion',
};

const SEED_ADMIN = { username: 'admin', password: 'prestige2026' };
// Bump this whenever buildSeed() changes so the demo data regenerates once.
const SEED_VERSION = '2026-06-catalog-ampm';
const SESSION_TTL_HOURS = 12;

const STATUS = {
  PENDING:   'pending',
  CONFIRMED: 'confirmed',
  COMPLETED: 'completed',
  CANCELLED: 'cancelled',
};

const STATUS_LABEL = {
  pending:   'Pending review',
  confirmed: 'Confirmed',
  completed: 'Completed',
  cancelled: 'Cancelled',
};

/* --- Date helpers ----------------------------------------- */
const ymd = (d) => {
  const dt = (d instanceof Date) ? d : new Date(d);
  const y = dt.getFullYear();
  const m = String(dt.getMonth()+1).padStart(2,'0');
  const day = String(dt.getDate()).padStart(2,'0');
  return `${y}-${m}-${day}`;
};
const fromYmd = (s) => {
  const [y, m, d] = s.split('-').map(Number);
  return new Date(y, m-1, d);
};
const today = () => { const d = new Date(); d.setHours(0,0,0,0); return d; };
const addDays = (d, n) => { const r = new Date(d); r.setDate(r.getDate()+n); return r; };
const fmtDate = (d) => (d instanceof Date ? d : fromYmd(d)).toLocaleDateString('en-US',{
  weekday:'short', month:'short', day:'numeric'
});
const fmtDateLong = (d) => (d instanceof Date ? d : fromYmd(d)).toLocaleDateString('en-US',{
  weekday:'long', year:'numeric', month:'long', day:'numeric'
});

/* --- Seed mock data --------------------------------------- */
const VEHICLE_OPTIONS = [
  { id:'sedan',  label:'Sedan' },
  { id:'suv',    label:'SUV' },
  { id:'pickup', label:'Pick-Up' },
  { id:'van',    label:'Van' },
  { id:'comm',   label:'Commercial Van' },
  { id:'truck',  label:'Trucks' },
];
const SERVICE_OPTIONS = [
  { id:'regular',   label:'Regular Wash',        duration:45,  prices:{ sedan:50, suv:80, pickup:80, van:99, comm:159, truck:199 } },
  { id:'detailing', label:'Detailing',           duration:150, prices:{ sedan:299, suv:349, pickup:349, van:349, comm:499, truck:649 } },
  { id:'luxury',    label:'Luxury Wash',         duration:210, flat:699 },
  { id:'headlight', label:'Headlight Polishing', duration:60,  flat:99 },
];
const seedPrice = (svc, vehId) => (svc.flat != null ? svc.flat : (svc.prices?.[vehId] ?? 0));
const SLOT_OPTIONS = [
  '7:00 AM','8:00 AM','9:00 AM','10:00 AM','11:00 AM','12:00 PM','1:00 PM',
  '2:00 PM','3:00 PM','4:00 PM','5:00 PM','6:00 PM','7:00 PM',
];

const buildSeed = () => {
  const t = today();
  const make = (offset, slot, vehId, svcId, status, customer) => {
    const veh = VEHICLE_OPTIONS.find(v => v.id === vehId);
    const svc = SERVICE_OPTIONS.find(s => s.id === svcId);
    const subtotal = seedPrice(svc, vehId);
    return {
      id: `REQ-${Date.now().toString(36).slice(-4)}-${Math.random().toString(36).slice(2,6).toUpperCase()}`,
      createdAt: addDays(t, offset - 2).toISOString(),
      status,
      paid: status !== 'cancelled',
      customer,
      address: { line: customer.addr || '1245 Sunset Blvd', city: customer.city || 'Beverly Hills', zip: customer.zip || '90210', notes: '' },
      vehicle: veh,
      service: svc,
      date: ymd(addDays(t, offset)),
      slot,
      payment: 'card',
      promo: null,
      pricing: { subtotal, total: Math.round(subtotal * 1.04) },
      emailSent: status === 'confirmed' || status === 'completed',
      emailSentAt: status === 'confirmed' || status === 'completed' ? addDays(t, offset - 1).toISOString() : null,
      notes: '',
    };
  };

  return [
    make(-3, '11:00 AM', 'suv',    'luxury',    'completed', { name:'Marisa Velasquez', email:'marisa.v@example.com', phone:'(310) 555-0142', addr:'9100 Wilshire Blvd', city:'Beverly Hills', zip:'90212' }),
    make(-1, '2:00 PM',  'sedan',  'detailing', 'completed', { name:'Daniel Kim',       email:'dkim@example.com',     phone:'(424) 555-0188', addr:'500 Ocean Ave',      city:'Santa Monica',  zip:'90402' }),
    make(0,  '9:00 AM',  'suv',    'detailing', 'confirmed', { name:'Sofia Ramos',      email:'sofia.r@example.com',  phone:'(310) 555-0177', addr:'250 Newport Center Dr', city:'Newport Beach', zip:'92660' }),
    make(0,  '1:00 PM',  'sedan',  'luxury',    'pending',   { name:'James Lambert',    email:'jlambert@example.com', phone:'(310) 555-0103', addr:'27900 Pacific Coast Hwy', city:'Malibu', zip:'90265' }),
    make(1,  '8:00 AM',  'pickup', 'regular',   'pending',   { name:'Carla Mendoza',    email:'cmendoza@example.com', phone:'(323) 555-0150', addr:'1100 Sunset Plaza Dr', city:'West Hollywood', zip:'90069' }),
    make(1,  '12:00 PM', 'sedan',  'detailing', 'confirmed', { name:'Ethan Park',       email:'epark@example.com',    phone:'(310) 555-0166', addr:'620 Manhattan Ave', city:'Manhattan Beach', zip:'90266' }),
    make(2,  '11:00 AM', 'van',    'detailing', 'pending',   { name:'Priya Shah',       email:'pshah@example.com',    phone:'(310) 555-0124', addr:'1800 Avenue of the Stars', city:'Los Angeles', zip:'90067' }),
    make(3,  '9:00 AM',  'suv',    'detailing', 'confirmed', { name:'Aaron Reyes',      email:'areyes@example.com',   phone:'(424) 555-0192', addr:'200 Pier Ave', city:'Hermosa Beach', zip:'90254' }),
    make(4,  '3:00 PM',  'comm',   'regular',   'pending',   { name:'Logistics Co.',    email:'ops@logisticsco.example.com', phone:'(310) 555-0145', addr:'5000 W Century Blvd', city:'Los Angeles', zip:'90045' }),
    make(7,  '11:00 AM', 'truck',  'luxury',    'pending',   { name:'Maya Brennan',     email:'mb@example.com',       phone:'(310) 555-0118', addr:'1500 Stone Canyon Rd', city:'Bel Air', zip:'90077' }),
  ];
};

/* --- Storage primitives ---------------------------------- */
const readJSON = (key, fallback) => {
  try { const v = localStorage.getItem(key); return v ? JSON.parse(v) : fallback; }
  catch { return fallback; }
};
const writeJSON = (key, value) => {
  try { localStorage.setItem(key, JSON.stringify(value)); } catch {}
};

/* --- Public store API ------------------------------------ */
const Store = {
  STATUS, STATUS_LABEL, SLOT_OPTIONS,

  ensureSeed(){
    const cur = readJSON(STORE_KEYS.requests, null);
    const ver = readJSON(STORE_KEYS.seedVersion, null);
    if (!cur || !Array.isArray(cur) || ver !== SEED_VERSION) {
      writeJSON(STORE_KEYS.requests, buildSeed());
      writeJSON(STORE_KEYS.seedVersion, SEED_VERSION);
    }
  },
  resetSeed(){
    writeJSON(STORE_KEYS.requests, buildSeed());
    writeJSON(STORE_KEYS.seedVersion, SEED_VERSION);
  },

  getRequests(){
    Store.ensureSeed();
    return readJSON(STORE_KEYS.requests, []);
  },
  setRequests(list){
    writeJSON(STORE_KEYS.requests, list);
    window.dispatchEvent(new CustomEvent('prestige:requests-changed'));
  },
  upsert(req){
    const list = Store.getRequests();
    const idx = list.findIndex(r => r.id === req.id);
    if (idx >= 0) list[idx] = req; else list.unshift(req);
    Store.setRequests(list);
  },
  updateStatus(id, status, extra={}){
    const list = Store.getRequests();
    const idx = list.findIndex(r => r.id === id);
    if (idx < 0) return null;
    list[idx] = { ...list[idx], status, ...extra };
    Store.setRequests(list);
    return list[idx];
  },

  /* Slot blocking — takes a Date or YYYY-MM-DD, returns set of taken slot strings */
  takenSlotsForDate(date){
    const key = (typeof date === 'string') ? date : ymd(date);
    const blockingStatuses = new Set([STATUS.PENDING, STATUS.CONFIRMED, STATUS.COMPLETED]);
    const reqs = Store.getRequests();
    return new Set(
      reqs
        .filter(r => r.date === key && r.paid && blockingStatuses.has(r.status))
        .map(r => r.slot)
    );
  },

  /* --- Users / accounts --------------------------------- */
  ensureUsers(){
    const cur = readJSON(STORE_KEYS.users, null);
    if (!cur || !Array.isArray(cur) || cur.length === 0) {
      writeJSON(STORE_KEYS.users, [{
        id: 'usr-seed-admin',
        username: SEED_ADMIN.username,
        password: SEED_ADMIN.password,
        role: 'admin',
        createdAt: new Date().toISOString(),
        createdBy: null,
        lastLogin: null,
      }]);
    }
  },
  getUsers(){ Store.ensureUsers(); return readJSON(STORE_KEYS.users, []); },
  setUsers(list){
    writeJSON(STORE_KEYS.users, list);
    window.dispatchEvent(new CustomEvent('prestige:users-changed'));
  },
  validateUserPayload({ username, password, confirm }, { existing = [] } = {}){
    const u = (username || '').trim().toLowerCase();
    const p = password || '';
    const c = confirm || '';
    if (u.length < 3) return 'Username must be at least 3 characters';
    if (!/^[a-z0-9._-]+$/.test(u)) return 'Username can only have letters, numbers, dot, dash or underscore';
    if (existing.some(x => x.username.toLowerCase() === u)) return 'That username already exists';
    if (p.length < 6) return 'Password must be at least 6 characters';
    if (c !== undefined && p !== c) return 'Passwords don’t match';
    return null;
  },
  createUser({ username, password, role = 'admin', createdBy = null }){
    const list = Store.getUsers();
    const err = Store.validateUserPayload({ username, password, confirm: password }, { existing: list });
    if (err) return { ok: false, error: err };
    const user = {
      id: `usr-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,
      username: username.trim().toLowerCase(),
      password,
      role,
      createdAt: new Date().toISOString(),
      createdBy,
      lastLogin: null,
    };
    Store.setUsers([...list, user]);
    return { ok: true, user };
  },
  deleteUser(id, { actingUser } = {}){
    const list = Store.getUsers();
    const target = list.find(u => u.id === id);
    if (!target) return { ok: false, error: 'User not found' };
    if (actingUser && target.username === actingUser) return { ok: false, error: 'You cannot delete your own account while signed in' };
    if (list.length <= 1) return { ok: false, error: 'Cannot delete the last admin account' };
    Store.setUsers(list.filter(u => u.id !== id));
    return { ok: true };
  },
  updatePassword(id, newPassword){
    if (!newPassword || newPassword.length < 6) return { ok: false, error: 'Password must be at least 6 characters' };
    const list = Store.getUsers();
    const idx = list.findIndex(u => u.id === id);
    if (idx < 0) return { ok: false, error: 'User not found' };
    list[idx] = { ...list[idx], password: newPassword };
    Store.setUsers(list);
    return { ok: true };
  },

  /* Auth — checks against users list, session in localStorage */
  login(username, password){
    Store.ensureUsers();
    const u = (username || '').trim().toLowerCase();
    const p = (password || '').trim();
    const list = Store.getUsers();
    const user = list.find(x => x.username.toLowerCase() === u && x.password === p);
    if (!user) return { ok: false, error: 'Invalid username or password' };
    // touch lastLogin
    Store.setUsers(list.map(x => x.id === user.id ? { ...x, lastLogin: new Date().toISOString() } : x));
    const session = {
      user: user.username,
      userId: user.id,
      role: user.role,
      issuedAt: Date.now(),
      expiresAt: Date.now() + SESSION_TTL_HOURS * 60 * 60 * 1000,
    };
    writeJSON(STORE_KEYS.session, session);
    return { ok: true, session };
  },
  logout(){ try { localStorage.removeItem(STORE_KEYS.session); } catch {} },
  getSession(){
    const s = readJSON(STORE_KEYS.session, null);
    if (!s || s.expiresAt < Date.now()) return null;
    return s;
  },

  /* Email mock — replace with EmailJS/backend call later */
  sendConfirmationEmail(req){
    return new Promise((resolve) => {
      setTimeout(() => {
        Store.updateStatus(req.id, STATUS.CONFIRMED, {
          emailSent: true,
          emailSentAt: new Date().toISOString(),
        });
        resolve({ ok: true, to: req.customer.email });
      }, 700);
    });
  },

  buildEmailPreview(req){
    const dStr = fmtDateLong(req.date);
    const total = req.pricing?.total ? `$${req.pricing.total.toFixed(2)}` : '—';
    return {
      to: req.customer.email,
      subject: `Your Prestige Auto Spa booking is confirmed — ${dStr} · ${req.slot}`,
      body: [
        `Hi ${req.customer.name.split(' ')[0]},`,
        ``,
        `Your booking with Prestige Auto Spa Mobile is confirmed.`,
        ``,
        `Service: ${req.service.label}`,
        `Vehicle: ${req.vehicle.label}`,
        `Date:    ${dStr}`,
        `Time:    ${req.slot}`,
        `Where:   ${req.address.line}, ${req.address.city} ${req.address.zip}`,
        `Total:   ${total}`,
        ``,
        `Our technician will arrive on time and ready. If anything changes, reply to this email or call (424) 415-0208.`,
        ``,
        `— Prestige Auto Spa Mobile`,
      ].join('\n'),
    };
  },
};

/* --- Date utils exposed for components ------------------- */
const DateUtils = { ymd, fromYmd, today, addDays, fmtDate, fmtDateLong };

window.PrestigeStore = Store;
window.PrestigeDate  = DateUtils;
