// InstantDevis — Stores localStorage : Profil, Catalogue, Signatures
// ═══════════════════════════════════════════════════════════════════

// ── MODULE 1 : PROFIL ARTISAN (légal / PDF / fiscal) ────────────────────
const AF_PROFILE_DEFAULTS = {
  workspaceId:          '',
  name:                 'Thomas Durand',
  companyName:          '',
  email:                '',
  phone:                '',
  address:              '',
  siret:                '',
  logoUrl:              '',
  updatedAt:            '',
  nom:                  'Thomas Durand',
  entreprise:           '',
  adresse:              '',
  codePostal:           '',
  ville:                '',
  tel:                  '',
  assureurNom:          '',
  assuranceNum:         '',
  iban:                 '',
  defaultTva:           20,
  acomptePercent:       30,
  /** Base HTTPS unique Cloudflare (agents) — public, sans secret ; priorité sous `AF_INTEGRATION.workersBase` dans tokens.jsx */
  workersBaseUrl:       '',
  vocalWorkerBaseUrl:   '',
};

/** Champs profil fiscal (non sensibles) — fusionnés avec le profil pour rétrocompatibilité localStorage. */
const AF_FISCAL_DEFAULTS = {
  /** Préréglage courant : auto_entrepreneur | ei_reel | eurl | sasu | sarl_tva | custom */
  companyPreset:       'custom',
  /** Libellé forme juridique (affichage + contexte agent) */
  legalForm:           '',
  /** Mode TVA machine : franchise | reel_simplifie | reel_normal | assujetti */
  vatMode:             '',
  /** Corps de métier principal (aligné catalogue / devis) */
  primaryTrade:        'multi',
  /** Clientèle : particuliers | professionnels | mixte */
  customerMode:        '',
  /** Ligne courte optionnelle pied de PDF / mentions */
  fiscalMentionShort:  '',
  /** true si l’utilisateur a modifié après un préréglage, ou mode manuel */
  fiscalCustomized:    true,
};

/** Préréglages fiscaux BTP (valeurs indicatives — l’utilisateur peut tout ajuster). */
const AF_FISCAL_PRESETS = {
  auto_entrepreneur: {
    label: 'Micro-entrepreneur artisan',
    patch: {
      legalForm: 'Micro-entrepreneur (auto-entrepreneur)',
      vatMode: 'franchise',
      defaultTva: 10,
      acomptePercent: 30,
      customerMode: 'particuliers',
      primaryTrade: 'multi',
    },
  },
  ei_reel: {
    label: 'EI au réel',
    patch: {
      legalForm: 'Entreprise individuelle (régime réel)',
      vatMode: 'reel_simplifie',
      defaultTva: 10,
      acomptePercent: 30,
      customerMode: 'mixte',
      primaryTrade: 'multi',
    },
  },
  eurl: {
    label: 'EURL artisan',
    patch: {
      legalForm: 'EURL',
      vatMode: 'assujetti',
      defaultTva: 10,
      acomptePercent: 30,
      customerMode: 'mixte',
      primaryTrade: 'multi',
    },
  },
  sasu: {
    label: 'SASU artisan',
    patch: {
      legalForm: 'SASU',
      vatMode: 'assujetti',
      defaultTva: 10,
      acomptePercent: 30,
      customerMode: 'mixte',
      primaryTrade: 'multi',
    },
  },
  sarl_tva: {
    label: 'Société artisanale assujettie TVA',
    patch: {
      legalForm: 'SARL / société artisanale (TVA)',
      vatMode: 'assujetti',
      defaultTva: 10,
      acomptePercent: 30,
      customerMode: 'mixte',
      primaryTrade: 'multi',
    },
  },
  custom: {
    label: 'Manuel / personnalisé',
    patch: {},
  },
};

