/* ============================================================
   STORE — historial (localStorage), biblioteca legal, fiscal helper
   Additive: no toca la lógica existente. Pub/sub vía evento.
   ============================================================ */

const LX_HISTORY_KEY = 'lexly_history';

function lxLoad() {
  try {
    const d = JSON.parse(localStorage.getItem(LX_HISTORY_KEY) || 'null');
    if (d && Array.isArray(d.chats) && Array.isArray(d.contracts)) return d;
  } catch (e) {}
  return { chats: [], contracts: [] };
}
function lxPersist(data) {
  try { localStorage.setItem(LX_HISTORY_KEY, JSON.stringify(data)); } catch (e) {}
  window.dispatchEvent(new CustomEvent('lexly-history'));
}

/* ---- Chats: upsert by id ---- */
function lxUpsertChat(entry) {
  const d = lxLoad();
  const i = d.chats.findIndex(c => c.id === entry.id);
  if (i !== -1) d.chats[i] = { ...d.chats[i], ...entry };
  else d.chats.unshift(entry);
  // keep most-recent first
  d.chats.sort((a, b) => b.updatedAt - a.updatedAt);
  lxPersist(d);
}
function lxAddContract(entry) {
  const d = lxLoad();
  d.contracts.unshift(entry);
  lxPersist(d);
}
function lxDeleteChat(id) { const d = lxLoad(); d.chats = d.chats.filter(c => c.id !== id); lxPersist(d); }
function lxDeleteContract(id) { const d = lxLoad(); d.contracts = d.contracts.filter(c => c.id !== id); lxPersist(d); }
function lxClearAll() { lxPersist({ chats: [], contracts: [] }); }

/* React hook that re-reads on change */
function useHistory() {
  const [data, setData] = useState(lxLoad);
  useEffect(() => {
    const h = () => setData(lxLoad());
    window.addEventListener('lexly-history', h);
    window.addEventListener('storage', h);
    return () => { window.removeEventListener('lexly-history', h); window.removeEventListener('storage', h); };
  }, []);
  return data;
}

function lxId() { return Date.now().toString(36) + Math.random().toString(36).slice(2, 7); }

/* ---- Relative date formatting (ES/CA) ---- */
function lxRelDate(ts, lang = 'es') {
  const now = Date.now();
  const diff = Math.floor((now - ts) / 1000);
  const L = {
    es: { now: 'Ahora mismo', min: 'hace {n} min', hour: 'hace {n} h', yest: 'Ayer', days: 'hace {n} días' },
    ca: { now: 'Ara mateix', min: 'fa {n} min', hour: 'fa {n} h', yest: 'Ahir', days: 'fa {n} dies' },
  }[lang] || null;
  const t = L || { now: 'Ahora mismo', min: 'hace {n} min', hour: 'hace {n} h', yest: 'Ayer', days: 'hace {n} días' };
  if (diff < 60) return t.now;
  if (diff < 3600) return t.min.replace('{n}', Math.floor(diff / 60));
  if (diff < 86400) return t.hour.replace('{n}', Math.floor(diff / 3600));
  if (diff < 172800) return t.yest;
  if (diff < 604800) return t.days.replace('{n}', Math.floor(diff / 86400));
  const d = new Date(ts);
  return d.toLocaleDateString(lang === 'ca' ? 'ca-ES' : 'es-ES', { day: 'numeric', month: 'short', year: 'numeric' });
}

/* ============================================================
   BIBLIOTECA LEGAL — catálogo
   type = tipo válido del generador (servicios|arrendamiento|compraventa|confidencialidad|laboral)
   ============================================================ */
