// ─── Dashboard — customizable widget grid ───────────────────────────────────
// Cada widget se redimensiona arrastrando: borde derecho (ancho), borde
// inferior (alto), esquina inf-derecha (diagonal). Snap a columnas para el
// ancho; alto libre en px. Persistencia v3: { layout: [ids], sizes: { [id]: { span, h } } }.

const LS_KEY      = 'lanven.dashboard.layout.v3';
const LS_KEY_V2   = 'lanven.dashboard.layout.v2';
const LS_KEY_V1   = 'lanven.dashboard.layout.v1';

const MIN_SPAN   = 2;
const MAX_SPAN   = 12;
const MIN_HEIGHT = 110;   // los KPIs más chicos rondan los 130px
const MAX_HEIGHT = 900;

function loadLayout() {
  try {
    // v3 — formato actual: sizes[id] = { span?, h? }
    const raw3 = localStorage.getItem(LS_KEY);
    if (raw3) {
      const obj = JSON.parse(raw3);
      if (obj && Array.isArray(obj.layout) && obj.layout.every(id => WIDGETS_BY_ID[id])) {
        return { layout: obj.layout, sizes: obj.sizes && typeof obj.sizes === 'object' ? obj.sizes : {} };
      }
    }
    // v2 — sizes[id] = number (col-span). Migrar a { span: n }
    const raw2 = localStorage.getItem(LS_KEY_V2);
    if (raw2) {
      const obj = JSON.parse(raw2);
      if (obj && Array.isArray(obj.layout) && obj.layout.every(id => WIDGETS_BY_ID[id])) {
        const migrated = {};
        if (obj.sizes) for (const id in obj.sizes) {
          const v = obj.sizes[id];
          if (typeof v === 'number') migrated[id] = { span: v };
          else if (v && typeof v === 'object') migrated[id] = v;
        }
        return { layout: obj.layout, sizes: migrated };
      }
    }
    // v1 — array de ids
    const raw1 = localStorage.getItem(LS_KEY_V1);
    if (raw1) {
      const arr = JSON.parse(raw1);
      if (Array.isArray(arr) && arr.every(id => WIDGETS_BY_ID[id])) return { layout: arr, sizes: {} };
    }
  } catch (e) {}
  return { layout: [...DEFAULT_LAYOUT], sizes: {} };
}

function saveLayout(state) {
  try { localStorage.setItem(LS_KEY, JSON.stringify(state)); } catch (e) {}
}