const AF_PROFILE_STORE = (() => {
  const KEY = 'instantdevis_profile';
  const LEGACY_KEY = 'instantdevis_profile_v1';
  const WORKSPACE_KEY = 'instantdevis_workspace_id';
  let _data = { ...AF_PROFILE_DEFAULTS, ...AF_FISCAL_DEFAULTS };
  let _listeners = [];

  const _isoNow = () => new Date().toISOString();
  const _randomHex = (bytes) => {
    try {
      if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
        const a = new Uint8Array(bytes);
        crypto.getRandomValues(a);
        return Array.from(a).map((b) => b.toString(16).padStart(2, '0')).join('');
      }
    } catch (e) {}
    let out = '';
    for (let i = 0; i < bytes; i += 1) {
      out += Math.floor(Math.random() * 256).toString(16).padStart(2, '0');
    }
    return out;
  };
  const _getOrCreateWorkspaceId = () => {
    try {
      const existing = String(localStorage.getItem(WORKSPACE_KEY) || '').trim();
      if (existing && existing.startsWith('ws_')) return existing;
      const created = `ws_${_randomHex(12)}`;
      localStorage.setItem(WORKSPACE_KEY, created);
      return created;
    } catch (e) {
      return `ws_${_randomHex(12)}`;
    }
  };
  const _safeTrim = (v) => String(v == null ? '' : v).trim();

  const _parse = (raw) => {
    const parsed = { ...AF_PROFILE_DEFAULTS, ...AF_FISCAL_DEFAULTS, ...JSON.parse(raw || '{}') };
    if ('openAiKey' in parsed) {
      try { delete parsed.openAiKey; } catch (e) { parsed.openAiKey = undefined; }
    }
    if (!parsed.vocalWorkerBaseUrl) parsed.vocalWorkerBaseUrl = '';
    if (parsed.workersBaseUrl == null) parsed.workersBaseUrl = '';
    if (parsed.primaryTrade == null || String(parsed.primaryTrade).trim() === '') parsed.primaryTrade = 'multi';
    if (parsed.companyPreset == null) parsed.companyPreset = 'custom';
    if (parsed.fiscalCustomized == null) parsed.fiscalCustomized = true;
    if (parsed.legalForm == null) parsed.legalForm = '';
    if (parsed.vatMode == null) parsed.vatMode = '';
    if (parsed.customerMode == null) parsed.customerMode = '';
    if (parsed.fiscalMentionShort == null) parsed.fiscalMentionShort = '';
    parsed.name = _safeTrim(parsed.name || parsed.nom);
    parsed.companyName = _safeTrim(parsed.companyName || parsed.entreprise);
    parsed.phone = _safeTrim(parsed.phone || parsed.tel);
    parsed.address = _safeTrim(parsed.address || parsed.adresse);
    parsed.logoUrl = _safeTrim(parsed.logoUrl);
    parsed.email = _safeTrim(parsed.email).toLowerCase();
    parsed.nom = parsed.name;
    parsed.entreprise = parsed.companyName;
    parsed.tel = parsed.phone;
    parsed.adresse = parsed.address;
    parsed.workspaceId = _safeTrim(parsed.workspaceId || _getOrCreateWorkspaceId());
    parsed.updatedAt = _safeTrim(parsed.updatedAt || _isoNow());
    return parsed;
  };

  try {
    const raw = localStorage.getItem(KEY) || localStorage.getItem(LEGACY_KEY);
    if (raw) _data = _parse(raw);
  } catch {}

  // Sync cross-tab: storage event fires in every tab EXCEPT the one that wrote
  window.addEventListener('storage', (e) => {
    if ((e.key !== KEY && e.key !== LEGACY_KEY) || e.newValue == null) return;
    try {
      _data = _parse(e.newValue);
      _listeners.forEach(fn => fn({ ..._data }));
    } catch {}
  });

  return {
    get()       { return { ..._data }; },
    loadProfile() { return { ..._data }; },
    normalizeProfile(u) { return _parse(JSON.stringify({ ..._data, ...(u || {}) })); },
    save(u)     {
      const next = _parse(JSON.stringify({ ..._data, ...(u || {}), updatedAt: _isoNow() }));
      try { delete next.openAiKey; } catch (e) {}
      _data = next;
      try {
        localStorage.setItem(KEY, JSON.stringify(_data));
        localStorage.setItem(LEGACY_KEY, JSON.stringify(_data));
      } catch {}
      _listeners.forEach(fn => fn({ ..._data }));
    },
    saveProfile(u) { this.save(u); },
    subscribe(fn) {
      _listeners.push(fn);
      return () => { _listeners = _listeners.filter(l => l !== fn); };
    },
  };
})();

/**
 * Profil fiscal — contexte déterministe pour l’app et futur agent fiscal (sans réseau).
 * @namespace AF_FISCAL
 */