const LIBRARY = [
  {
    id: 'negocios', icon: 'briefcase',
    name: { es: 'Negocios y contratos', ca: 'Negocis i contractes' },
    docs: [
      { name: { es: 'Contrato de prestación de servicios', ca: 'Contracte de prestació de serveis' }, type: 'servicios' },
      { name: { es: 'Acuerdo de confidencialidad (NDA)', ca: "Acord de confidencialitat (NDA)" }, type: 'confidencialidad' },
      { name: { es: 'Contrato de compraventa mercantil', ca: 'Contracte de compravenda mercantil' }, type: 'compraventa' },
      { name: { es: 'Contrato de colaboración comercial', ca: 'Contracte de col·laboració comercial' }, type: 'servicios' },
      { name: { es: 'Acuerdo de distribución', ca: 'Acord de distribució' }, type: 'servicios' },
    ],
  },
  {
    id: 'autonomos', icon: 'bolt',
    name: { es: 'Autónomos y freelance', ca: 'Autònoms i freelance' },
    docs: [
      { name: { es: 'Contrato de servicios freelance', ca: 'Contracte de serveis freelance' }, type: 'servicios' },
      { name: { es: 'Hoja de encargo profesional', ca: "Full d'encàrrec professional" }, type: 'servicios' },
      { name: { es: 'NDA para cliente', ca: 'NDA per a client' }, type: 'confidencialidad' },
      { name: { es: 'Cesión de derechos de autor', ca: "Cessió de drets d'autor" }, type: 'servicios' },
      { name: { es: 'Contrato de mantenimiento', ca: 'Contracte de manteniment' }, type: 'servicios' },
    ],
  },
  {
    id: 'inmobiliario', icon: 'building',
    name: { es: 'Inmobiliario', ca: 'Immobiliari' },
    docs: [
      { name: { es: 'Arrendamiento de vivienda', ca: "Arrendament d'habitatge" }, type: 'arrendamiento' },
      { name: { es: 'Arrendamiento de local de negocio', ca: 'Arrendament de local de negoci' }, type: 'arrendamiento' },
      { name: { es: 'Compraventa inmobiliaria', ca: 'Compravenda immobiliària' }, type: 'compraventa' },
      { name: { es: 'Contrato de arras', ca: "Contracte d'arres" }, type: 'compraventa' },
      { name: { es: 'Arrendamiento de habitación', ca: "Arrendament d'habitació" }, type: 'arrendamiento' },
    ],
  },
  {
    id: 'personal', icon: 'heart',
    name: { es: 'Personal y familia', ca: 'Personal i família' },
    docs: [
      { name: { es: 'Compraventa de vehículo', ca: 'Compravenda de vehicle' }, type: 'compraventa' },
      { name: { es: 'Préstamo entre particulares', ca: 'Préstec entre particulars' }, type: 'compraventa' },
      { name: { es: 'Reconocimiento de deuda', ca: 'Reconeixement de deute' }, type: 'compraventa' },
      { name: { es: 'Acuerdo de convivencia', ca: 'Acord de convivència' }, type: 'servicios' },
      { name: { es: 'Contrato de cesión de uso', ca: "Contracte de cessió d'ús" }, type: 'arrendamiento' },
    ],
  },
];

/* ============================================================
   FISCAL — versión compacta para el dashboard (no toca alerts.jsx)
   ============================================================ */
const LX_OBLIGATIONS = [
  { code: '303', name: 'Modelo 303', desc: { es: 'IVA trimestral', ca: 'IVA trimestral' }, kind: 'q', dates: [[3,20],[6,20],[9,20],[0,30]] },
  { code: '130', name: 'Modelo 130', desc: { es: 'IRPF trimestral', ca: 'IRPF trimestral' }, kind: 'q', dates: [[3,20],[6,20],[9,20],[0,30]] },
  { code: '390', name: 'Modelo 390', desc: { es: 'Resumen anual IVA', ca: 'Resum anual IVA' }, kind: 'a', date: [0,30] },
  { code: '100', name: 'Modelo 100', desc: { es: 'Declaración de la renta', ca: 'Declaració de la renda' }, kind: 'a', date: [5,30] },
];
function lxNextDeadlines() {
  const today = new Date(); today.setHours(0,0,0,0);
  const occ = (m, d, y = 0) => new Date(today.getFullYear() + y, m, d, 23,59,59);
  const days = (due) => Math.ceil((due - today) / 86400000);
  const status = (n) => n < 10 ? 'red' : n <= 30 ? 'amber' : 'green';
  return LX_OBLIGATIONS.map(o => {
    let due;
    if (o.kind === 'q') {
      const c = [];
      for (let y = 0; y <= 1; y++) o.dates.forEach(([m, d]) => c.push(occ(m, d, y)));
      c.sort((a, b) => a - b);
      due = c.find(x => x >= today);
    } else {
      due = occ(o.date[0], o.date[1]);
      if (due < today) due = occ(o.date[0], o.date[1], 1);
    }
    const n = days(due);
    return { ...o, due, days: n, status: status(n) };
  }).sort((a, b) => a.days - b.days);
}

