/* global React, window, Icon */
// ──────────────────────────────────────────────────────────────────────────
// App-wide Dialog + Toast system. Replaces the browser-native confirm() /
// alert() / prompt() popups (which show "Claude" as the page title and don't
// match the dark/coral design).
//
// Public API — Promise-based so call-sites can `await` them naturally:
//   window.appConfirm({ title, message, confirmText, cancelText, danger })  → Promise<bool>
//   window.appAlert({ title, message, tone })                                → Promise<void>
//   window.appPrompt({ title, message, placeholder, secret, defaultValue })  → Promise<string|null>
//   window.appSelect({ title, message, options: [{value, label, sub}] })     → Promise<value|null>
//   window.appToast(message, opts?)                                          → void  (auto-dismiss)
//
// Mount <DialogHost/> once at the App root — it subscribes to the queue and
// renders the currently-open dialog plus any toasts.
// ──────────────────────────────────────────────────────────────────────────

const { useState: useStateDlg, useEffect: useEffectDlg, useRef: useRefDlg } = React;

// ── pub-sub queue ────────────────────────────────────────────────────────
const _dialogSubs = new Set();
let _currentDialog = null;
const _toastSubs = new Set();
let _toasts = [];
let _toastSeq = 1;

function _emitDialog() { for (const fn of _dialogSubs) fn(_currentDialog); }
function _emitToasts() { for (const fn of _toastSubs) fn(_toasts); }

function _openDialog(spec) {
  return new Promise((resolve) => {
    _currentDialog = { ...spec, _resolve: resolve };
    _emitDialog();
  });
}
function _closeDialog(value) {
  const d = _currentDialog;
  _currentDialog = null;
  _emitDialog();
  if (d && d._resolve) d._resolve(value);
}

// ── Public helpers ───────────────────────────────────────────────────────
window.appConfirm = (opts = {}) => _openDialog({ kind: 'confirm', ...opts });
window.appAlert   = (opts = {}) => _openDialog({ kind: 'alert', ...opts });
window.appPrompt  = (opts = {}) => _openDialog({ kind: 'prompt', ...opts });
window.appSelect  = (opts = {}) => _openDialog({ kind: 'select', ...opts });

window.appToast = (message, opts = {}) => {
  const id = _toastSeq++;
  const tone = opts.tone || 'info';
  const duration = opts.duration ?? (tone === 'error' ? 4500 : 2800);
  _toasts = [..._toasts, { id, message, tone, duration }];
  _emitToasts();
  setTimeout(() => {
    _toasts = _toasts.filter((t) => t.id !== id);
    _emitToasts();
  }, duration);
};

// ── DialogHost — render the active dialog + toasts ───────────────────────
function DialogHost() {
  const [dialog, setDialog] = useStateDlg(_currentDialog);
  const [toasts, setToasts] = useStateDlg(_toasts);
  useEffectDlg(() => {
    _dialogSubs.add(setDialog);
    _toastSubs.add(setToasts);
    return () => {
      _dialogSubs.delete(setDialog);
      _toastSubs.delete(setToasts);
    };
  }, []);

  return (
    <>
      {dialog && <DialogModal key={dialog._resolve} dialog={dialog} onClose={_closeDialog}/>}
      <ToastStack toasts={toasts}/>
    </>
  );
}