const AF_FISCAL = (() => {
  function isProfileComplete(p) {
    const x = p || (typeof AF_PROFILE_STORE !== 'undefined' ? AF_PROFILE_STORE.get() : {});
    return !!(
      String(x.legalForm || '').trim()
      && String(x.vatMode || '').trim()
      && String(x.customerMode || '').trim()
      && String(x.primaryTrade || '').trim()
    );
  }

  /**
   * Contexte fiscal normalisé (lecture seule) pour agent / écrans.
   * @returns {{
   *   companyPreset: string,
   *   legalForm: string,
   *   vatMode: string,
   *   trade: string,
   *   customerMode: string,
   *   acomptePercent: number,
   *   defaultTva: number,
   *   fiscalMentionShort: string,
   *   isCustom: boolean,
   *   fiscalProfileComplete: boolean
   * }}
   */
  function getContext() {
    const p = typeof AF_PROFILE_STORE !== 'undefined' ? AF_PROFILE_STORE.get() : {};
    const acompte = p.acomptePercent != null ? Number(p.acomptePercent) : 30;
    const dtva = p.defaultTva != null ? Number(p.defaultTva) : 20;
    return {
      companyPreset: String(p.companyPreset || 'custom'),
      legalForm: String(p.legalForm || '').trim(),
      vatMode: String(p.vatMode || '').trim(),
      trade: String(p.primaryTrade || 'multi').trim() || 'multi',
      customerMode: String(p.customerMode || '').trim(),
      acomptePercent: Number.isFinite(acompte) ? acompte : 30,
      defaultTva: Number.isFinite(dtva) ? dtva : 20,
      fiscalMentionShort: String(p.fiscalMentionShort || '').trim(),
      isCustom: !!p.fiscalCustomized,
      fiscalProfileComplete: isProfileComplete(p),
    };
  }

  function getPresetLabel(presetId) {
    const id = String(presetId || '');
    const d = AF_FISCAL_PRESETS[id];
    return d ? d.label : 'Manuel / personnalisé';
  }

  /** @returns {Array<{ id: string, label: string }>} */
  function listPresets() {
    return Object.keys(AF_FISCAL_PRESETS).map((id) => ({
      id,
      label: AF_FISCAL_PRESETS[id].label,
    }));
  }

  /**
   * Objet de fusion à passer à AF_PROFILE_STORE.save pour appliquer un préréglage.
   * @param {string} presetId
   * @returns {object|null} null si id inconnu
   */
  function buildApplyPresetPatch(presetId) {
    const id = String(presetId || '');
    const def = AF_FISCAL_PRESETS[id];
    if (!def) return null;
    if (id === 'custom') {
      return {
        companyPreset: 'custom',
        fiscalCustomized: true,
      };
    }
    return {
      ...def.patch,
      companyPreset: id,
      fiscalCustomized: false,
    };
  }

  return {
    PRESETS: AF_FISCAL_PRESETS,
    DEFAULTS: AF_FISCAL_DEFAULTS,
    getContext,
    isProfileComplete,
    getPresetLabel,
    listPresets,
    buildApplyPresetPatch,
  };
})();

// ── MODULE 2 : CATALOGUE PRESTATIONS ──────────────────────────
const AF_CATALOG_DEFAULTS = [
  { id:'cat-1',  label:'Pose carrelage',             unit:'m²',     pu:42,  tva:10, trade:'multi',       keywords:['carrelage','careler','carreau','pose carre'] },
  { id:'cat-2',  label:'Dépose carrelage + évac.',   unit:'m²',     pu:18,  tva:10, trade:'multi',       keywords:['dépose','evacuation','gravats','ancien carre'] },
  { id:'cat-3',  label:'Joint époxy carrelage',      unit:'m²',     pu:8,   tva:10, trade:'multi',       keywords:['joint époxy','époxy','joint'] },
  { id:'cat-4',  label:'Chauffe-eau 200L Atlantic',  unit:'pce',    pu:489, tva:20, trade:'plomberie',   keywords:['chauffe-eau','ballon','eau chaude'] },
  { id:'cat-5',  label:'Remplacement robinet/mitigeur', unit:'pce', pu:180, tva:20, trade:'plomberie',   keywords:['robinet','mitigeur','fuite','robineterie'] },
  { id:'cat-6',  label:'Pose WC suspendu',           unit:'pce',    pu:350, tva:20, trade:'plomberie',   keywords:['wc','toilette','sanitaire','cuvette'] },
  { id:'cat-7',  label:'Main d\'œuvre plombier',     unit:'h',      pu:58,  tva:20, trade:'plomberie',   keywords:['plombier','main d\'oeuvre plom'] },
  { id:'cat-8',  label:'Tableau électrique Legrand', unit:'pce',    pu:268, tva:10, trade:'electricite', keywords:['tableau','disjoncteur','tableau électrique'] },
  { id:'cat-9',  label:'Prise/interrupteur Legrand', unit:'pce',    pu:45,  tva:10, trade:'electricite', keywords:['prise','interrupteur','applique'] },
  { id:'cat-10', label:'Câblage gaine (ml)',          unit:'ml',     pu:12,  tva:10, trade:'electricite', keywords:['câble','gaine','câblage'] },
  { id:'cat-11', label:'Main d\'œuvre électricien',  unit:'h',      pu:62,  tva:20, trade:'electricite', keywords:['électricien','elec','main d\'oeuvre elec'] },
  { id:'cat-12', label:'Peinture acrylique Tollens', unit:'m²',     pu:22,  tva:10, trade:'peinture',    keywords:['peinture','peindre','acrylique','tollens'] },
  { id:'cat-13', label:'Préparation murs (ponçage)', unit:'m²',     pu:12,  tva:10, trade:'peinture',    keywords:['ponçage','préparation','rebouchage','poncer'] },
  { id:'cat-14', label:'Application 2 couches',      unit:'m²',     pu:10,  tva:10, trade:'peinture',    keywords:['application','couche','rouleau'] },
  { id:'cat-15', label:'Déplacement & frais',        unit:'forfait', pu:45, tva:20, trade:'multi',       keywords:['déplacement','frais','déplace'] },
  { id:'cat-16', label:'Main d\'œuvre (généralist.)',unit:'h',      pu:52,  tva:20, trade:'multi',       keywords:['main d\'oeuvre','mo','heure'] },
];

