// Data store — fetches from Supabase on mount, exposes the same shape the
// pages expect (camelCase fields, house slugs as IDs). Mutations (add/update)
// write through to Supabase and reconcile local state from the returned row.
//
// `pipeline` is in-memory only — future bookings come from Lodgify later,
// not Plaid, and aren't persisted. It's populated from window.generatePipeline
// once that helper exists (added in Phase 1, task 4).

function useStore() {
  const [loading, setLoading] = React.useState(true);
  const [houses, setHouses] = React.useState([]);
  const [transactions, setTransactions] = React.useState([]);
  const [cleanings, setCleanings] = React.useState([]);
  const [pipeline, setPipeline] = React.useState([]);
  const [year, setYear] = React.useState(2026);
  const [cleanerFormFields, setCleanerFormFields] = React.useState(() => DEFAULT_CLEANER_FIELDS.slice());

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      const [h, t, c] = await Promise.all([
        window.db.from('houses').select('*').order('created_at'),
        window.db.from('transactions').select('*').order('date', { ascending: false }),
        window.db.from('cleanings').select('*').order('date', { ascending: false }),
      ]);
      if (cancelled) return;
      const err = h.error || t.error || c.error;
      if (err) { console.error('Initial load failed:', err); return; }

      const appHouses = h.data.map(dbHouseToApp);
      setHouseLookups(appHouses);
      setHouses(appHouses);
      setTransactions(t.data.map(dbTxnToApp));
      setCleanings(c.data.map(dbCleaningToApp));
      if (typeof window.generatePipeline === 'function') {
        setPipeline(window.generatePipeline(appHouses));
      }
      setLoading(false);
    })();
    return () => { cancelled = true; };
  }, []);

  const reloadTransactions = React.useCallback(async () => {
    const { data, error } = await window.db.from('transactions').select('*').order('date', { ascending: false });
    if (error) { console.error('reloadTransactions:', error); return; }
    setTransactions(data.map(dbTxnToApp));
  }, []);

  const updateHouse = React.useCallback(async (slug, patch) => {
    const uuid = houseUuid(slug);
    if (!uuid) return;
    const { error } = await window.db.from('houses').update(appHousePatchToDb(patch)).eq('id', uuid);
    if (error) { console.error('updateHouse:', error); return; }
    setHouses(prev => prev.map(h => h.id === slug ? { ...h, ...patch } : h));
  }, []);

  const updateCleanerFields = React.useCallback((fields) => {
    setCleanerFormFields(fields);
  }, []);

  const addTransaction = React.useCallback(async (t) => {
    const { data, error } = await window.db.from('transactions').insert(appTxnToDb(t)).select().single();
    if (error) { console.error('addTransaction:', error); return; }
    setTransactions(prev => [dbTxnToApp(data), ...prev]);
  }, []);

  const addCleaning = React.useCallback(async (c, house) => {
    const cleaningRow = appCleaningToDb({
      houseId: house.id,
      date: c.date,
      cleaningRateSnapshot: house.cleaningRate,
      laundryAmount: c.laundryAmount,
      laundryReceiptUrl: c.laundryReceiptUrl,
      notes: c.notes,
      cleaner: c.cleaner,
    });
    const txnRows = [
      appTxnToDb({
        houseId: house.id, date: c.date, type: 'expense',
        category: 'Cleaning', description: `Turnover cleaning — ${house.name}`,
        amount: house.cleaningRate, source: 'cleaner',
      }),
    ];
    if (c.laundryAmount > 0) {
      txnRows.push(appTxnToDb({
        houseId: house.id, date: c.date, type: 'expense',
        category: 'Laundry', description: 'Laundry service',
        amount: c.laundryAmount, source: 'cleaner',
        receiptUrl: c.laundryReceiptUrl ? 'receipt' : null,
      }));
    }

    const [cleaningRes, txnRes] = await Promise.all([
      window.db.from('cleanings').insert(cleaningRow).select().single(),
      window.db.from('transactions').insert(txnRows).select(),
    ]);
    if (cleaningRes.error || txnRes.error) {
      console.error('addCleaning:', cleaningRes.error || txnRes.error);
      return;
    }
    setCleanings(prev => [dbCleaningToApp(cleaningRes.data), ...prev]);
    setTransactions(prev => [...txnRes.data.map(dbTxnToApp), ...prev]);
  }, []);

  return {
    loading, transactions, cleanings, houses, pipeline,
    year, setYear,
    addTransaction, addCleaning,
    cleanerFormFields, updateCleanerFields,
    updateHouse,
    reloadTransactions,
  };
}

function txnYear(t)  { return Number(t.date.slice(0, 4)); }
function txnMonth(t) { return Number(t.date.slice(5, 7)) - 1; }

function filterByYear(txns, year) {
  if (year === 'all') return txns;
  return txns.filter(t => txnYear(t) === year);
}

function monthlyTotals(txns, year) {
  const income = Array(12).fill(0);
  const expense = Array(12).fill(0);
  txns.forEach(t => {
    if (txnYear(t) !== year) return;
    if (t.type === 'income') income[txnMonth(t)] += t.amount;
    else expense[txnMonth(t)] += t.amount;
  });
  return { income, expense };
}

function byHouseTotals(txns, houses) {
  return houses.map(h => {
    const ts = txns.filter(t => t.houseId === h.id);
    const income  = ts.filter(t => t.type === 'income').reduce((s, t) => s + t.amount, 0);
    const expense = ts.filter(t => t.type === 'expense').reduce((s, t) => s + t.amount, 0);
    return { house: h, income, expense, net: income - expense };
  });
}

function byCategoryTotals(txns, type) {
  const m = new Map();
  txns.filter(t => t.type === type).forEach(t => {
    m.set(t.category, (m.get(t.category) || 0) + t.amount);
  });
  return Array.from(m.entries()).map(([category, value]) => ({ category, value }))
    .sort((a, b) => b.value - a.value);
}

Object.assign(window, { useStore, filterByYear, monthlyTotals, byHouseTotals, byCategoryTotals, txnYear, txnMonth });
