// design-system.jsx — Shared tokens, paper texture, and atomic UI for ilovejp App
// Aesthetic: warm stationery / paper feel, washi tape accents, hand-drawn touches.
// Book accent colors (yellow / pink / blue / green) + neutrals.

// ─────────────────────────────────────────────────────────────
// Tokens
// ─────────────────────────────────────────────────────────────
const TOKENS = {
  // warm paper neutrals
  paper: '#FAF6EE',         // page bg
  paperDeep: '#F2EBDC',     // section divider
  ivory: '#FFFDF7',         // card
  ink: '#231F1A',           // headings
  inkSoft: '#5C544A',       // body
  inkMute: '#9A8E7E',       // captions
  rule: '#E5DCC8',          // hairlines
  ruleDeep: '#D4C9B0',
  // dark mode
  paperDark: '#1A1714',
  paperDeepDark: '#221E1A',
  ivoryDark: '#2A2521',
  inkDark: '#F5EFE2',
  inkSoftDark: '#C9BFAE',
  inkMuteDark: '#8A8071',
  ruleDark: '#3A3530',
  // book colors
  book1: '#F5C84B',         // 黃 — 入門
  book1Soft: '#FFF1C6',
  book1Ink: '#7A5A0F',
  book2: '#F2A6BD',         // 粉 — 對話口語
  book2Soft: '#FCE2EA',
  book2Ink: '#8C2F4C',
  book3: '#7AB6E0',         // 藍 — 旅遊
  book3Soft: '#D9EBF6',
  book3Ink: '#1F557C',
  book4: '#8FB87A',         // 綠 — 閱讀聽力
  book4Soft: '#DBE9CC',
  book4Ink: '#3F6028',
  // accents
  red: '#C8553D',           // bookmark / important
  ochre: '#B8843F',
};

const FONTS = {
  jp: '"Zen Kaku Gothic New", "Noto Sans JP", system-ui, sans-serif',
  jpHand: '"Klee One", "Yuji Syuku", "Zen Kaku Gothic New", serif',
  zh: '"Noto Sans TC", "PingFang TC", system-ui, sans-serif',
  zhHand: '"Klee One", "Noto Sans TC", serif',
  mono: '"JetBrains Mono", ui-monospace, monospace',
};

// theme switcher
function useTheme(dark) {
  return React.useMemo(() => dark ? {
    paper: TOKENS.paperDark,
    paperDeep: TOKENS.paperDeepDark,
    ivory: TOKENS.ivoryDark,
    ink: TOKENS.inkDark,
    inkSoft: TOKENS.inkSoftDark,
    inkMute: TOKENS.inkMuteDark,
    rule: TOKENS.ruleDark,
    ruleDeep: TOKENS.ruleDark,
  } : {
    paper: TOKENS.paper, paperDeep: TOKENS.paperDeep, ivory: TOKENS.ivory,
    ink: TOKENS.ink, inkSoft: TOKENS.inkSoft, inkMute: TOKENS.inkMute,
    rule: TOKENS.rule, ruleDeep: TOKENS.ruleDeep,
  }, [dark]);
}

// Book lookup
const BOOKS = [
  { id: 1, color: TOKENS.book1, soft: TOKENS.book1Soft, ink: TOKENS.book1Ink,
    title: '從零開始 用YouTube影片學日文', subtitle: '日語名師井上一宏為零基礎自學者設計的22堂線上影音課',
    short: '入門基礎', tag: 'BOOK 1', date: '2022.09', lessons: 22, parts: 3,
    desc: '為零基礎自學者而設計的22堂課' },
  { id: 2, color: TOKENS.book2, soft: TOKENS.book2Soft, ink: TOKENS.book2Ink,
    title: '從零開始 用YouTube影片學日文（2）', subtitle: '對話口語大特訓 井上老師的12堂免費線上課程',
    short: '對話口語', tag: 'BOOK 2', date: '2023.10', lessons: 12, parts: 1,
    desc: '講出自然的日文為目標！' },
  { id: 3, color: TOKENS.book3, soft: TOKENS.book3Soft, ink: TOKENS.book3Ink,
    title: '從零開始，用YouTube影片學日文（3）', subtitle: '旅遊對話大特訓 井上老師的25堂免費線上課程',
    short: '旅遊會話', tag: 'BOOK 3', date: '2024.09', lessons: 25, parts: 4,
    desc: '日本旅遊必學25堂課' },
  { id: 4, color: TOKENS.book4, soft: TOKENS.book4Soft, ink: TOKENS.book4Ink,
    title: '從零開始 用YouTube影片學日文（4）', subtitle: '閱讀與聽力大躍進 井上老師精選60篇課文＆100+超實用語法',
    short: '閱讀聽力', tag: 'BOOK 4', date: '2025.04', lessons: 80, parts: 2,
    desc: '60篇實用短文 × 100個常用文法' },
];