/* ============================================================
   FICHAS FISCALES — caché en localStorage (no regenerar)
   ============================================================ */
const LX_FICHE_KEY = 'lexly_fiches';
function lxFicheGet(code) {
  try { const d = JSON.parse(localStorage.getItem(LX_FICHE_KEY) || '{}'); return d[code] || null; } catch (e) { return null; }
}
function lxFicheSet(code, val) {
  try {
    const d = JSON.parse(localStorage.getItem(LX_FICHE_KEY) || '{}');
    d[code] = val;
    localStorage.setItem(LX_FICHE_KEY, JSON.stringify(d));
  } catch (e) {}
}

/* ============================================================
   PERFIL INTELIGENTE — consentimiento granular RGPD (opt-in)
   Todo en localStorage. Nada sale del navegador.
   ============================================================ */
const LX_PROFILE_KEY = 'lexly_profile';

const CCAA = [
  'Andalucía','Aragón','Asturias','Islas Baleares','Canarias','Cantabria',
  'Castilla-La Mancha','Castilla y León','Cataluña','Comunidad Valenciana',
  'Extremadura','Galicia','Madrid','Murcia','Navarra','País Vasco','La Rioja',
  'Ceuta','Melilla',
];

/* Cada categoría: id, etiqueta, para qué se usa, y campos editables (si aplica). */
const PROFILE_CATEGORIES = [
  { id: 'whoami', label: 'Quién eres', use: 'Personaliza el trato y adapta las respuestas a tu profesión o actividad.',
    fields: [
      { key: 'nombre', label: 'Nombre', type: 'text', ph: 'Tu nombre' },
      { key: 'actividad', label: 'Profesión o actividad económica', type: 'text', ph: 'Ej. Diseñadora gráfica' },
      { key: 'tipo', label: 'Tipo de contribuyente', type: 'select', options: [['autonomo','Autónomo / Freelancer'],['pyme','Pyme / Sociedad'],['particular','Particular']] },
    ] },
  { id: 'company', label: 'Empresa o sector', use: 'Adapta ejemplos y normativa al contexto de tu empresa o sector.',
    fields: [
      { key: 'empresa', label: 'Empresa', type: 'text', ph: 'Razón social' },
      { key: 'sector', label: 'Sector', type: 'text', ph: 'Ej. Comercio electrónico' },
    ] },
  { id: 'region', label: 'Comunidad Autónoma', use: 'Tiene en cuenta la normativa autonómica aplicable a tu residencia o actividad.',
    fields: [ { key: 'ccaa', label: 'Comunidad Autónoma', type: 'select', options: CCAA.map(c => [c, c]) } ] },
  { id: 'fiscal', label: 'Situación fiscal', use: 'Ajusta la información fiscal a tu régimen y tipo de IVA.',
    fields: [
      { key: 'regimen', label: 'Régimen', type: 'select', options: [['directa','Estimación directa'],['directa_simpl','Estimación directa simplificada'],['modulos','Estimación objetiva (módulos)'],['sociedades','Impuesto sobre Sociedades'],['recargo','Recargo de equivalencia']] },
      { key: 'iva', label: 'Tipo de IVA habitual', type: 'select', options: [['21','General (21%)'],['10','Reducido (10%)'],['4','Superreducido (4%)'],['exento','Exento']] },
    ] },
  { id: 'history', label: 'Historial de conversaciones con la IA', use: 'Permite que Lexly tenga en cuenta tus conversaciones anteriores para dar continuidad.', fields: [] },
  { id: 'documents', label: 'Documentos subidos', use: 'Permite recordar los documentos que has revisado para futuras consultas.', fields: [] },
  { id: 'forms', label: 'Formularios completados', use: 'Reutiliza datos de formularios anteriores para no pedírtelos de nuevo.', fields: [] },
  { id: 'preferences', label: 'Preferencias de uso', use: 'Adapta el nivel de detalle y el estilo de las respuestas a cómo prefieres usar Lexly.',
    fields: [ { key: 'estilo', label: 'Estilo de respuesta preferido', type: 'select', options: [['breve','Respuestas breves y directas'],['detallado','Respuestas detalladas'],['tecnico','Con detalle técnico/normativo']] } ] },
  { id: 'topics', label: 'Temas de interés', use: 'Prioriza la información sobre los temas legales y fiscales que más te importan.',
    fields: [ { key: 'temas', label: 'Temas de interés', type: 'textarea', ph: 'Ej. RGPD, morosidad, contratos freelance…' } ] },
  { id: 'goals', label: 'Objetivos fiscales, jurídicos o empresariales', use: 'Orienta las recomendaciones hacia lo que quieres conseguir.',
    fields: [ { key: 'objetivos', label: 'Tus objetivos', type: 'textarea', ph: 'Ej. Optimizar mi fiscalidad como autónomo, internacionalizar…' } ] },
];

