// toasts-and-errors.jsx — System toast unifié + Error Boundary global
// API : window.toast.success('msg'), .error, .info, .warn
// Remplace progressivement les alert() en attendant migration complète

const { useState: _tUseS, useEffect: _tUseE } = React;

// ─── Toast container ──────────────────────────────────────────────────────
let _toastId = 0;
const _toastListeners = [];

function pushToast(toast) {
  const id = ++_toastId;
  const t = { id, ts: Date.now(), level: 'info', timeout: 5000, ...toast };
  _toastListeners.forEach(fn => fn({ type: 'add', toast: t }));
  if (t.timeout > 0) {
    setTimeout(() => _toastListeners.forEach(fn => fn({ type: 'remove', id })), t.timeout);
  }
  return id;
}

window.toast = {
  success: (msg, opts = {}) => pushToast({ level: 'success', message: msg, ...opts }),
  error:   (msg, opts = {}) => pushToast({ level: 'error',   message: msg, timeout: 8000, ...opts }),
  warn:    (msg, opts = {}) => pushToast({ level: 'warn',    message: msg, ...opts }),
  info:    (msg, opts = {}) => pushToast({ level: 'info',    message: msg, ...opts }),
  dismiss: (id) => _toastListeners.forEach(fn => fn({ type: 'remove', id })),
};

function ToastContainer() {
  const [toasts, setToasts] = _tUseS([]);
  _tUseE(() => {
    const handler = (evt) => {
      if (evt.type === 'add') setToasts(t => [...t, evt.toast]);
      else if (evt.type === 'remove') setToasts(t => t.filter(x => x.id !== evt.id));
    };
    _toastListeners.push(handler);
    return () => {
      const idx = _toastListeners.indexOf(handler);
      if (idx >= 0) _toastListeners.splice(idx, 1);
    };
  }, []);

  if (!toasts.length) return null;
  return (
    <div style={{
      position: 'fixed', bottom: 20, right: 20, zIndex: 99999,
      display: 'flex', flexDirection: 'column', gap: 8,
      maxWidth: 400, pointerEvents: 'none',
    }}>
      {toasts.map(t => <Toast key={t.id} toast={t} onClose={() => window.toast.dismiss(t.id)} />)}
    </div>
  );
}

function Toast({ toast, onClose }) {
  const meta = {
    success: { icon: '✓', bg: 'var(--signal-tint)', border: 'var(--signal-soft)', color: 'var(--signal-deep)' },
    error:   { icon: '✗', bg: 'var(--rouge-tint)',  border: 'var(--rouge)',        color: 'var(--rouge)' },
    warn:    { icon: '⚠', bg: 'var(--copper-tint)', border: 'var(--copper)',       color: 'var(--copper)' },
    info:    { icon: 'ℹ', bg: 'var(--paper-2)',     border: 'var(--line-2)',       color: 'var(--ink)' },
  }[toast.level] || { icon: 'ℹ', bg: 'var(--paper-2)', border: 'var(--line-2)', color: 'var(--ink)' };

  return (
    <div style={{
      pointerEvents: 'auto',
      padding: '12px 14px', display: 'flex', alignItems: 'flex-start', gap: 10,
      background: meta.bg, border: `1px solid ${meta.border}`, borderRadius: 8,
      color: meta.color, fontSize: 13, fontWeight: 500,
      boxShadow: 'var(--shadow-2)', minWidth: 280,
      animation: 'fade-up 200ms ease-out',
    }}>
      <span style={{ fontSize: 16, lineHeight: 1, marginTop: 1 }}>{meta.icon}</span>
      <div style={{ flex: 1, lineHeight: 1.4 }}>
        {toast.title && <div style={{ fontWeight: 700, marginBottom: 3 }}>{toast.title}</div>}
        <div>{toast.message}</div>
      </div>
      <button onClick={onClose} style={{ fontSize: 14, color: meta.color, opacity: 0.6, padding: 2, cursor: 'pointer' }}>✕</button>
    </div>
  );
}

window.ToastContainer = ToastContainer;

// ─── Confirm Modal — remplace window.confirm() ────────────────────────────
// Usage : await window.confirmModal('Êtes-vous sûr ?', { title: 'Suppression', danger: true })
//          → Promise<boolean>
let _confirmListeners = [];
window.confirmModal = function (message, opts = {}) {
  return new Promise((resolve) => {
    const config = {
      message,
      title: opts.title || 'Confirmer',
      confirmLabel: opts.confirmLabel || 'Confirmer',
      cancelLabel: opts.cancelLabel || 'Annuler',
      danger: !!opts.danger,
      icon: opts.icon || (opts.danger ? '⚠️' : '❓'),
      resolve,
    };
    _confirmListeners.forEach(fn => fn(config));
  });
};