function Dashboard() {
  const [cur, setCur] = useState('ARS');
  const initial = useMemo(loadLayout, []);
  const [layout, setLayout] = useState(initial.layout);
  const [sizes,  setSizes]  = useState(initial.sizes);  // { [id]: { span?, h? } }
  const [editing, setEditing] = useState(false);
  const [panelOpen, setPanelOpen] = useState(false);
  const [dragId, setDragId] = useState(null);
  const [resizing, setResizing] = useState(null);  // { id, dir }
  const gridRef = useRef(null);
  const { kpis: liveKpis, cajas: liveCajas } = useLiveDashboardData();

  useEffect(() => { saveLayout({ layout, sizes }); }, [layout, sizes]);

  const removeWidget = (id) => setLayout(l => l.filter(x => x !== id));
  const addWidget = (id) => setLayout(l => {
    if (l.includes(id)) return l;
    const idx = DEFAULT_LAYOUT.indexOf(id);
    if (idx < 0) return [...l, id];
    const next = [...l];
    let pos = next.length;
    for (let i = 0; i < next.length; i++) {
      const di = DEFAULT_LAYOUT.indexOf(next[i]);
      if (di > idx || di < 0) { pos = i; break; }
    }
    next.splice(pos, 0, id);
    return next;
  });
  const resetLayout = () => { setLayout([...DEFAULT_LAYOUT]); setSizes({}); };
  const resetSize = (id) => setSizes(s => { const n = { ...s }; delete n[id]; return n; });
  const updateSize = (id, patch) => setSizes(s => ({ ...s, [id]: { ...(s[id] || {}), ...patch } }));

  // ── Drag-to-resize ─────────────────────────────────────────────────────
  // dir: 'x' (borde derecho), 'y' (borde inferior), 'xy' (esquina diagonal)
  const beginResize = (id, dir, e) => {
    e.preventDefault();
    e.stopPropagation();
    const grid = gridRef.current;
    if (!grid) return;

    const widgetEl = e.currentTarget.closest('[data-widget-id]');
    const widgetRect = widgetEl.getBoundingClientRect();
    const gridRect = grid.getBoundingClientRect();
    const gap = parseFloat(getComputedStyle(grid).columnGap) || 16;
    const colUnit = (gridRect.width + gap) / 12;
    const widgetLeftCol = Math.round((widgetRect.left - gridRect.left) / colUnit);
    const startHeight = widgetRect.height;
    const startClientY = e.clientY;

    setResizing({ id, dir });
    document.body.style.cursor = dir === 'x' ? 'ew-resize' : dir === 'y' ? 'ns-resize' : 'nwse-resize';
    document.body.style.userSelect = 'none';

    const onMove = (ev) => {
      const patch = {};
      if (dir === 'x' || dir === 'xy') {
        const newRight = ev.clientX - gridRect.left;
        let newSpan = Math.round(newRight / colUnit) - widgetLeftCol;
        newSpan = Math.max(MIN_SPAN, Math.min(MAX_SPAN - widgetLeftCol, newSpan));
        patch.span = newSpan;
      }
      if (dir === 'y' || dir === 'xy') {
        const dy = ev.clientY - startClientY;
        let newH = Math.round((startHeight + dy) / 10) * 10;  // snap a 10px
        newH = Math.max(MIN_HEIGHT, Math.min(MAX_HEIGHT, newH));
        patch.h = newH;
      }
      setSizes(s => {
        const cur = s[id] || {};
        const merged = { ...cur, ...patch };
        if (merged.span === cur.span && merged.h === cur.h) return s;
        return { ...s, [id]: merged };
      });
    };
    const onUp = () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup', onUp);
      document.body.style.cursor = '';
      document.body.style.userSelect = '';
      setResizing(null);
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
  };

  // Drag-to-reorder
  const onDragOver = (e, overId) => {
    e.preventDefault();
    if (!dragId || dragId === overId) return;
    setLayout(l => {
      const from = l.indexOf(dragId), to = l.indexOf(overId);
      if (from < 0 || to < 0) return l;
      const next = [...l];
      next.splice(from, 1);
      next.splice(to, 0, dragId);
      return next;
    });
  };

  const customCount = Object.keys(sizes).filter(id => {
    const s = sizes[id]; if (!s) return false;
    const w = WIDGETS_BY_ID[id]; if (!w) return false;
    return (s.span && s.span !== w.span) || s.h != null;
  }).length;

  return (
    <div className="fade-in">
      <PageHeader
        crumbs={['Inicio', 'Dashboard']}
        title="Buen día, Sofía."
        sub={editing
          ? `Modo edición · arrastrá los bordes para redimensionar (↔ ancho, ↕ alto, ⤡ diagonal) · arrastrá el centro para mover · × para quitar${customCount ? ` · ${customCount} personalizados` : ''}`
          : `Resumen operacional · mayo 2026 · ${layout.length} widgets activos`}
        actions={
          <>
            <CurrencyToggle value={cur} onChange={setCur} />
            <Button variant="outline" size="md" icon={<I.Settings size={14} />} onClick={() => { setEditing(e => !e); setPanelOpen(p => !p || !editing); }}>
              {editing ? 'Terminar' : 'Personalizar'}
            </Button>
            {!editing && <Button variant="primary" size="md" icon={<I.Plus size={14} sw={2} />}>Nueva operación</Button>}
          </>
        }
      />

      {/* Grid */}
      <div ref={gridRef}
        className={`grid grid-cols-12 gap-4 items-start ${panelOpen ? 'pr-[336px] transition-[padding] duration-200' : 'transition-[padding] duration-200'}`}>
        {layout.length === 0 && (
          <div className="col-span-12 border-2 border-dashed border-slate-200 rounded-md py-20 flex flex-col items-center text-center">
            <div className="text-[13px] font-semibold text-ink">Dashboard vacío</div>
            <div className="text-[12px] text-slate-500 mt-1">Agregá widgets desde el panel de la derecha o restablecé el layout por defecto.</div>
            <div className="mt-4 flex items-center gap-2">
              <Button variant="outline" size="md" onClick={resetLayout}>Restablecer layout</Button>
              {!panelOpen && <Button variant="primary" size="md" icon={<I.Plus size={14} sw={2} />} onClick={() => { setEditing(true); setPanelOpen(true); }}>Agregar widgets</Button>}
            </div>
          </div>
        )}
        {layout.map(id => {
          const w = WIDGETS_BY_ID[id];
          if (!w) return null;
          const s = sizes[id] || {};
          const span = s.span || w.span;
          const height = s.h;
          const isCustomW = s.span && s.span !== w.span;
          const isCustomH = s.h != null;
          const isResizing = resizing?.id === id;
          return (
            <div key={id}
              data-widget-id={id}
              draggable={editing && !isResizing}
              onDragStart={() => setDragId(id)}
              onDragEnd={() => setDragId(null)}
              onDragOver={(e) => onDragOver(e, id)}
              className={`relative flex flex-col ${editing && !isResizing ? 'cursor-grab active:cursor-grabbing' : ''} ${dragId === id ? 'opacity-40' : ''} ${isResizing ? 'z-20' : ''}`}
              style={{
                gridColumn: `span ${span} / span ${span}`,
                height: height ? `${height}px` : undefined,
                ...(editing ? { outline: isResizing ? '2px solid #C9A961' : '1px dashed #C9A961', outlineOffset: '2px', borderRadius: '6px' } : null),
                transition: isResizing ? 'none' : 'outline 120ms',
              }}>
              {/* Wrapper que estira al contenido al alto disponible */}
              <div className="flex-1 min-h-0 [&>*]:h-full">
                {w.render({ cur, kpis: liveKpis || KPIS, cajas: liveCajas || CAJAS })}
              </div>

              {editing && (
                <>
                  {/* Etiqueta + dimensiones actuales */}
                  <div className="absolute top-2 left-2 inline-flex items-center gap-1.5 px-1.5 py-0.5 rounded bg-white/95 backdrop-blur text-[9px] uppercase tracking-[0.1em] text-slate-500 font-medium border border-slate-100 z-10 pointer-events-none">
                    <span>⋮⋮</span>
                    <span>{w.title}</span>
                    <span className="font-mono tracking-normal normal-case" style={isCustomW ? { color: '#A88A47' } : null}>· {span}/12</span>
                    {isCustomH && (
                      <span className="font-mono tracking-normal normal-case" style={{ color: '#A88A47' }}>· {height}px</span>
                    )}
                    {(isCustomW || isCustomH) && (
                      <button onClick={(e) => { e.stopPropagation(); resetSize(id); }}
                        title="Volver al tamaño por defecto"
                        className="pointer-events-auto ml-0.5 w-3.5 h-3.5 inline-flex items-center justify-center rounded-full text-slate-400 hover:text-slate-700">
                        <I.X size={8} sw={2.5} />
                      </button>
                    )}
                  </div>

                  {/* Borde derecho — drag horizontal */}
                  <div
                    onMouseDown={(e) => beginResize(id, 'x', e)}
                    onDragStart={(e) => e.preventDefault()}
                    title="Arrastrar para cambiar ancho"
                    className="absolute top-2 bottom-2 -right-1 w-2 z-10 group flex items-center justify-center"
                    style={{ cursor: 'ew-resize' }}>
                    <span className={`block w-[3px] rounded-full transition-all ${isResizing && resizing?.dir !== 'y' ? 'h-12 bg-gold' : 'h-8 bg-slate-300 opacity-0 group-hover:opacity-100'}`} />
                  </div>

                  {/* Borde inferior — drag vertical */}
                  <div
                    onMouseDown={(e) => beginResize(id, 'y', e)}
                    onDragStart={(e) => e.preventDefault()}
                    title="Arrastrar para cambiar alto"
                    className="absolute left-3 right-3 -bottom-1 h-2 z-10 group flex items-center justify-center"
                    style={{ cursor: 'ns-resize' }}>
                    <span className={`block h-[3px] rounded-full transition-all ${isResizing && resizing?.dir === 'y' ? 'w-12 bg-gold' : 'w-8 bg-slate-300 opacity-0 group-hover:opacity-100'}`} />
                  </div>

                  {/* Esquina inf-derecha — drag diagonal */}
                  <div
                    onMouseDown={(e) => beginResize(id, 'xy', e)}
                    onDragStart={(e) => e.preventDefault()}
                    title="Arrastrar para redimensionar diagonalmente"
                    className="absolute -bottom-1 -right-1 w-5 h-5 z-20 flex items-end justify-end pr-0.5 pb-0.5"
                    style={{ cursor: 'nwse-resize' }}>
                    <svg width="11" height="11" viewBox="0 0 11 11" className={`transition-opacity ${isResizing && resizing?.dir === 'xy' ? 'opacity-100' : 'opacity-50 hover:opacity-100'}`}>
                      <path d="M 10 2 L 2 10 M 10 6 L 6 10" stroke={isResizing && resizing?.dir === 'xy' ? '#C9A961' : '#8A9AA5'} strokeWidth="1.4" strokeLinecap="round" />
                    </svg>
                  </div>

                  {/* Quitar */}
                  <button
                    onClick={(e) => { e.stopPropagation(); removeWidget(id); }}
                    className="absolute -top-2 -right-2 w-6 h-6 rounded-full bg-white border border-slate-200 text-slate-500 hover:bg-rose-50 hover:border-rose-300 hover:text-rose-700 shadow-card inline-flex items-center justify-center z-10"
                    title="Quitar widget">
                    <I.X size={12} sw={2.5} />
                  </button>
                </>
              )}
            </div>
          );
        })}
      </div>

      {panelOpen && (
        <CustomizePanel
          layout={layout}
          sizes={sizes}
          onAdd={addWidget}
          onRemove={removeWidget}
          onReset={resetLayout}
          onResetSize={resetSize}
          onClose={() => { setPanelOpen(false); setEditing(false); }}
        />
      )}
    </div>
  );
}

