// ─── 공통 UI: 아이콘, 모달, 토스트, 사이드바, 설정 모달 ───
const { useState, useEffect, useRef, useCallback } = React;

// SVG 아이콘 (stroke 기반)
const I = {
  chat: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>,
  grid: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="7" height="9" rx="1"></rect><rect x="14" y="3" width="7" height="5" rx="1"></rect><rect x="14" y="12" width="7" height="9" rx="1"></rect><rect x="3" y="16" width="7" height="5" rx="1"></rect></svg>,
  layers: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></svg>,
  upload: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>,
  db: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path></svg>,
  bar: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="20" x2="12" y2="10"></line><line x1="18" y1="20" x2="18" y2="4"></line><line x1="6" y1="20" x2="6" y2="16"></line></svg>,
  line: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><polyline points="3 17 9 11 13 15 21 7"></polyline><polyline points="14 7 21 7 21 14"></polyline></svg>,
  pie: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M21.21 15.89A10 10 0 1 1 8 2.83"></path><path d="M22 12A10 10 0 0 0 12 2v10z"></path></svg>,
  table: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="3" y1="15" x2="21" y2="15"></line><line x1="12" y1="3" x2="12" y2="21"></line></svg>,
  plus: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>,
  x: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>,
  send: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>,
  save: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>,
  settings: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>,
  trash: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>,
  check: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>,
  more: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="1.4"></circle><circle cx="12" cy="5" r="1.4"></circle><circle cx="12" cy="19" r="1.4"></circle></svg>,
  drag: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="9" cy="6" r="1"></circle><circle cx="9" cy="12" r="1"></circle><circle cx="9" cy="18" r="1"></circle><circle cx="15" cy="6" r="1"></circle><circle cx="15" cy="12" r="1"></circle><circle cx="15" cy="18" r="1"></circle></svg>,
  sparkle: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9L12 3z"></path><path d="M19 15l.8 2.2L22 18l-2.2.8L19 21l-.8-2.2L16 18l2.2-.8L19 15z"></path></svg>,
  file: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>,
  calendar: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>,
  copy: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>,
  refresh: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><polyline points="23 4 23 10 17 10"></polyline><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path></svg>,
  alert: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>,
};

const VIEW_ICON = { bar: I.bar, line: I.line, pie: I.pie, table: I.table };

// Modal shell
function Modal({ title, onClose, children, foot, wide, icon }) {
  useEffect(() => {
    const h = (e) => e.key === 'Escape' && onClose();
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [onClose]);
  return (
    <div className="modal-scrim" onMouseDown={onClose}>
      <div className={'modal' + (wide ? ' wide' : '')} onMouseDown={(e) => e.stopPropagation()}>
        <div className="modal-head">
          {icon && <span style={{ color: 'var(--blue-600)', display: 'flex' }}>{icon}</span>}
          <h3>{title}</h3>
          <button className="x" onClick={onClose}>{I.x}</button>
        </div>
        <div className="modal-body">{children}</div>
        {foot && <div className="modal-foot">{foot}</div>}
      </div>
    </div>
  );
}

// Toast host
function useToasts() {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((msg) => {
    const id = Math.random().toString(36).slice(2);
    setToasts((t) => [...t, { id, msg }]);
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 2600);
  }, []);
  const host = (
    <div className="toast-wrap">
      {toasts.map((t) => (<div className="toast" key={t.id}>{I.check}{t.msg}</div>))}
    </div>
  );
  return [push, host];
}

// 컴포넌트 설정 모달 (조회기간/차트종류/TOP N/제목·설명/색상)
const THEME_SWATCH = { blue: '#1B5BD7', navy: '#11295E', teal: '#0E7C7B', amber: '#C97A0A' };