function ConfirmModalContainer() {
  const [config, setConfig] = _tUseS(null);
  _tUseE(() => {
    const handler = (cfg) => setConfig(cfg);
    _confirmListeners.push(handler);
    return () => {
      const idx = _confirmListeners.indexOf(handler);
      if (idx >= 0) _confirmListeners.splice(idx, 1);
    };
  }, []);

  if (!config) return null;
  const close = (result) => {
    config.resolve(result);
    setConfig(null);
  };
  return (
    <div onClick={e => { if (e.target === e.currentTarget) close(false); }}
      style={{ position: 'fixed', inset: 0, zIndex: 99998, background: 'rgba(14,16,16,0.6)', display: 'grid', placeItems: 'center', backdropFilter: 'blur(3px)', padding: 16 }}>
      <div style={{ width: 'min(440px, 100%)', background: 'var(--paper)', borderRadius: 12, border: '1px solid var(--line-2)', boxShadow: 'var(--shadow-3)', padding: 24 }}>
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 14, marginBottom: 18 }}>
          <div style={{ fontSize: 32, lineHeight: 1 }}>{config.icon}</div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 16, fontWeight: 700, marginBottom: 6 }}>{config.title}</div>
            <div style={{ fontSize: 13, color: 'var(--ink-3)', lineHeight: 1.5, whiteSpace: 'pre-wrap' }}>{config.message}</div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <button onClick={() => close(false)} style={{
            padding: '8px 16px', fontSize: 13, fontWeight: 500,
            background: 'var(--paper-2)', color: 'var(--ink-2)',
            border: '1px solid var(--line-2)', borderRadius: 6, cursor: 'pointer',
          }}>{config.cancelLabel}</button>
          <button onClick={() => close(true)} autoFocus style={{
            padding: '8px 16px', fontSize: 13, fontWeight: 600,
            background: config.danger ? 'var(--rouge)' : 'var(--ink)',
            color: '#fff',
            border: 'none', borderRadius: 6, cursor: 'pointer',
          }}>{config.confirmLabel}</button>
        </div>
      </div>
    </div>
  );
}
window.ConfirmModalContainer = ConfirmModalContainer;

// ─── O1 — Patch global window.alert / window.confirm ───────────────────────
// Garde les fallbacks navigateur si toast/confirmModal pas dispo.
// Override fait que tout le code legacy (18 fichiers) bénéficie automatiquement
// du nouveau design sans réécriture.
(function patchNativeDialogs() {
  const _origAlert = window.alert.bind(window);
  const _origConfirm = window.confirm.bind(window);

  window.alert = function (msg) {
    if (window.toast) {
      const text = String(msg || '');
      const isError = /erreur|échec|impossible|fail|denied|refusé/i.test(text) || text.startsWith('⚠') || text.startsWith('✗');
      const isSuccess = text.startsWith('✓') || /succès|réussi|enregistré|créé|ok/i.test(text);
      if (isError) window.toast.error(text);
      else if (isSuccess) window.toast.success(text);
      else window.toast.info(text);
      return undefined;
    }
    return _origAlert(msg);
  };

  // Note : window.confirm est synchrone en natif. On ne peut pas le rendre async
  // sans casser les call sites. On garde le natif mais on expose
  // window.confirmModal (Promise) pour les nouveaux call sites.
  // Les anciens utilisent toujours window.confirm (popup natif) — acceptable.
  window.confirmModal = window.confirmModal; // déjà défini plus haut
})();

// ─── Error Boundary ───────────────────────────────────────────────────────
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null, errorInfo: null };
  }
  static getDerivedStateFromError(error) { return { error }; }
  componentDidCatch(error, errorInfo) {
    console.error('[ErrorBoundary]', error, errorInfo);
    this.setState({ errorInfo });
    // Notifie via toast aussi
    if (window.toast) window.toast.error(`Erreur module : ${error.message}`, { title: 'Une erreur est survenue' });
  }
  render() {
    if (this.state.error) {
      return (
        <div style={{ padding: 32, textAlign: 'center', background: 'var(--paper)', minHeight: '100vh' }}>
          <div style={{ fontSize: 48, marginBottom: 16 }}>⚠️</div>
          <div style={{ fontSize: 20, fontWeight: 700, marginBottom: 8 }}>Erreur dans ce module</div>
          <div style={{ fontSize: 13, color: 'var(--ink-3)', marginBottom: 14, maxWidth: 480, margin: '0 auto 14px' }}>
            Un problème est survenu lors de l'affichage. Les autres modules continuent de fonctionner — vous pouvez naviguer ailleurs ou recharger la page.
          </div>
          <details style={{ marginBottom: 16, fontSize: 11, color: 'var(--ink-4)', maxWidth: 600, margin: '0 auto 16px', textAlign: 'left' }}>
            <summary style={{ cursor: 'pointer', padding: 8, background: 'var(--paper-2)', borderRadius: 4 }}>Détails techniques</summary>
            <pre style={{ padding: 12, background: 'var(--paper-2)', borderRadius: 4, overflow: 'auto', fontSize: 10, marginTop: 8 }}>
              {this.state.error.toString()}
              {this.state.errorInfo && '\n\n' + this.state.errorInfo.componentStack}
            </pre>
          </details>
          <button onClick={() => this.setState({ error: null, errorInfo: null })}
            style={{ padding: '8px 20px', fontSize: 13, background: 'var(--ink)', color: 'var(--paper)', border: 'none', borderRadius: 6, cursor: 'pointer', marginRight: 8 }}>
            🔄 Réessayer
          </button>
          <button onClick={() => window.location.reload()}
            style={{ padding: '8px 20px', fontSize: 13, background: 'var(--paper-2)', color: 'var(--ink)', border: '1px solid var(--line-2)', borderRadius: 6, cursor: 'pointer' }}>
            🔄 Recharger la page
          </button>
        </div>
      );
    }
    return this.props.children;
  }
}
window.ErrorBoundary = ErrorBoundary;
