// Single-profile client store. Backs to browser localStorage.
// Exposes window.QW_account with a useAccount() React hook.
const { useEffect, useState } = React;

const MAX_FAVOURITES = 50;

const listeners = new Set();
let state = {
  profile: null,
  rooms: [],
  favourites: [],
  cart: [],
  visualisations: [],
  loaded: false,
  notice: '',
};

function emit() { for (const fn of listeners) fn(); }
function setState(patch) { 
  state = { ...state, ...patch }; 
  saveToStorage();
  emit(); 
}

function saveToStorage() {
  if (typeof window === 'undefined') return;
  try {
    const data = {
      profile: state.profile,
      rooms: state.rooms,
      favourites: state.favourites,
      cart: state.cart,
      visualisations: state.visualisations
    };
    localStorage.setItem('vennora_account_state', JSON.stringify(data));
  } catch (err) {
    console.error('Failed to save state to localStorage', err);
  }
}

let noticeTimer = null;
function setNotice(text) {
  state = { ...state, notice: text }; // don't trigger saveToStorage for transient notice
  emit();
  if (noticeTimer) clearTimeout(noticeTimer);
  if (text) noticeTimer = setTimeout(() => {
    state = { ...state, notice: '' };
    emit();
  }, 4500);
}

function refresh() {
  if (typeof window === 'undefined') return;
  try {
    const stored = localStorage.getItem('vennora_account_state');
    if (stored) {
      const d = JSON.parse(stored);
      state = {
        ...state,
        profile: d.profile || null,
        rooms: d.rooms || [],
        favourites: d.favourites || [],
        cart: d.cart || [],
        visualisations: d.visualisations || [],
        loaded: true,
      };
      emit();
      return;
    }
  } catch (err) {
    console.error('Failed to parse localStorage state', err);
  }
  
  state = { ...state, loaded: true };
  emit();
}

async function uploadRoom(file, label) {
  // Since we are running in local-only mode, we can read the file as a Data URI to display it
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const room = {
        id: Math.random().toString(36).substring(2, 9),
        url: e.target.result,
        label: label || 'Room',
        createdAt: new Date().toISOString()
      };
      setState({ rooms: [...state.rooms, room] });
      resolve(room);
    };
    reader.readAsDataURL(file);
  });
}

async function deleteRoom(id) {
  setState({ rooms: state.rooms.filter(r => r.id !== id) });
}

async function toggleFavourite(tileId) {
  const original = state.favourites || [];
  const alreadyFaved = original.includes(tileId);
  
  if (!alreadyFaved && original.length >= MAX_FAVOURITES) {
    setNotice(`You've hit the limit (${MAX_FAVOURITES} tiles). Submit a quote or remove some to add more.`);
    return { ok: false, error: 'cap' };
  }

  const newFavs = alreadyFaved
    ? original.filter(id => id !== tileId)
    : [...original, tileId];
    
  setState({ favourites: newFavs });
  return { ok: true };
}

function saveCart(cart) {
  setState({ cart });
}

function addToCart(tileId, sqm = 5) {
  const existing = state.cart.find(i => i.tileId === tileId);
  let next;
  if (existing) {
    next = state.cart.map(i => i.tileId === tileId ? { ...i, sqm: (i.sqm || 0) + sqm } : i);
  } else {
    next = [...state.cart, { tileId, sqm, addedAt: new Date().toISOString() }];
  }
  saveCart(next);
}

function updateCartItem(tileId, patchOrSqm) {
  const patch = (patchOrSqm && typeof patchOrSqm === 'object')
    ? patchOrSqm
    : { sqm: patchOrSqm };

  const norm = {};
  if ('sqm'  in patch) norm.sqm  = Math.max(0, Number(patch.sqm)  || 0);
  if ('qty'  in patch) norm.qty  = Math.max(0, Math.floor(Number(patch.qty) || 0));
  if ('size' in patch) norm.size = patch.size ? String(patch.size).trim() : '';

  const exists = state.cart.some(i => i.tileId === tileId);
  let next;
  if (exists) {
    next = state.cart.map(i =>
      i.tileId === tileId ? { ...i, ...norm } : i
    );
  } else {
    next = [...state.cart, {
      tileId,
      size: norm.size || '',
      sqm:  norm.sqm  || 0,
      qty:  norm.qty  || 0,
      addedAt: new Date().toISOString(),
    }];
  }
  
  next = next.filter(i => (i.sqm > 0) || (i.qty > 0) || i.size);
  saveCart(next);
}

function removeFromCart(tileId) {
  saveCart(state.cart.filter(i => i.tileId !== tileId));
}

async function saveVisualisation(payload) {
  const visualisation = {
    ...payload,
    id: Math.random().toString(36).substring(2, 9),
    createdAt: new Date().toISOString()
  };
  setState({ visualisations: [visualisation, ...state.visualisations] });
  return visualisation;
}

function useAccount() {
  const [, tick] = useState(0);
  useEffect(() => {
    const fn = () => tick(n => n + 1);
    listeners.add(fn);
    if (!state.loaded) refresh();
    return () => { listeners.delete(fn); };
  }, []);
  
  return {
    ...state,
    MAX_FAVOURITES,
    isCartFull: (state.favourites || []).length >= MAX_FAVOURITES,
    refresh,
    uploadRoom,
    deleteRoom,
    toggleFavourite,
    addToCart,
    updateCartItem,
    removeFromCart,
    saveVisualisation,
    setNotice,
  };
}

Object.assign(window, {
  QW_account: { state, refresh, uploadRoom, deleteRoom, toggleFavourite, addToCart, updateCartItem, removeFromCart, saveVisualisation, setNotice, MAX_FAVOURITES },
  useAccount,
});
