/* ============ Studio store ============ */
/*  Single source of truth — every change autosaves to localStorage.
    Components subscribe via useStore(), mutate via the imperative API.  */

const STORAGE_KEY = 'notaryStudio.v1';
const BACKUP_KEY  = 'notaryStudio.backups.v1';
const LAST_BACKUP_KEY = 'notaryStudio.lastBackup';
const BACKUP_KEEP = 30; // rolling daily snapshots

const todayISO = () => new Date().toISOString().slice(0,10);
const nowISO = () => new Date().toISOString();
const uid = () => Math.random().toString(36).slice(2, 9) + Date.now().toString(36).slice(-3);

const DEFAULT_SETTINGS = {
  businessName: 'Middlesex Notary Co',
  notaryName: '',
  state: 'MA',
  defaultFee: 150,
  mileageRate: 0.67,            // IRS 2024 standard
  baseAddress: '',
  accent: 'navy',
  logoUrl: 'assets/middlesex-logo.png',
};

const SEED_CLIENTS = [
  { id: 'c1', name: 'John Doe',  phone: '555-0101', email: 'john@email.com',  source: 'Facebook',   status: 'Not Contacted',     priority: 'Low',    revenue: 1000, paid: true,  notes: '', createdAt: nowISO() },
  { id: 'c2', name: 'Jane Doe',  phone: '555-0102', email: 'jane@email.com',  source: 'Website',    status: 'Contacted',         priority: 'Medium', revenue: 5000, paid: false, notes: '', createdAt: nowISO() },
  { id: 'c3', name: 'J Doe',     phone: '555-0103', email: 'jdoe@email.com',  source: 'Networking', status: 'Awaiting Response', priority: 'High',   revenue:10000, paid: false, notes: '', createdAt: nowISO() },
];

const SEED_SIGNINGS = [
  { id: 's1', clientId: 'c2', title: 'Loan signing — Refinance', date: todayISO(), time: '14:00', durationMin: 60, location: '123 Market St, San Francisco', docType: 'Refinance', fee: 175, status: 'Scheduled', notes: '', createdAt: nowISO() },
  { id: 's2', clientId: 'c1', title: 'POA notarization',         date: todayISO(), time: '10:30', durationMin: 30, location: '500 Oak Ave',                  docType: 'POA',        fee: 65,  status: 'Completed', notes: '', createdAt: nowISO() },
];

const SEED_MILEAGE = [
  { id: 'm1', date: todayISO(), clientId: 'c2', purpose: 'Loan signing', from: 'Office', to: '123 Market St', miles: 14.2, roundTrip: true, notes: '', createdAt: nowISO() },
  { id: 'm2', date: todayISO(), clientId: 'c1', purpose: 'POA delivery', from: 'Office', to: '500 Oak Ave',   miles:  8.6, roundTrip: true, notes: '', createdAt: nowISO() },
];

function loadInitial() {
  // Try v1 first
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) {
      const parsed = JSON.parse(raw);
      const settings = { ...DEFAULT_SETTINGS, ...(parsed.settings || {}) };
      // One-time migration: if user is still on the previous app defaults,
      // promote them to Middlesex Notary Co branding.
      if (!parsed._brandedMiddlesex) {
        if (settings.businessName === 'My Notary Practice' || !settings.businessName) {
          settings.businessName = 'Middlesex Notary Co';
        }
        if (settings.accent === 'blue' || !settings.accent) settings.accent = 'navy';
        if (!settings.state) settings.state = 'MA';
        settings.logoUrl = 'assets/middlesex-logo.png';
      }
      return {
        clients:  parsed.clients  || [],
        signings: parsed.signings || [],
        mileage:  parsed.mileage  || [],
        settings,
        _brandedMiddlesex: true,
      };
    }
  } catch(e) {}

  // Migrate from legacy 'notaryData' (previous ledger build)
  try {
    const legacy = localStorage.getItem('notaryData');
    if (legacy) {
      const arr = JSON.parse(legacy);
      const clients = (Array.isArray(arr) ? arr : []).map(c => ({
        id: 'c' + c.id,
        name: c.name || '',
        phone: c.phone || '',
        email: c.email || '',
        source: c.source || 'Phone',
        status: c.status || 'Not Contacted',
        priority: c.priority || 'Low',
        revenue: parseFloat(c.revenue) || 0,
        paid: !!c.paid,
        notes: '',
        createdAt: nowISO(),
      }));
      return { clients, signings: [], mileage: [], settings: { ...DEFAULT_SETTINGS } };
    }
  } catch(e) {}

  return {
    clients: SEED_CLIENTS,
    signings: SEED_SIGNINGS,
    mileage: SEED_MILEAGE,
    settings: { ...DEFAULT_SETTINGS },
  };
}