// ─────────────────────────────────────────────────────────────
// Paper texture — subtle fiber + grain via SVG noise
// ─────────────────────────────────────────────────────────────
const PaperBg = ({ tone = 'paper', dark = false, children, style = {} }) => {
  const T = useTheme(dark);
  const bg = T[tone];
  return (
    <div style={{
      position: 'relative',
      background: `
        radial-gradient(ellipse at 30% 0%, rgba(255,200,120,${dark ? 0.04 : 0.08}), transparent 50%),
        radial-gradient(ellipse at 80% 100%, rgba(200,150,80,${dark ? 0.04 : 0.06}), transparent 60%),
        ${bg}`,
      ...style,
    }}>
      {/* fiber overlay */}
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        opacity: dark ? 0.12 : 0.18, mixBlendMode: 'multiply',
        backgroundImage: `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.4   0 0 0 0 0.32   0 0 0 0 0.2   0 0 0 0.6 0'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='0.45'/></svg>")`,
      }}/>
      <div style={{ position: 'relative' }}>{children}</div>
    </div>
  );
};

// Washi tape strip — for book covers, headers, decorative
const WashiTape = ({ color, w = 80, h = 22, rot = -3, style = {}, pattern = 'dots' }) => {
  const patterns = {
    dots: `radial-gradient(circle at 6px 6px, rgba(0,0,0,0.08) 1.2px, transparent 1.5px)`,
    stripe: `repeating-linear-gradient(45deg, transparent 0 6px, rgba(0,0,0,0.08) 6px 7px)`,
    cross: `repeating-linear-gradient(0deg, transparent 0 5px, rgba(0,0,0,0.08) 5px 6px), repeating-linear-gradient(90deg, transparent 0 5px, rgba(0,0,0,0.08) 5px 6px)`,
    plain: 'none',
  };
  return (
    <div style={{
      width: w, height: h, background: color, transform: `rotate(${rot}deg)`,
      backgroundImage: patterns[pattern],
      backgroundSize: pattern === 'dots' ? '12px 12px' : 'auto',
      boxShadow: '0 1px 2px rgba(0,0,0,0.08), inset 0 0 0 1px rgba(255,255,255,0.25)',
      opacity: 0.92,
      ...style,
    }}/>
  );
};

