/* global React, TOOLS, TOOL_BY_ID, useI18n, useTheme, useHistory, useHashRoute, navigate, Icon, formatRelativeTime, clearHistory */
/* ============================================================
   shell.jsx — App shell (top bar, breadcrumbs) + Hub page
   ============================================================ */

const { useState: useState_S, useEffect: useEffect_S, useMemo: useMemo_S } = React;

// ---------- TopBar ----------
function TopBar({ tweaks, setTweaks }) {
  const { lang, setLang, t } = useI18n();
  const { theme, toggle } = useTheme();
  const route = useHashRoute();

  let crumbs = null;
  if (route.name === 'tool') {
    const tool = TOOL_BY_ID[route.toolId];
    crumbs = (
      <div className="crumbs">
        <a className="crumb" onClick={(e) => { e.preventDefault(); navigate(''); }} href="#/">{t('crumb_hub')}</a>
        <span className="sep">{t('crumb_sep')}</span>
        <span className="crumb current">{tool ? t(tool.nameKey) : ''}</span>
      </div>
    );
  } else {
    crumbs = (
      <div className="crumbs">
        <span className="crumb current">{t('crumb_hub')}</span>
      </div>
    );
  }

  return (
    <header className="top">
      <a className="brand" onClick={(e) => { e.preventDefault(); navigate(''); }} href="#/">
        <div className="brand-mark">C↓</div>
        <div>
          <div className="brand-text-main">{t('brand')}</div>
          <div className="brand-text-sub">{t('brand_sub')}</div>
        </div>
      </a>
      {crumbs}
      <div className="top-actions">
        <button
          className="lang-toggle"
          onClick={() => setLang(lang === 'zh' ? 'en' : 'zh')}
          title="Toggle language"
        >
          {lang === 'zh' ? 'EN' : '中'}
        </button>
        <button
          className="icon-btn"
          onClick={toggle}
          title="Toggle theme"
        >
          {theme === 'light' ? <Icon.Moon /> : <Icon.Sun />}
        </button>
      </div>
    </header>
  );
}

// ---------- Hub ----------