const Store = (function() {
  let state = loadInitial();
  let listeners = new Set();
  let saveTimer = null;
  let savingFlag = { saving: false, savedAt: Date.now() };

  function notify() {
    listeners.forEach(fn => fn(state));
  }
  function scheduleSave() {
    if (saveTimer) clearTimeout(saveTimer);
    savingFlag = { saving: true, savedAt: savingFlag.savedAt };
    notify();
    saveTimer = setTimeout(() => {
      try {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
        savingFlag = { saving: false, savedAt: Date.now() };
        notify();
      } catch(e) { console.warn('save failed', e); }
    }, 280);
  }

  // Save immediately on page hide so we never lose data
  window.addEventListener('beforeunload', () => {
    try { localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); } catch(e){}
    try { maybeBackup(true); } catch(e){}
  });
  document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'hidden') {
      try { localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); } catch(e){}
    }
  });

  // -------- Daily backup system --------
  function loadBackups() {
    try { return JSON.parse(localStorage.getItem(BACKUP_KEY) || '[]'); } catch(e) { return []; }
  }
  function saveBackups(list) {
    try { localStorage.setItem(BACKUP_KEY, JSON.stringify(list)); } catch(e){}
  }
  function maybeBackup(force = false) {
    const today = todayISO();
    const last = localStorage.getItem(LAST_BACKUP_KEY);
    if (!force && last === today) return false;
    const list = loadBackups();
    const snapshot = {
      id: today + '-' + Math.random().toString(36).slice(2,6),
      date: today,
      createdAt: nowISO(),
      counts: { clients: state.clients.length, signings: state.signings.length, mileage: state.mileage.length },
      data: { clients: state.clients, signings: state.signings, mileage: state.mileage, settings: state.settings },
    };
    // Replace existing entry for today; otherwise prepend
    const filtered = list.filter(b => b.date !== today);
    const next = [snapshot, ...filtered].slice(0, BACKUP_KEEP);
    saveBackups(next);
    localStorage.setItem(LAST_BACKUP_KEY, today);
    return true;
  }
  // Snapshot on first load and every hour while the tab is open
  setTimeout(() => maybeBackup(false), 1500);
  setInterval(() => maybeBackup(false), 60 * 60 * 1000);

  function listBackups() { return loadBackups(); }
  function restoreBackup(id) {
    const b = loadBackups().find(x => x.id === id);
    if (!b) return false;
    commit({
      clients:  b.data.clients  || [],
      signings: b.data.signings || [],
      mileage:  b.data.mileage  || [],
      settings: { ...DEFAULT_SETTINGS, ...(b.data.settings || {}) },
    });
    return true;
  }
  function deleteBackup(id) {
    saveBackups(loadBackups().filter(x => x.id !== id));
    notify();
  }
  function snapshotNow(label) {
    const list = loadBackups();
    const snapshot = {
      id: 'manual-' + Date.now().toString(36),
      date: todayISO(),
      createdAt: nowISO(),
      label: label || 'Manual snapshot',
      counts: { clients: state.clients.length, signings: state.signings.length, mileage: state.mileage.length },
      data: { clients: state.clients, signings: state.signings, mileage: state.mileage, settings: state.settings },
    };
    saveBackups([snapshot, ...list].slice(0, BACKUP_KEEP + 5));
    notify();
    return snapshot.id;
  }

  function getState() { return state; }
  function getSavingFlag() { return savingFlag; }
  function subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); }
  function commit(next) {
    state = next;
    notify();
    scheduleSave();
  }

  // ----- Clients -----
  const Clients = {
    add(c = {}) {
      const item = {
        id: uid(),
        name: '', phone: '', email: '', source: 'Phone',
        status: 'Not Contacted', priority: 'Low',
        revenue: 0, paid: false, notes: '',
        createdAt: nowISO(),
        ...c,
      };
      commit({ ...state, clients: [item, ...state.clients] });
      return item.id;
    },
    update(id, patch) {
      commit({ ...state, clients: state.clients.map(c => c.id === id ? { ...c, ...patch } : c) });
    },
    remove(id) {
      commit({ ...state, clients: state.clients.filter(c => c.id !== id) });
    },
  };

  // ----- Signings -----
  const Signings = {
    add(s = {}) {
      const item = {
        id: uid(), clientId: null, title: '', date: todayISO(), time: '10:00',
        durationMin: 60, location: '', docType: 'Other', fee: state.settings.defaultFee,
        status: 'Scheduled', notes: '', createdAt: nowISO(),
        ...s,
      };
      commit({ ...state, signings: [item, ...state.signings] });
      return item.id;
    },
    update(id, patch) {
      commit({ ...state, signings: state.signings.map(s => s.id === id ? { ...s, ...patch } : s) });
    },
    remove(id) {
      commit({ ...state, signings: state.signings.filter(s => s.id !== id) });
    },
  };

  // ----- Mileage -----
  const Mileage = {
    add(m = {}) {
      const item = {
        id: uid(), date: todayISO(), clientId: null,
        purpose: '', from: state.settings.baseAddress || 'Office', to: '',
        miles: 0, roundTrip: true, notes: '', createdAt: nowISO(),
        ...m,
      };
      commit({ ...state, mileage: [item, ...state.mileage] });
      return item.id;
    },
    update(id, patch) {
      commit({ ...state, mileage: state.mileage.map(m => m.id === id ? { ...m, ...patch } : m) });
    },
    remove(id) {
      commit({ ...state, mileage: state.mileage.filter(m => m.id !== id) });
    },
  };

  // ----- Settings -----
  const Settings = {
    update(patch) {
      commit({ ...state, settings: { ...state.settings, ...patch } });
    },
  };

  // ----- Bulk -----
  function importJSON(payload) {
    if (!payload) return;
    commit({
      clients:  payload.clients  || [],
      signings: payload.signings || [],
      mileage:  payload.mileage  || [],
      settings: { ...DEFAULT_SETTINGS, ...(payload.settings || {}) },
    });
  }
  function resetAll() {
    commit({ clients: SEED_CLIENTS, signings: SEED_SIGNINGS, mileage: SEED_MILEAGE, settings: { ...DEFAULT_SETTINGS } });
  }

  return { getState, getSavingFlag, subscribe, Clients, Signings, Mileage, Settings, importJSON, resetAll, listBackups, restoreBackup, deleteBackup, snapshotNow };
})();