function lxProfileDefault() {
  const consent = {}; const data = {};
  PROFILE_CATEGORIES.forEach(c => { consent[c.id] = false; data[c.id] = {}; });
  return { consent, data, log: [] };
}
function lxProfileLoad() {
  try {
    const d = JSON.parse(localStorage.getItem(LX_PROFILE_KEY) || 'null');
    if (d && d.consent && d.data) {
      const base = lxProfileDefault();
      return { consent: { ...base.consent, ...d.consent }, data: { ...base.data, ...d.data }, log: Array.isArray(d.log) ? d.log : [] };
    }
  } catch (e) {}
  return lxProfileDefault();
}
function lxProfilePersist(p) {
  try { localStorage.setItem(LX_PROFILE_KEY, JSON.stringify(p)); } catch (e) {}
  window.dispatchEvent(new CustomEvent('lexly-profile'));
}
function lxSetConsent(catId, on) {
  const p = lxProfileLoad();
  p.consent[catId] = !!on;
  if (!on) p.data[catId] = {}; // al desactivar se borran los datos de la categoría
  p.log.unshift({ category: catId, action: on ? 'activado' : 'desactivado', at: Date.now() });
  lxProfilePersist(p);
}
function lxSetProfileData(catId, key, value) {
  const p = lxProfileLoad();
  p.data[catId] = { ...(p.data[catId] || {}), [key]: value };
  lxProfilePersist(p);
}
function lxProfileDeleteCategory(catId) {
  const p = lxProfileLoad();
  p.data[catId] = {};
  if (p.consent[catId]) { p.consent[catId] = false; p.log.unshift({ category: catId, action: 'datos eliminados', at: Date.now() }); }
  lxProfilePersist(p);
}
function lxProfileDeleteAll() {
  const fresh = lxProfileDefault();
  fresh.log = [{ category: 'todo', action: 'todos los datos eliminados', at: Date.now() }];
  lxProfilePersist(fresh);
}
function useProfile() {
  const [p, setP] = useState(lxProfileLoad);
  useEffect(() => {
    const h = () => setP(lxProfileLoad());
    window.addEventListener('lexly-profile', h);
    window.addEventListener('storage', h);
    return () => { window.removeEventListener('lexly-profile', h); window.removeEventListener('storage', h); };
  }, []);
  return p;
}

/* Tipo de contribuyente consentido (para alertas fiscales). null si no consentido. */
function lxProfileActivityType() {
  const p = lxProfileLoad();
  if (p.consent.whoami && p.data.whoami && p.data.whoami.tipo) return p.data.whoami.tipo;
  return null;
}