// ── Modal ────────────────────────────────────────────────────────────────
function DialogModal({ dialog, onClose }) {
  const inputRef = useRefDlg(null);
  const [val, setVal] = useStateDlg(dialog.defaultValue || '');
  // Focus first interactive element on open
  useEffectDlg(() => {
    const id = setTimeout(() => { inputRef.current?.focus(); }, 60);
    return () => clearTimeout(id);
  }, []);
  // ESC = cancel, Enter = confirm
  useEffectDlg(() => {
    const onKey = (e) => {
      if (e.key === 'Escape') {
        e.preventDefault();
        onClose(dialog.kind === 'confirm' ? false : dialog.kind === 'alert' ? undefined : null);
      } else if (e.key === 'Enter' && (e.target.tagName !== 'TEXTAREA')) {
        if (dialog.kind === 'confirm') { e.preventDefault(); onClose(true); }
        else if (dialog.kind === 'alert') { e.preventDefault(); onClose(); }
        else if (dialog.kind === 'prompt') { e.preventDefault(); onClose(val); }
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [dialog, val]);

  const danger = !!dialog.danger;
  const tone = dialog.tone || (danger ? 'danger' : 'info');
  const accentColor =
    tone === 'danger'  ? '#DC2626' :
    tone === 'success' ? '#10B981' :
    tone === 'warning' ? '#F59E0B' :
    'var(--primary, #6366F1)';
  const accentSoft =
    tone === 'danger'  ? 'rgba(220,38,38,0.10)' :
    tone === 'success' ? 'rgba(16,185,129,0.10)' :
    tone === 'warning' ? 'rgba(245,158,11,0.10)' :
    'rgba(99,102,241,0.10)';
  const iconName =
    tone === 'danger'  ? 'trash' :
    tone === 'success' ? 'check' :
    tone === 'warning' ? 'bell' :
    'badge';

  const titleText = dialog.title || (
    dialog.kind === 'confirm' ? 'ยืนยันการดำเนินการ' :
    dialog.kind === 'alert'   ? 'แจ้งเตือน' :
    dialog.kind === 'prompt'  ? 'กรอกข้อมูล' :
    dialog.kind === 'select'  ? 'เลือกตัวเลือก' :
    'แจ้งเตือน'
  );

  return (
    <div
      role="dialog"
      aria-modal="true"
      onClick={() => onClose(dialog.kind === 'confirm' ? false : dialog.kind === 'alert' ? undefined : null)}
      style={{
        position: 'fixed', inset: 0, zIndex: 200,
        background: 'rgba(15,14,20,0.55)',
        backdropFilter: 'blur(8px)',
        display: 'grid', placeItems: 'center',
        padding: 20,
        animation: 'dlg-fade 160ms ease',
      }}
    >
      <div
        onClick={(e) => e.stopPropagation()}
        style={{
          width: '100%', maxWidth: dialog.kind === 'select' ? 480 : 440,
          background: 'var(--surface, #fff)',
          borderRadius: 18,
          boxShadow: '0 20px 60px rgba(15,14,20,0.40)',
          overflow: 'hidden',
          animation: 'dlg-pop 220ms cubic-bezier(0.4, 1.4, 0.5, 1)',
        }}
      >
        {/* Header — icon + title */}
        <div style={{padding: '20px 22px 12px', display: 'flex', gap: 14, alignItems: 'flex-start'}}>
          <div style={{
            width: 42, height: 42, borderRadius: 12,
            background: accentSoft, color: accentColor,
            display: 'grid', placeItems: 'center', flexShrink: 0,
          }}>
            <Icon name={iconName} size={20}/>
          </div>
          <div style={{flex: 1, minWidth: 0, paddingTop: 4}}>
            <div className="h2" style={{fontSize: 16.5, lineHeight: 1.35, margin: 0}}>
              {titleText}
            </div>
            {dialog.message && (
              <div style={{
                fontSize: 13.5, color: 'var(--ink-3, #64748B)',
                marginTop: 6, lineHeight: 1.55, whiteSpace: 'pre-wrap',
              }}>
                {dialog.message}
              </div>
            )}
          </div>
        </div>

        {/* Body — input / options */}
        {dialog.kind === 'prompt' && (
          <div style={{padding: '6px 22px 4px'}}>
            <input
              ref={inputRef}
              className="input"
              type={dialog.secret ? 'password' : 'text'}
              value={val}
              onChange={(e) => setVal(e.target.value)}
              placeholder={dialog.placeholder || ''}
              style={{width: '100%', padding: '10px 14px', fontSize: 14, borderRadius: 10}}
            />
          </div>
        )}

        {dialog.kind === 'select' && (
          <div className="col scroll-thin" style={{
            padding: '4px 14px 6px', gap: 6, maxHeight: 380, overflowY: 'auto',
          }}>
            {(dialog.options || []).map((opt) => (
              <button
                key={String(opt.value)}
                type="button"
                onClick={() => onClose(opt.value)}
                style={{
                  textAlign: 'left',
                  padding: '11px 14px',
                  borderRadius: 12,
                  background: 'var(--surface-2, #F3F4F6)',
                  border: '1.5px solid transparent',
                  cursor: 'pointer',
                  fontSize: 13.5,
                  display: 'flex', alignItems: 'center', gap: 10,
                  transition: 'all 120ms',
                }}
                onMouseEnter={(e) => {
                  e.currentTarget.style.background = accentSoft;
                  e.currentTarget.style.borderColor = accentColor;
                }}
                onMouseLeave={(e) => {
                  e.currentTarget.style.background = 'var(--surface-2, #F3F4F6)';
                  e.currentTarget.style.borderColor = 'transparent';
                }}
              >
                <div style={{flex: 1, minWidth: 0}}>
                  <div style={{fontWeight: 600}}>{opt.label}</div>
                  {opt.sub && (
                    <div className="muted" style={{fontSize: 11.5, marginTop: 2}}>{opt.sub}</div>
                  )}
                </div>
                <Icon name="chevron-right" size={14}/>
              </button>
            ))}
          </div>
        )}

        {/* Footer — buttons */}
        <div className="row" style={{
          justifyContent: 'flex-end',
          gap: 8, padding: '14px 22px 20px',
          borderTop: dialog.kind === 'select' ? '1px solid var(--line, #E5E7EB)' : 'none',
          marginTop: dialog.kind === 'select' ? 6 : 0,
        }}>
          {dialog.kind !== 'alert' && (
            <button
              type="button"
              onClick={() => onClose(dialog.kind === 'confirm' ? false : null)}
              className="btn btn-ghost btn-sm"
              style={{padding: '8px 18px', fontWeight: 600}}
            >
              {dialog.cancelText || 'ยกเลิก'}
            </button>
          )}
          {dialog.kind === 'confirm' && (
            <button
              type="button"
              onClick={() => onClose(true)}
              className="btn btn-sm"
              style={{
                padding: '8px 20px',
                background: accentColor,
                color: '#fff',
                fontWeight: 700,
                border: 'none',
              }}
            >
              {dialog.confirmText || (danger ? 'ลบ' : 'ตกลง')}
            </button>
          )}
          {dialog.kind === 'prompt' && (
            <button
              type="button"
              onClick={() => onClose(val)}
              className="btn btn-sm"
              disabled={dialog.required && !val.trim()}
              style={{
                padding: '8px 20px',
                background: accentColor,
                color: '#fff',
                fontWeight: 700,
                border: 'none',
                opacity: (dialog.required && !val.trim()) ? 0.5 : 1,
              }}
            >
              {dialog.confirmText || 'ยืนยัน'}
            </button>
          )}
          {dialog.kind === 'alert' && (
            <button
              type="button"
              onClick={() => onClose()}
              className="btn btn-sm"
              style={{
                padding: '8px 22px',
                background: accentColor,
                color: '#fff',
                fontWeight: 700,
                border: 'none',
              }}
            >
              {dialog.confirmText || 'รับทราบ'}
            </button>
          )}
        </div>
      </div>

      <style>{`
        @keyframes dlg-fade { from {opacity: 0;} to {opacity: 1;} }
        @keyframes dlg-pop {
          from { opacity: 0; transform: translateY(8px) scale(0.96); }
          to { opacity: 1; transform: translateY(0) scale(1); }
        }
      `}</style>
    </div>
  );
}

// ── Toasts (slide-up corner notifications) ───────────────────────────────
function ToastStack({ toasts }) {
  if (!toasts.length) return null;
  return (
    <div style={{
      position: 'fixed', bottom: 24, right: 24, zIndex: 250,
      display: 'flex', flexDirection: 'column', gap: 10,
      pointerEvents: 'none',
    }}>
      {toasts.map((t) => <ToastItem key={t.id} toast={t}/>)}
    </div>
  );
}

function ToastItem({ toast }) {
  const tone = toast.tone || 'info';
  const accent =
    tone === 'success' ? '#10B981' :
    tone === 'error'   ? '#DC2626' :
    tone === 'warning' ? '#F59E0B' :
    'var(--primary, #6366F1)';
  const bg =
    tone === 'success' ? 'rgba(16,185,129,0.12)' :
    tone === 'error'   ? 'rgba(220,38,38,0.10)' :
    tone === 'warning' ? 'rgba(245,158,11,0.12)' :
    'rgba(99,102,241,0.10)';
  const iconName =
    tone === 'success' ? 'check' :
    tone === 'error'   ? 'x' :
    tone === 'warning' ? 'bell' :
    'badge';

  return (
    <div style={{
      display: 'flex', gap: 10, alignItems: 'center',
      padding: '12px 16px',
      background: 'var(--surface, #fff)',
      border: `1.5px solid ${accent}`,
      borderRadius: 12,
      boxShadow: '0 8px 24px rgba(15,14,20,0.18)',
      minWidth: 240, maxWidth: 420,
      pointerEvents: 'auto',
      animation: 'toast-in 280ms cubic-bezier(0.4, 1.5, 0.5, 1)',
    }}>
      <div style={{
        width: 24, height: 24, borderRadius: 6,
        background: bg, color: accent,
        display: 'grid', placeItems: 'center', flexShrink: 0,
      }}>
        <Icon name={iconName} size={13}/>
      </div>
      <div style={{flex: 1, fontSize: 13, fontWeight: 500, color: 'var(--ink, #0F172A)'}}>
        {toast.message}
      </div>
      <style>{`
        @keyframes toast-in {
          from { opacity: 0; transform: translateX(20px); }
          to { opacity: 1; transform: translateX(0); }
        }
      `}</style>
    </div>
  );
}

window.DialogHost = DialogHost;