function useStore() {
  const [, setTick] = React.useState(0);
  React.useEffect(() => Store.subscribe(() => setTick(t => t + 1)), []);
  return Store.getState();
}
function useSavingFlag() {
  const [, setTick] = React.useState(0);
  React.useEffect(() => Store.subscribe(() => setTick(t => t + 1)), []);
  return Store.getSavingFlag();
}

/* ============ Formatters ============ */
const fmt = {
  money: (n, dp = 0) => '$' + (Number(n) || 0).toLocaleString('en-US', { minimumFractionDigits: dp, maximumFractionDigits: dp }),
  miles: (n) => (Number(n) || 0).toLocaleString('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 }) + ' mi',
  date:  (iso) => { try { return new Date(iso + 'T00:00:00').toLocaleDateString('en-US', { month:'short', day:'numeric', year:'numeric' }); } catch(e) { return iso; } },
  dateShort: (iso) => { try { return new Date(iso + 'T00:00:00').toLocaleDateString('en-US', { month:'short', day:'numeric' }); } catch(e) { return iso; } },
  time: (t) => { if (!t) return ''; const [h,m] = t.split(':').map(Number); const am = h < 12; const hh = h % 12 || 12; return `${hh}:${String(m).padStart(2,'0')} ${am?'AM':'PM'}`; },
  relativeTime: (ts) => {
    const diff = (Date.now() - ts) / 1000;
    if (diff < 5)  return 'just now';
    if (diff < 60) return Math.floor(diff) + 's ago';
    if (diff < 3600) return Math.floor(diff/60) + 'm ago';
    if (diff < 86400) return Math.floor(diff/3600) + 'h ago';
    return Math.floor(diff/86400) + 'd ago';
  },
};

const STATUS_TONES = {
  'Not Contacted': 'gray',
  'Contacted': 'blue',
  'Awaiting Response': 'orange',
  'Won': 'green',
  'Lost': 'red',
  'Pending': 'purple',
  'Scheduled': 'blue',
  'Completed': 'green',
  'Cancelled': 'red',
  'No-show':   'red',
};
const PRIORITY_TONES = { Low: 'gray', Medium: 'orange', High: 'red' };

Object.assign(window, { Store, useStore, useSavingFlag, fmt, todayISO, nowISO, uid, STATUS_TONES, PRIORITY_TONES });