function SettingsModal({ comp, onClose, onSave }) {
  const [title, setTitle] = useState(comp.title);
  const [desc, setDesc] = useState(comp.desc || '');
  const [view, setView] = useState(comp.view);
  const [cfg, setCfg] = useState({ ...comp.config });
  const [period, setPeriod] = useState(cfg.periodMode || (cfg.period && cfg.period.includes('개월') ? 'recent' : 'range'));
  const isTrendOrShare = comp.kind === 'trend' || comp.kind === 'share';

  const save = () => {
    const periodLabel = period === 'recent' ? `최근 ${cfg.recentN || 6}개월` : `${cfg.from || '2026-01-01'} ~ ${cfg.to || '2026-06-25'}`;
    onSave({ ...comp, title, desc, view, config: { ...cfg, periodMode: period, period: periodLabel } });
  };

  return (
    <Modal title="컴포넌트 설정" icon={I.settings} onClose={onClose} wide
      foot={<><button className="btn btn-ghost" onClick={onClose}>취소</button><button className="btn btn-primary" onClick={save}>{I.check}저장</button></>}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0 28px' }}>
        <div>
          <div className="settings-group-title">표시 정보</div>
          <div className="field"><label>제목</label><input className="input" value={title} onChange={(e) => setTitle(e.target.value)} /></div>
          <div className="field"><label>설명</label><textarea className="input" rows="2" style={{ resize: 'vertical' }} value={desc} onChange={(e) => setDesc(e.target.value)} /></div>

          <div className="settings-group-title">View 형태</div>
          <div className="field">
            <div className="seg">
              {['bar', 'line', 'pie', 'table'].map((v) => (
                <button key={v} className={view === v ? 'active' : ''} onClick={() => setView(v)}>
                  {VIEW_ICON[v]}{({ bar: '막대', line: '선', pie: '파이', table: '표' })[v]}
                </button>
              ))}
            </div>
          </div>

          <div className="settings-group-title">색상 테마</div>
          <div className="field">
            <div className="swatches">
              {Object.entries(THEME_SWATCH).map(([k, c]) => (
                <button key={k} className={'swatch' + (cfg.theme === k ? ' active' : '')} style={{ background: c }} onClick={() => setCfg({ ...cfg, theme: k })} title={k}></button>
              ))}
            </div>
          </div>
        </div>

        <div>
          <div className="settings-group-title">데이터 조건</div>
          <div className="field">
            <label>데이터셋</label>
            <div className="ds-pill">{I.db}{comp.source}</div>
          </div>

          <div className="field">
            <label>조회 기간</label>
            <div className="seg" style={{ marginBottom: 10 }}>
              <button className={period === 'range' ? 'active' : ''} onClick={() => setPeriod('range')}>{I.calendar}기간 지정</button>
              <button className={period === 'recent' ? 'active' : ''} onClick={() => setPeriod('recent')}>최근 N개월</button>
            </div>
            {period === 'range' ? (
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <input type="date" className="input" value={cfg.from || '2026-01-01'} onChange={(e) => setCfg({ ...cfg, from: e.target.value })} />
                <span style={{ color: 'var(--ink-3)' }}>~</span>
                <input type="date" className="input" value={cfg.to || '2026-06-25'} onChange={(e) => setCfg({ ...cfg, to: e.target.value })} />
              </div>
            ) : (
              <div className="seg">
                {[3, 6, 12].map((n) => (<button key={n} className={(cfg.recentN || 6) === n ? 'active' : ''} onClick={() => setCfg({ ...cfg, recentN: n })}>{n}개월</button>))}
              </div>
            )}
          </div>

          {!isTrendOrShare && (
            <div className="field">
              <label>투자 주체</label>
              <div className="seg">
                {['ind', 'inst', 'frgn'].map((s) => (<button key={s} className={(cfg.subject || comp.subject || 'ind') === s ? 'active' : ''} onClick={() => setCfg({ ...cfg, subject: s })}>{SUBJ[s]}</button>))}
              </div>
            </div>
          )}

          <div className="field">
            <label>표시 항목 수 (TOP N)</label>
            <div className="stepper">
              <button onClick={() => setCfg({ ...cfg, topN: Math.max(3, (cfg.topN || 10) - 1) })}>−</button>
              <input value={cfg.topN || 10} onChange={(e) => setCfg({ ...cfg, topN: Math.max(3, Math.min(12, +e.target.value || 10)) })} />
              <button onClick={() => setCfg({ ...cfg, topN: Math.min(12, (cfg.topN || 10) + 1) })}>+</button>
            </div>
          </div>
        </div>
      </div>
    </Modal>
  );
}

Object.assign(window, { I, VIEW_ICON, Modal, useToasts, SettingsModal });