/* Fragmento de contexto para el system prompt — SOLO categorías consentidas y con datos. */
function lxProfileContext() {
  const p = lxProfileLoad();
  const C = p.consent, D = p.data;
  const bits = [];
  if (C.whoami) {
    const w = D.whoami || {};
    const tipoMap = { autonomo: 'autónomo/freelancer', pyme: 'pyme/sociedad', particular: 'particular' };
    const who = [];
    if (w.actividad) who.push(w.actividad);
    if (w.tipo) who.push('(' + (tipoMap[w.tipo] || w.tipo) + ')');
    if (who.length) bits.push('El usuario es ' + who.join(' '));
    if (w.nombre) bits.push('Se llama ' + w.nombre);
  }
  if (C.company) {
    const c = D.company || {};
    if (c.empresa || c.sector) bits.push('Trabaja en ' + [c.empresa, c.sector ? 'sector ' + c.sector : ''].filter(Boolean).join(', '));
  }
  if (C.region && D.region && D.region.ccaa) bits.push('Reside o desarrolla su actividad en ' + D.region.ccaa);
  if (C.fiscal) {
    const f = D.fiscal || {};
    const regMap = { directa: 'estimación directa', directa_simpl: 'estimación directa simplificada', modulos: 'estimación objetiva (módulos)', sociedades: 'Impuesto sobre Sociedades', recargo: 'recargo de equivalencia' };
    if (f.regimen) bits.push('Régimen fiscal: ' + (regMap[f.regimen] || f.regimen));
    if (f.iva) bits.push('IVA habitual: ' + (f.iva === 'exento' ? 'exento' : f.iva + '%'));
  }
  if (C.topics && D.topics && D.topics.temas) bits.push('Temas de interés: ' + D.topics.temas);
  if (C.goals && D.goals && D.goals.objetivos) bits.push('Objetivos: ' + D.goals.objetivos);
  if (C.preferences && D.preferences && D.preferences.estilo) {
    const stMap = { breve: 'prefiere respuestas breves y directas', detallado: 'prefiere respuestas detalladas', tecnico: 'prefiere detalle técnico y normativo' };
    bits.push(stMap[D.preferences.estilo] || '');
  }
  if (C.history) bits.push('Permite usar su historial de conversaciones para dar continuidad');

  const clean = bits.filter(Boolean);
  if (!clean.length) return '';
  let out = '[PERFIL DEL USUARIO — datos que el usuario ha consentido compartir; úsalos para personalizar tus respuestas cuando sea relevante, sin mencionarlos explícitamente salvo que pregunte]\n' + clean.join('. ') + '.';
  // Capa territorial: instrucciones según la Comunidad Autónoma consentida.
  const cc = (C.region && D.region && D.region.ccaa) ? D.region.ccaa : null;
  if (cc) {
    const foral = cc === 'País Vasco' || cc === 'Navarra';
    out += '\n[ADAPTACIÓN TERRITORIAL] Cuando una norma fiscal o jurídica varíe según la comunidad autónoma (tramos autonómicos del IRPF, impuestos cedidos, deducciones autonómicas, etc.), prioriza la normativa de ' + cc + ' y acláralo en tu respuesta.';
    if (foral) out += ' ' + cc + ' tiene RÉGIMEN FORAL propio (hacienda foral): su fiscalidad difiere sustancialmente de la estatal de territorio común; tenlo siempre en cuenta y adviértelo.';
    out += ' Recuerda que la normativa autonómica debe verificarse en la hacienda autonómica correspondiente.';
  }
  return out;
}

function lxProfileExport() {
  return JSON.stringify(lxProfileLoad(), null, 2);
}

/* ---- Flag de onboarding ---- */
function lxOnboarded() { try { return localStorage.getItem('lexly_onboarded') === '1'; } catch (e) { return false; } }
function lxSetOnboarded() { try { localStorage.setItem('lexly_onboarded', '1'); } catch (e) {} }

/* ============================================================
   PLANES Y LÍMITES DE USO
   Punto central: lxCurrentPlan() decide qué plan tiene el usuario.
   Cuando se integre Stripe, SOLO hay que cambiar esta función para
   que lea el plan del pago real. El resto del control de límites
   seguirá funcionando igual.
   ============================================================ */

const PLAN_LIMITS = {
  guest:      { chat: 15, contract: 3,        review: 1,        risks: false, hacienda: false },
  particular: { chat: Infinity, contract: 5,  review: 3,        risks: false, hacienda: false },
  autonomo:   { chat: Infinity, contract: Infinity, review: Infinity, risks: true,  hacienda: true },
  pyme:       { chat: Infinity, contract: Infinity, review: Infinity, risks: true,  hacienda: true },
};