function CustomizePanel({ layout, sizes, onAdd, onRemove, onReset, onResetSize, onClose }) {
  const grouped = useMemo(() => {
    const m = {};
    WIDGETS.forEach(w => { (m[w.group] ||= []).push(w); });
    return m;
  }, []);
  const active = new Set(layout);

  return (
    <aside className="fixed top-[64px] right-0 bottom-0 w-[320px] bg-white border-l border-slate-200 shadow-pop flex flex-col z-20 fade-in">
      <div className="px-5 pt-5 pb-4 border-b border-slate-100">
        <div className="flex items-start justify-between">
          <div>
            <div className="text-[10px] uppercase tracking-[0.14em] text-slate-400 font-medium">Personalizar</div>
            <h3 className="font-serif text-[22px] text-ink leading-tight mt-1">Catálogo de widgets</h3>
          </div>
          <button onClick={onClose} className="p-1 -mr-1 rounded hover:bg-slate-100 text-slate-500"><I.X size={16} /></button>
        </div>
        <p className="text-[11.5px] text-slate-500 mt-2 leading-snug">
          Tildá widgets para agregar. En el dashboard, arrastrá los bordes o la esquina inf-derecha para redimensionar libremente.
        </p>
      </div>

      <div className="flex-1 overflow-y-auto">
        {Object.entries(grouped).map(([group, items]) => (
          <div key={group} className="border-b border-slate-100 last:border-0">
            <div className="px-5 pt-4 pb-2 text-[10px] uppercase tracking-[0.14em] text-slate-400 font-semibold sticky top-0 bg-white/95 backdrop-blur z-10">{group}</div>
            <ul className="pb-2">
              {items.map(w => {
                const isActive = active.has(w.id);
                const s = sizes[w.id] || {};
                const currentSpan = s.span || w.span;
                const currentH    = s.h;
                const isCustom = isActive && ((s.span && s.span !== w.span) || s.h != null);
                const toggle = () => isActive ? onRemove(w.id) : onAdd(w.id);
                return (
                  <li key={w.id} className={isActive ? 'bg-canvas/60' : ''}>
                    <button
                      type="button"
                      onClick={toggle}
                      className="w-full text-left px-5 py-2 flex items-start gap-3 hover:bg-canvas transition-colors">
                      <span
                        className={`mt-0.5 w-4 h-4 rounded border flex-shrink-0 flex items-center justify-center transition-colors ${isActive ? 'bg-slate-700 border-slate-700 text-white' : 'border-slate-300 bg-white'}`}>
                        {isActive && <I.Check size={10} sw={3} />}
                      </span>
                      <span className="flex-1 min-w-0">
                        <span className="flex items-center justify-between gap-2">
                          <span className="text-[12.5px] text-ink font-medium leading-tight">{w.title}</span>
                          <span className="text-[9px] font-mono text-slate-400">
                            {isActive ? `${currentSpan}/12${currentH ? ` · ${currentH}px` : ''}` : 'inactivo'}
                          </span>
                        </span>
                        {w.desc && <span className="block text-[11px] text-slate-500 mt-0.5 leading-snug">{w.desc}</span>}
                        {isCustom && (
                          <span
                            role="button"
                            tabIndex={0}
                            onClick={(e) => { e.stopPropagation(); onResetSize(w.id); }}
                            className="inline-flex items-center gap-1 mt-1 text-[10px] text-slate-500 hover:text-ink cursor-pointer">
                            ↺ tamaño por defecto ({w.span}/12)
                          </span>
                        )}
                      </span>
                    </button>
                  </li>
                );
              })}
            </ul>
          </div>
        ))}
      </div>

      <div className="px-5 py-4 border-t border-slate-100 bg-canvas flex items-center gap-2">
        <button onClick={onReset} className="text-[11.5px] text-slate-600 hover:text-ink font-medium">Restablecer</button>
        <div className="flex-1" />
        <span className="text-[10px] text-slate-400 font-mono">{layout.length} activos · {WIDGETS.length - layout.length} disponibles</span>
      </div>
    </aside>
  );
}

window.Dashboard = Dashboard;