function Hub() {
  const { t } = useI18n();
  const [query, setQuery] = useState_S('');
  const { items: history, reload } = useHistory();

  const filtered = useMemo_S(() => {
    if (!query.trim()) return TOOLS;
    const q = query.toLowerCase();
    return TOOLS.filter(tool =>
      t(tool.nameKey).toLowerCase().includes(q) ||
      t(tool.descKey).toLowerCase().includes(q) ||
      tool.id.includes(q)
    );
  }, [query, t]);

  const tweaks = window.__cv_tweaks || {};
  const cardStyle = tweaks.cardStyle || 'soft';

  return (
    <div className="hub">
      <div className="hub-hero">
        <div className="hub-eyebrow">{t('hub_eyebrow')}</div>
        <h1 className="hub-title">
          {t('hub_title_pre')} <em>{t('hub_title_em')}</em>
        </h1>
        <p className="hub-sub">{t('hub_sub')}</p>
      </div>

      <div className="hub-toolbar">
        <div className="hub-search">
          <Icon.Search />
          <input
            type="text"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder={t('hub_search_placeholder')}
          />
        </div>
      </div>

      <div className="hub-section">
        <div className="hub-section-head">
          <div className="hub-section-title">{t('section_tools')}</div>
          <div className="hub-section-meta">{filtered.length.toString().padStart(2, '0')} · {t('section_tools_meta')}</div>
        </div>
        <div className="tools-grid">
          {filtered.map(tool => (
            <ToolCard key={tool.id} tool={tool} styleVariant={cardStyle} />
          ))}
        </div>
      </div>

      <div className="hub-section">
        <div className="hub-section-head">
          <div className="hub-section-title">{t('section_history')}</div>
          <div className="hub-section-meta" style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span>{history.length.toString().padStart(2, '0')} · {t('section_history_meta')}</span>
            {history.length > 0 && (
              <button
                className="btn btn-ghost"
                style={{ height: 26, padding: '0 10px', fontSize: 11 }}
                onClick={() => { clearHistory(); reload(); }}
              >{t('history_clear')}</button>
            )}
          </div>
        </div>
        {history.length === 0 ? (
          <div className="hist-empty">{t('history_empty')}</div>
        ) : (
          <div className="hist-list">
            {history.slice(0, 12).map(entry => {
              const tool = TOOL_BY_ID[entry.toolId];
              if (!tool) return null;
              return (
                <div
                  className="hist-row"
                  key={entry.id}
                  onClick={() => navigate(entry.payload ? `${entry.toolId}?h=${entry.id}` : entry.toolId)}
                  style={{ '--card-hue': `var(--hue-${tool.hue})` }}
                >
                  <div className="hist-icon">{tool.initials}</div>
                  <div className="hist-name">
                    {entry.title || t('untitled')}
                    {entry.size != null && <small>{window.fmtBytes(entry.size)}</small>}
                  </div>
                  <div className="hist-tool">{t(tool.nameKey)}</div>
                  <div className="hist-time">{formatRelativeTime(entry.ts, t)}</div>
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );
}

function ToolCard({ tool, styleVariant }) {
  const { t } = useI18n();
  const cls = `tool-card style-${styleVariant || 'soft'}`;
  return (
    <div
      className={cls}
      onClick={() => navigate(tool.id)}
      style={{ '--card-hue': `var(--hue-${tool.hue})` }}
    >
      <div className="tool-card-icon">{tool.initials}</div>
      <h3 className="tool-card-title">{t(tool.nameKey)}</h3>
      <p className="tool-card-desc">{t(tool.descKey)}</p>
      <div className="tool-card-foot">
        <span className={`tool-card-badge ${tool.badge === 'live' ? 'live' : ''}`}>
          {t(tool.badgeKey)}
        </span>
        <span className="tool-card-arrow">→</span>
      </div>
    </div>
  );
}

// ---------- Common Tool Page chrome ----------

function ToolHead({ tool, actions }) {
  const { t } = useI18n();
  return (
    <header className="tool-head" style={{ '--card-hue': `var(--hue-${tool.hue})` }}>
      <div className="tool-head-icon">{tool.initials}</div>
      <div>
        <div className="tool-head-title">{t(tool.nameKey)}</div>
        <div className="tool-head-sub">{t(tool.descKey)}</div>
      </div>
      <div className="tool-head-actions">{actions}</div>
    </header>
  );
}

function StatusBar({ status, left, right }) {
  const { t } = useI18n();
  const pillClass = status === 'busy' ? 'busy' : status === 'err' ? 'err' : 'ok';
  const pillText = status === 'busy' ? t('common_busy') : status === 'err' ? t('common_error') : t('common_ready');
  return (
    <footer className="statusbar">
      {left}
      <span className="status-spacer" />
      {right}
      <span className={`status-pill ${pillClass}`}>{pillText}</span>
    </footer>
  );
}

// ---------- Dropzone ----------

function Dropzone({ accept, multiple, files, onFiles, onRemove, styleVariant = 'default', title, sub, busy, busyText }) {
  const { t } = useI18n();
  const { dragover, bind, inputProps } = window.useDropzone({
    accept, multiple,
    onFiles: (newFiles) => {
      if (multiple) onFiles([...(files || []), ...newFiles]);
      else onFiles(newFiles);
    },
  });
  const cls = `dropzone style-${styleVariant} ${dragover ? 'dragover' : ''}`;
  const hasFiles = files && files.length > 0;
  return (
    <div className={cls} {...bind}>
      <input {...inputProps} />
      {busy ? (
        <>
          <div className="dropzone-icon"><span className="spin" /></div>
          <div className="dropzone-title">{busyText || t('common_busy')}</div>
        </>
      ) : (
        <>
          <div className="dropzone-icon">{dragover ? '↓' : '+'}</div>
          <div>
            <div className="dropzone-title">{dragover ? t('common_drop_here') : title}</div>
            <div className="dropzone-sub">{sub}</div>
          </div>
          {hasFiles ? (
            <div className="file-chips">
              {files.map((f, i) => (
                <span className="file-chip" key={i} onClick={(e) => e.stopPropagation()}>
                  {f.name} <span style={{ color: 'var(--ink-3)' }}>· {window.fmtBytes(f.size)}</span>
                  <span className="x" onClick={(e) => { e.stopPropagation(); onRemove?.(i); }} title={t('common_remove')}>×</span>
                </span>
              ))}
            </div>
          ) : (
            <div className="dropzone-files">{t('common_browse')}</div>
          )}
        </>
      )}
    </div>
  );
}

// ---------- Common option controls ----------

function OptCheckbox({ checked, onChange, label, hint }) {
  return (
    <label className="opt">
      <input type="checkbox" checked={!!checked} onChange={e => onChange(e.target.checked)} />
      <span className="opt-label">{label}</span>
      {hint && <span className="opt-hint">{hint}</span>}
    </label>
  );
}

function OptRadio({ value, onChange, label, options }) {
  return (
    <div className="opt opt-radio">
      <span className="opt-label">{label}</span>
      <div className="radio-group">
        {options.map(o => (
          <button
            key={o.value}
            className={`radio-pill ${value === o.value ? 'active' : ''}`}
            onClick={() => onChange(o.value)}
          >{o.label}</button>
        ))}
      </div>
    </div>
  );
}

function OptDivider() { return <div className="opt-divider" />; }

// ---------- Empty state ----------

function EmptyOutput({ title, sub }) {
  return (
    <div className="placeholder-pane">
      <div className="ph-title">{title}</div>
      <div className="ph-sub">{sub}</div>
    </div>
  );
}

// ---------- Export to window ----------

Object.assign(window, {
  TopBar, Hub, ToolHead, StatusBar, Dropzone,
  OptCheckbox, OptRadio, OptDivider,
  EmptyOutput,
});