const AF_CATALOG_STORE = (() => {
  const KEY = 'instantdevis_catalog_v1';
  let _items = [...AF_CATALOG_DEFAULTS];
  let _listeners = [];

  try {
    const raw = localStorage.getItem(KEY);
    if (raw) {
      const parsed = JSON.parse(raw);
      if (Array.isArray(parsed) && parsed.length > 0) _items = parsed;
    }
  } catch {}

  const _notify = () => _listeners.forEach(fn => fn([..._items]));
  const _persist = () => {
    try { localStorage.setItem(KEY, JSON.stringify(_items)); } catch {}
  };

  // Sync cross-tab
  window.addEventListener('storage', (e) => {
    if (e.key !== KEY || e.newValue == null) return;
    try {
      const parsed = JSON.parse(e.newValue);
      if (Array.isArray(parsed)) { _items = parsed; _notify(); }
    } catch {}
  });

  return {
    getAll()     { return [..._items]; },

    // Recherche par mots-clés (pour la simulation de dictée)
    search(text) {
      const lower = text.toLowerCase();
      return _items.filter(it =>
        (it.keywords || []).some(kw => lower.includes(kw.toLowerCase())) ||
        it.label.toLowerCase().split(' ').some(w => w.length > 3 && lower.includes(w))
      );
    },

    // Matches pour une prestation spécifique par trade
    forTrade(trade) {
      return _items.filter(it => it.trade === trade || it.trade === 'multi');
    },

    add(item) {
      const newItem = { ...item, id: `cat-${Date.now()}` };
      _items = [newItem, ..._items];
      _persist(); _notify();
      return newItem;
    },

    update(id, updates) {
      _items = _items.map(it => it.id === id ? { ...it, ...updates } : it);
      _persist(); _notify();
    },

    remove(id) {
      _items = _items.filter(it => it.id !== id);
      _persist(); _notify();
    },

    reset() {
      _items = [...AF_CATALOG_DEFAULTS];
      _persist(); _notify();
    },

    subscribe(fn) {
      _listeners.push(fn);
      return () => { _listeners = _listeners.filter(l => l !== fn); };
    },
  };
})();

// ── MODULE 3 : SIGNATURES (par ID de devis) ────────────────────
const AF_SIGN_STORE = (() => {
  const KEY = 'instantdevis_signatures_v1';
  let _sigs = {};

  try {
    const raw = localStorage.getItem(KEY);
    if (raw) _sigs = JSON.parse(raw);
  } catch {}

  const _persist = () => {
    try { localStorage.setItem(KEY, JSON.stringify(_sigs)); } catch {}
  };

  return {
    get(devisId)  { return _sigs[devisId] || null; },
    has(devisId)  { return !!_sigs[devisId]; },

    save(devisId, dataUrl) {
      if (typeof AF_STORE !== 'undefined' && devisId != null && AF_STORE.isDevisReadOnlyById(devisId)) {
        console.warn('[InstantDevis] AF_SIGN_STORE.save refusé — devis signé / payé (verrou)');
        return null;
      }
      const now = new Date();
      _sigs[devisId] = {
        dataUrl,
        date:     now.toLocaleDateString('fr-FR'),
        datetime: now.toISOString(),
      };
      _persist();
      return _sigs[devisId];
    },

    remove(devisId) {
      if (typeof AF_STORE !== 'undefined' && devisId != null && AF_STORE.isDevisReadOnlyById(devisId)) {
        console.warn('[InstantDevis] AF_SIGN_STORE.remove refusé — devis signé / payé (verrou)');
        return;
      }
      delete _sigs[devisId];
      _persist();
    },
  };
})();

Object.assign(window, { AF_PROFILE_STORE, AF_CATALOG_STORE, AF_SIGN_STORE, AF_FISCAL });