// Hand-drawn underline (svg squiggle)
const Squiggle = ({ color = TOKENS.red, w = 80, h = 8, style = {} }) => (
  <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`} style={{ display: 'block', ...style }}>
    <path d={`M2 ${h-3} Q ${w*0.2} 1, ${w*0.4} ${h-3} T ${w*0.8} ${h-3} T ${w-2} ${h-3}`}
      stroke={color} strokeWidth="2" fill="none" strokeLinecap="round"/>
  </svg>
);

// Hand-drawn circle (highlight)
const HandCircle = ({ color = TOKENS.red, size = 40, sw = 2, style = {} }) => (
  <svg width={size} height={size * 0.7} viewBox="0 0 100 70" style={{ position: 'absolute', ...style }}>
    <path d="M 50 5 C 20 5, 5 20, 5 35 C 5 55, 25 65, 55 65 C 80 63, 95 50, 92 30 C 88 12, 70 6, 48 8"
      stroke={color} strokeWidth={sw} fill="none" strokeLinecap="round" opacity="0.85"/>
  </svg>
);

// Stamp (round seal) — for furigana mode, achievement, etc.
const Stamp = ({ char = '読', color = TOKENS.red, size = 44, style = {} }) => (
  <div style={{
    width: size, height: size, borderRadius: '50%',
    border: `${size*0.07}px solid ${color}`, color,
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    fontFamily: FONTS.jpHand, fontWeight: 700, fontSize: size * 0.45,
    background: 'rgba(200,85,61,0.08)',
    transform: 'rotate(-6deg)',
    boxShadow: `inset 0 0 0 1px rgba(200,85,61,0.15)`,
    ...style,
  }}>{char}</div>
);

// ─────────────────────────────────────────────────────────────
// Furigana (振假名) — rt above kanji
// ─────────────────────────────────────────────────────────────
// pairs: [ ['漢字','かんじ'], 'です' ]  — string = plain, array = ruby
const Furigana = ({ pairs, show = true, size = 18, color, ruby = TOKENS.inkMute, style = {} }) => {
  const T = useTheme(false);
  return (
    <ruby style={{
      fontFamily: FONTS.jp, fontSize: size, color: color || T.ink,
      lineHeight: show ? 2 : 1.5, rubyAlign: 'center',
      ...style,
    }}>
      {pairs.map((p, i) => {
        if (typeof p === 'string') return <span key={i}>{p}</span>;
        return (
          <React.Fragment key={i}>
            <span>{p[0]}</span>
            <rt style={{
              fontSize: size * 0.5, color: ruby, fontWeight: 400,
              opacity: show ? 1 : 0,
              transition: 'opacity 0.3s',
            }}>{p[1]}</rt>
          </React.Fragment>
        );
      })}
    </ruby>
  );
};

// ─────────────────────────────────────────────────────────────
// Section header — small label + title + optional squiggle
// ─────────────────────────────────────────────────────────────
const SectionLabel = ({ children, color = TOKENS.red, style = {} }) => (
  <div style={{
    fontFamily: FONTS.mono, fontSize: 11, fontWeight: 600,
    color, letterSpacing: 1.2, textTransform: 'uppercase',
    display: 'flex', alignItems: 'center', gap: 8, ...style,
  }}>
    <span style={{ width: 16, height: 1, background: color }}/>
    {children}
  </div>
);

// Card — soft paper card, optional book-color top stripe
const PaperCard = ({ children, dark = false, accent, style = {}, onClick, padding = 16 }) => {
  const T = useTheme(dark);
  return (
    <div onClick={onClick} style={{
      background: T.ivory, borderRadius: 16,
      padding, position: 'relative', overflow: 'hidden',
      border: `1px solid ${T.rule}`,
      boxShadow: dark ? 'none' : '0 1px 0 rgba(0,0,0,0.02), 0 2px 8px rgba(60,40,20,0.04)',
      cursor: onClick ? 'pointer' : 'default',
      ...style,
    }}>
      {accent && (
        <div style={{
          position: 'absolute', left: 0, top: 0, bottom: 0,
          width: 4, background: accent,
        }}/>
      )}
      {children}
    </div>
  );
};

// Pill button (rounded, paper-feel)
const PaperButton = ({ children, onClick, color = TOKENS.ink, bg, dark = false, size = 'md', style = {} }) => {
  const T = useTheme(dark);
  const sizes = {
    sm: { p: '6px 12px', fs: 13 },
    md: { p: '10px 18px', fs: 14 },
    lg: { p: '14px 24px', fs: 16 },
  }[size];
  return (
    <button onClick={onClick} style={{
      padding: sizes.p, fontSize: sizes.fs,
      fontFamily: FONTS.zh, fontWeight: 600,
      borderRadius: 999, border: `1px solid ${color}`,
      background: bg || 'transparent', color,
      cursor: 'pointer', letterSpacing: 0.2,
      ...style,
    }}>{children}</button>
  );
};

// ─────────────────────────────────────────────────────────────
// Bottom Tab Bar — 首頁 / 學習 / 我的
// ─────────────────────────────────────────────────────────────
const TabBar = ({ active, onChange, dark = false }) => {
  const T = useTheme(dark);
  const tabs = [
    { id: 'home', label: '首頁', jp: 'ホーム', icon: 'home' },
    { id: 'learn', label: '學習', jp: 'まなぶ', icon: 'book' },
    { id: 'me', label: '我的', jp: 'マイ', icon: 'me' },
  ];
  const Icon = ({ k, active }) => {
    const c = active ? TOKENS.red : T.inkMute;
    const sw = active ? 2.2 : 1.8;
    if (k === 'home') return (
      <svg width="22" height="22" viewBox="0 0 22 22" fill="none">
        <path d="M3 9.5L11 3l8 6.5V19a1 1 0 01-1 1h-4v-6h-6v6H4a1 1 0 01-1-1V9.5z" stroke={c} strokeWidth={sw} strokeLinejoin="round"/>
      </svg>);
    if (k === 'book') return (
      <svg width="22" height="22" viewBox="0 0 22 22" fill="none">
        <path d="M4 4h6c1.7 0 3 1.3 3 3v12c0-1.7-1.3-3-3-3H4V4z" stroke={c} strokeWidth={sw} strokeLinejoin="round"/>
        <path d="M18 4h-6c1.7 0 3 1.3 3 3v12c0-1.7 1.3-3 3-3V4z" stroke={c} strokeWidth={sw} strokeLinejoin="round"/>
      </svg>);
    return (
      <svg width="22" height="22" viewBox="0 0 22 22" fill="none">
        <circle cx="11" cy="8" r="4" stroke={c} strokeWidth={sw}/>
        <path d="M3 20c1.5-4 4.5-6 8-6s6.5 2 8 6" stroke={c} strokeWidth={sw} strokeLinecap="round"/>
      </svg>);
  };
  return (
    <div style={{
      position: 'absolute', bottom: 0, left: 0, right: 0, zIndex: 30,
      paddingBottom: 28, paddingTop: 8,
      background: dark
        ? 'linear-gradient(to top, rgba(26,23,20,0.98) 60%, rgba(26,23,20,0))'
        : 'linear-gradient(to top, rgba(250,246,238,0.98) 60%, rgba(250,246,238,0))',
      backdropFilter: 'blur(20px)',
    }}>
      <div style={{
        margin: '0 16px', display: 'flex', gap: 4,
        background: T.ivory, borderRadius: 28,
        padding: 6, border: `1px solid ${T.rule}`,
        boxShadow: dark ? 'none' : '0 4px 16px rgba(60,40,20,0.06)',
      }}>
        {tabs.map(t => (
          <button key={t.id} onClick={() => onChange(t.id)} style={{
            flex: 1, border: 'none', background: active === t.id ? (dark ? 'rgba(200,85,61,0.15)' : '#FBEFEA') : 'transparent',
            borderRadius: 22, padding: '8px 4px',
            display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
            cursor: 'pointer',
          }}>
            <Icon k={t.icon} active={active === t.id}/>
            <span style={{
              fontFamily: FONTS.zh, fontSize: 11, fontWeight: 600,
              color: active === t.id ? TOKENS.red : T.inkMute,
            }}>{t.label}</span>
          </button>
        ))}
      </div>
    </div>
  );
};

// ─────────────────────────────────────────────────────────────
// Top App Bar — back / title / right action — paper style
// ─────────────────────────────────────────────────────────────
const PaperAppBar = ({ title, onBack, right, dark = false, sub, accent }) => {
  const T = useTheme(dark);
  return (
    <div style={{
      paddingTop: 54, paddingBottom: 12, paddingLeft: 8, paddingRight: 8,
      display: 'flex', alignItems: 'center', gap: 4,
      position: 'sticky', top: 0, zIndex: 5,
      background: `linear-gradient(to bottom, ${T.paper} 70%, ${T.paper}dd)`,
    }}>
      {onBack ? (
        <button onClick={onBack} style={{
          width: 38, height: 38, borderRadius: 19, border: 'none',
          background: 'transparent', cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <svg width="20" height="20" viewBox="0 0 20 20" fill="none">
            <path d="M13 4l-6 6 6 6" stroke={T.ink} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </button>
      ) : <div style={{ width: 38 }}/>}
      <div style={{ flex: 1, textAlign: 'center', minWidth: 0 }}>
        {sub && <div style={{ fontFamily: FONTS.mono, fontSize: 10, color: accent || T.inkMute, letterSpacing: 1.2 }}>{sub}</div>}
        {title && <div style={{ fontFamily: FONTS.zh, fontSize: 15, fontWeight: 700, color: T.ink, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{title}</div>}
      </div>
      <div style={{ width: 38, display: 'flex', justifyContent: 'flex-end' }}>{right || null}</div>
    </div>
  );
};

Object.assign(window, {
  TOKENS, FONTS, BOOKS,
  useTheme, PaperBg, WashiTape, Squiggle, HandCircle, Stamp,
  Furigana, SectionLabel, PaperCard, PaperButton, TabBar, PaperAppBar,
});