const PLAN_LABELS = {
  guest:      { es: 'Modo invitado', ca: 'Mode convidat' },
  particular: { es: 'Plan Particular', ca: 'Pla Particular' },
  autonomo:   { es: 'Plan Autónomo', ca: 'Pla Autònom' },
  pyme:       { es: 'Plan Pyme', ca: 'Pla Pime' },
  free:       { es: 'Plan Gratis', ca: 'Pla Gratis' },
};

/* Devuelve el plan actual del usuario.
   HOY: un registrado está en 'free' (gratis) hasta que pague.
   CON STRIPE: aquí se leerá el plan pagado (particular/autonomo/pyme). */
function lxCurrentPlan(session) {
  if (!session || session.status === 'guest') return 'guest';
  // Punto de integración Stripe: sustituir por el plan real del pago.
  try {
    const paid = localStorage.getItem('lexly_plan');
    if (paid && PLAN_LIMITS[paid]) return paid;
  } catch (e) {}
  return 'free';
}

/* El plan 'free' (registrado sin pagar) usa los mismos límites que invitado
   salvo que no se le bloquean contract/review por estar registrado:
   reutilizamos los límites de invitado como plan gratuito registrado. */
function lxPlanLimits(plan) {
  if (plan === 'free') return PLAN_LIMITS.guest;
  return PLAN_LIMITS[plan] || PLAN_LIMITS.guest;
}

function lxPlanLabel(plan, lang = 'es') {
  const l = PLAN_LABELS[plan] || PLAN_LABELS.free;
  return l[lang] || l.es;
}

/* Contador de uso mensual. Se reinicia cada mes natural. */
function lxUsageKey() {
  const d = new Date();
  return `lexly_usage_${d.getFullYear()}_${d.getMonth() + 1}`;
}

function lxUsageLoad() {
  try {
    const raw = localStorage.getItem(lxUsageKey());
    if (raw) return JSON.parse(raw);
  } catch (e) {}
  return { chat: 0, contract: 0, review: 0 };
}

function lxUsagePersist(u) {
  try { localStorage.setItem(lxUsageKey(), JSON.stringify(u)); } catch (e) {}
  window.dispatchEvent(new CustomEvent('lexly-usage'));
}

/* Comprueba si una acción está permitida según el plan y el uso actual. */
function lxCanUse(session, action) {
  const plan = lxCurrentPlan(session);
  const limits = lxPlanLimits(plan);
  // Funciones premium (riesgos, hacienda): permitidas o no según el plan.
  if (action === 'risks' || action === 'hacienda') {
    return { allowed: !!limits[action], plan, limit: limits[action], used: 0, remaining: limits[action] ? Infinity : 0 };
  }
  const used = lxUsageLoad()[action] || 0;
  const limit = limits[action];
  const allowed = used < limit;
  return { allowed, plan, limit, used, remaining: limit === Infinity ? Infinity : Math.max(0, limit - used) };
}

/* Registra que se ha consumido una acción (suma 1 al contador del mes). */
function lxRegisterUse(action) {
  const u = lxUsageLoad();
  u[action] = (u[action] || 0) + 1;
  lxUsagePersist(u);
  return u;
}

function useUsage() {
  const [, force] = useState(0);
  useEffect(() => {
    const h = () => force(n => n + 1);
    window.addEventListener('lexly-usage', h);
    window.addEventListener('storage', h);
    return () => { window.removeEventListener('lexly-usage', h); window.removeEventListener('storage', h); };
  }, []);
  return lxUsageLoad();
}

Object.assign(window, {
  PLAN_LIMITS, PLAN_LABELS, lxCurrentPlan, lxPlanLimits, lxPlanLabel,
  lxUsageLoad, lxCanUse, lxRegisterUse, useUsage,
});

Object.assign(window, {
  lxLoad, lxUpsertChat, lxAddContract, lxDeleteChat, lxDeleteContract, lxClearAll,
  useHistory, lxId, lxRelDate, LIBRARY, lxNextDeadlines,
  lxFicheGet, lxFicheSet,
  PROFILE_CATEGORIES, CCAA, lxProfileLoad, lxSetConsent, lxSetProfileData,
  lxProfileDeleteCategory, lxProfileDeleteAll, useProfile, lxProfileActivityType,
  lxProfileContext, lxProfileExport,
  lxOnboarded, lxSetOnboarded,
});
