// qiaopi-compose.jsx — Transwriting engine + submission form.
//
// A modern visitor writes a family letter in plain spoken Chinese (大白话);
// composeQiaopi() dresses it in the conventions of a real qiaopi: an honorific
// salutation keyed to the recipient relation, the 敬稟者 opening, a remittance
// clause, set closing phrases, and a signature line. This is a deterministic
// template/dictionary transform — NOT a language model. The single entry point
// composeQiaopi() is the swap point if a real AI rewrite is wired in later.

// ─── Relation → salutation + self-term ───────────────────────────────
// salutation: 抬头称谓 ; selfTerm: 寄信人对收信人的自称
const RELATION_PRESETS = {
  mother:  { label: '母亲',   salutation: '母親大人膝下：',     selfTerm: '兒' },
  father:  { label: '父亲',   salutation: '父親大人膝下：',     selfTerm: '兒' },
  parents: { label: '父母',   salutation: '父母親大人尊前：',   selfTerm: '兒' },
  wife:    { label: '妻子',   salutation: '賢妻妝次：',         selfTerm: '夫' },
  husband: { label: '丈夫',   salutation: '夫君大人台鑒：',     selfTerm: '妻' },
  brother: { label: '兄长',   salutation: '兄長大人尊鑒：',     selfTerm: '弟' },
  younger: { label: '弟弟',   salutation: '賢弟如晤：',         selfTerm: '兄' },
  sister:  { label: '姐妹',   salutation: '姊妹如晤：',         selfTerm: '兄' },
  child:   { label: '子女',   salutation: '吾兒見字：',         selfTerm: '父' },
  grandpa: { label: '祖父母', salutation: '祖父母大人尊前：',   selfTerm: '孫' },
};
const RELATION_DEFAULT = { salutation: '尊鑒：', selfTerm: '弟' };

function relationPreset(relation, recipientName) {
  const p = RELATION_PRESETS[relation];
  if (p) return p;
  // Fallback: prepend the typed recipient name to a generic respectful salutation.
  const name = (recipientName || '').trim();
  return { salutation: (name ? name + ' ' : '') + RELATION_DEFAULT.salutation, selfTerm: RELATION_DEFAULT.selfTerm };
}

// ─── Currency presets ─────────────────────────────────────────────────
const CURRENCY_PRESETS = [
  { value: '银元', en: 'silver dollars' },
  { value: '叻币', en: 'Straits dollars' },
  { value: '铢',   en: 'baht' },
  { value: '披索', en: 'pesos' },
  { value: '港币', en: 'HK dollars' },
  { value: '国币', en: 'yuan' },
];

// ─── Light 大白话 → 文言 dictionary ────────────────────────────────────
// Whole-substring replacements applied in order. {SELF} is filled with the
// relation's self-term. Kept deliberately light — the goal is flavour, not a
// faithful classical translation.
const WORD_RULES = [
  ['不要担心', '勿念'],
  ['不用担心', '勿念'],
  ['别担心',   '勿念'],
  ['担心',     '掛念'],
  ['我们',     '我等'],
  ['我',       '{SELF}'],
  ['你们',     '汝等'],
  ['咱们',     '我等'],
  ['收到',     '查收'],
  ['寄给',     '付與'],
  ['寄回',     '付回'],
  ['寄',       '付'],
  ['钱',       '銀'],
  ['家里',     '家中'],
  ['家中',     '家中'],
  ['现在',     '現今'],
  ['最近',     '近日'],
  ['身体',     '身體'],
  ['想念',     '思念'],
  ['很想',     '甚念'],
  ['平安',     '平安'],
  ['希望',     '望'],
  ['一定',     '務必'],
  ['请',       '請'],
  ['谢谢',     '感荷'],
  ['因为',     '因'],
  ['所以',     '故'],
  ['但是',     '惟'],
  ['知道',     '知悉'],
  ['告诉',     '稟告'],
];

function classicalize(text, selfTerm) {
  let out = (text || '').trim();
  for (const [from, to] of WORD_RULES) {
    out = out.split(from).join(to.replace('{SELF}', selfTerm));
  }
  return out;
}

// ─── Date → 干支年 + 月 + 日 (postmark flavour) ────────────────────────
const STEMS = ['甲','乙','丙','丁','戊','己','庚','辛','壬','癸'];
const BRANCHES = ['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'];
const CN_NUM = ['〇','一','二','三','四','五','六','七','八','九','十'];
function cnDay(d) {
  if (d <= 10) return (d === 10 ? '初十' : '初' + CN_NUM[d]);
  if (d < 20) return '十' + CN_NUM[d - 10];
  if (d === 20) return '二十';
  if (d < 30) return '廿' + CN_NUM[d - 20];
  if (d === 30) return '三十';
  return '卅一';
}
function cnMonth(m) {
  return (m === 1 ? '正' : (m === 12 ? '臘' : (m === 11 ? '冬' : CN_NUM[m]))) + '月';
}
function composePostmark(date) {
  const y = date.getFullYear();
  const ganzhi = STEMS[(y - 4) % 10] + BRANCHES[(y - 4) % 12] + '年';
  return ganzhi + ' ' + cnMonth(date.getMonth() + 1) + ' ' + cnDay(date.getDate());
}

// ─── The transform ────────────────────────────────────────────────────
// form: { senderName, recipientName, relation, fromCity, fromCountry,
//         toCity, toRegion, amountValue, currency, body, makePublic }
// opts.bodyOverride: when set, used verbatim as the letter core instead of
//   classicalizing form.body — lets the live preview show the framing
//   (salutation / amount / signature) while the body stays a placeholder
//   until the visitor clicks 誊成侨批.
function composeQiaopi(form, opts) {
  const preset = relationPreset(form.relation, form.recipientName);
  const selfTerm = preset.selfTerm;
  const senderName = (form.senderName || '').trim() || '某';
  const fromCity = (form.fromCity || '').trim() || '南洋';
  const recipientName = (form.recipientName || '').trim();

  const core = (opts && opts.bodyOverride != null)
    ? opts.bodyOverride
    : classicalize(form.body, selfTerm);

  const amountVal = parseFloat(form.amountValue);
  const currency = (form.currency || '银元').trim();
  const hasAmount = !isNaN(amountVal) && amountVal > 0;
  const amountClause = hasAmount
    ? '\n　　茲付去' + currency + amountVal + '元，伏祈查收。'
    : '';

  const now = new Date();
  const postmark = composePostmark(now);

  const bodyZh =
    preset.salutation +
    '\n　　敬稟者，' + core + amountClause +
    '\n　　餘容後稟。耑此，敬請\n　　福安。' +
    '\n\n　　　　' + fromCity + ' ' + senderName + ' ' + selfTerm + ' 謹稟' +
    '\n　　　　' + postmark;

  const currencyEn = (CURRENCY_PRESETS.find((c) => c.value === currency) || {}).en || '';

  const title = (fromCity + (form.fromCountry ? '' : '') + senderName + '寄' +
    (form.toRegion || form.toCity || '家') +
    (recipientName ? recipientName : '') + '家書').trim();

  return {
    id: makeCommunityId(),
    community: true,
    featured: true,   // so the route is clickable on the 信路 map
    title,
    year: now.getFullYear(),
    month: now.getMonth() + 1,
    from: {
      city: fromCity,
      cityEn: '',
      country: (form.fromCountry || '').trim(),
      countryEn: '',
      lng: null, lat: null,
    },
    to: {
      city: (form.toCity || '').trim(),
      cityEn: '',
      region: (form.toRegion || form.toCity || '').trim(),
      regionEn: '',
      lng: null, lat: null,
    },
    sender: { name: senderName, nameEn: null },
    recipient: { name: recipientName || '—', nameEn: null },
    amount: hasAmount ? { value: amountVal, currency, currencyEn } : null,
    bodyZh,
    bodyEn: (form.body || '').trim(),   // plain-language original, shown as 白话原文
    postmark,
    scans: [],
    cover: null,
    scanStatus: 'placeholder',
    tags: ['網寄'],
    createdAt: now.toISOString(),
    private: !form.makePublic,
  };
}

// ─── Submission form page ─────────────────────────────────────────────
function ComposePage({ onCancel, onPublished, tweaks, width, height, isMobile = false }) {
  const [form, setForm] = React.useState({
    senderName: '', recipientName: '', relation: 'mother',
    fromCity: '', fromCountry: '', toCity: '', toRegion: '',
    amountValue: '', currency: '银元', body: '',
  });
  // `composed` = the body has been 誊写 (transformed) into the preview. Framing
  // fields preview live; the body only enters on clicking 誊成侨批. Editing the
  // body again drops back to the placeholder so it must be re-誊写.
  const [composed, setComposed] = React.useState(false);
  const [composing, setComposing] = React.useState(false);
  // AI-polished body core (文言). null → fall back to the rule-based classicalize.
  const [aiCore, setAiCore] = React.useState(null);
  const [publishing, setPublishing] = React.useState(false);
  const set = (k) => (e) => setForm({ ...form, [k]: e.target.value });
  const setBody = (e) => { setForm({ ...form, body: e.target.value }); setComposed(false); setAiCore(null); };

  const BODY_PLACEHOLDER = '〔正文待誊写——点「誊成侨批」生成〕';
  const hasAny = !!(form.senderName.trim() || form.recipientName.trim() || form.body.trim());
  const canCompose = !!(form.senderName.trim() && form.recipientName.trim() && form.body.trim());
  // bodyOverride: placeholder before 誊写; AI core if we got one; else undefined → rule transform.
  const bodyOpt = composed
    ? (aiCore != null ? { bodyOverride: aiCore } : undefined)
    : { bodyOverride: BODY_PLACEHOLDER };
  const liveLetter = hasAny ? composeQiaopi({ ...form, makePublic: true }, bodyOpt) : null;

  // 誊写正文: try Workers AI polish; on any failure use the rule-based transform.
  const doCompose = async () => {
    if (!canCompose || composing) return;
    setComposing(true);
    let core = null;
    try {
      const res = await fetch('/api/rewrite', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ text: form.body, relation: form.relation }),
      });
      if (res.ok) {
        const d = await res.json();
        if (d && d.ok && d.text) core = d.text;
      }
    } catch (e) { /* network/AI down → rule fallback */ }
    setAiCore(core);     // null → composeQiaopi uses classicalize
    setComposed(true);
    setComposing(false);
  };
  const publish = async (makePublic) => {
    if (publishing) return;
    setPublishing(true);
    // reuse the same AI core (if any) that's shown in the preview
    const letter = composeQiaopi({ ...form, makePublic }, aiCore != null ? { bodyOverride: aiCore } : undefined);
    try { await resolveLetterCoords(letter); } catch (e) { /* coords stay null */ }
    try { await saveCommunityLetter(letter); } catch (e) { /* fell back to local */ }
    setPublishing(false);
    onPublished(letter, makePublic);
  };

  return (
    <div style={{ position: 'relative', width, height, overflow: 'hidden', fontFamily: '"Noto Serif SC", serif', color: '#2a1f17' }}>
      <PaperBg tone={tweaks.paperTone} style={{ position: 'absolute', inset: 0 }}>
        {/* header */}
        <div style={{
          position: 'absolute', top: 28, left: isMobile ? 20 : 56, right: isMobile ? 20 : 56, zIndex: 5,
          display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        }}>
          <button onClick={onCancel} style={backBtn}>← 返回信路</button>
          <div style={{ fontFamily: '"EB Garamond", serif', fontStyle: 'italic', fontSize: 13, letterSpacing: 3, color: '#7a4828' }}>
            写一封家书 · Write a letter home
          </div>
        </div>

        {/* scroll body */}
        <div style={{
          position: 'absolute', inset: isMobile ? '76px 0 0' : '92px 0 0',
          overflowY: 'auto', WebkitOverflowScrolling: 'touch', padding: isMobile ? '0 20px 40px' : '0 56px 48px',
        }}>
          <div style={{
            display: 'flex', gap: isMobile ? 0 : 48, flexDirection: isMobile ? 'column' : 'row',
            alignItems: 'flex-start', maxWidth: 1180, margin: '0 auto',
          }}>
            {/* ── form column ── */}
            <div style={{ flex: '1 1 0', minWidth: 0, width: '100%' }}>
              <h2 style={{ fontFamily: '"Noto Serif SC", serif', fontWeight: 900, fontSize: isMobile ? 30 : 40, letterSpacing: 6, margin: '0 0 6px' }}>寄一封家信</h2>
              <p style={{ fontSize: 13, lineHeight: 1.8, color: '#5a3a22', margin: '0 0 24px', maxWidth: 520 }}>
                用今天的大白话写下你想说的话，我们替你誊成当年侨批的行文格式——称谓、敬辞、汇款、落款，一应俱全。
              </p>

              <Field label="寄信人 · 你的名字">
                <input value={form.senderName} onChange={set('senderName')} placeholder="如：陳榮" style={inp} />
              </Field>

              <div style={row}>
                <Field label="收信人 · 寄给谁" style={{ flex: 2 }}>
                  <input value={form.recipientName} onChange={set('recipientName')} placeholder="如：母亲、王秀英" style={inp} />
                </Field>
                <Field label="关系" style={{ flex: 1 }}>
                  <select value={form.relation} onChange={set('relation')} style={inp}>
                    {Object.keys(RELATION_PRESETS).map((k) => (
                      <option key={k} value={k}>{RELATION_PRESETS[k].label}</option>
                    ))}
                    <option value="other">其他</option>
                  </select>
                </Field>
              </div>

              <div style={row}>
                <Field label="寄出地 · 城市" style={{ flex: 1 }}>
                  <input value={form.fromCity} onChange={set('fromCity')} placeholder="如：槟城" style={inp} />
                </Field>
                <Field label="寄出地 · 国家" style={{ flex: 1 }}>
                  <input value={form.fromCountry} onChange={set('fromCountry')} placeholder="如：马来亚" style={inp} />
                </Field>
              </div>

              <div style={row}>
                <Field label="收信地 · 城市" style={{ flex: 1 }}>
                  <input value={form.toCity} onChange={set('toCity')} placeholder="如：泉州" style={inp} />
                </Field>
                <Field label="收信地 · 乡里" style={{ flex: 1 }}>
                  <input value={form.toRegion} onChange={set('toRegion')} placeholder="如：福建 永春" style={inp} />
                </Field>
              </div>

              <div style={row}>
                <Field label="汇款 · 金额（可留空）" style={{ flex: 1 }}>
                  <input value={form.amountValue} onChange={set('amountValue')} placeholder="如：30" inputMode="decimal" style={inp} />
                </Field>
                <Field label="币种" style={{ flex: 1 }}>
                  <select value={form.currency} onChange={set('currency')} style={inp}>
                    {CURRENCY_PRESETS.map((c) => <option key={c.value} value={c.value}>{c.value}</option>)}
                  </select>
                </Field>
              </div>

              <Field label="家书正文 · 用大白话写">
                <textarea value={form.body} onChange={setBody} rows={isMobile ? 6 : 8}
                  placeholder="想说什么就写什么，比如：妈，我在外面一切都好，不要担心。这次寄三十块钱回家用，给三婶买点东西。家里要是钱不够就来信。"
                  style={{ ...inp, resize: 'vertical', lineHeight: 1.8, fontFamily: '"Noto Serif SC", serif' }} />
              </Field>

              <button onClick={doCompose} disabled={!canCompose || composing}
                style={{ ...primaryBtnLg, opacity: (canCompose && !composing) ? 1 : 0.45, cursor: composing ? 'wait' : (canCompose ? 'pointer' : 'not-allowed') }}>
                {composing ? '正在誊写…' : (composed ? '重新誊写正文' : '誊成侨批 · 誊写正文 →')}
              </button>
              {!canCompose ? (
                <div style={{ marginTop: 8, fontSize: 11, color: '#7a4828', opacity: 0.7 }}>
                  填好寄信人、收信人、正文后即可誊写。
                </div>
              ) : (
                <div style={{ marginTop: 8, fontSize: 11, color: '#7a4828', opacity: 0.7 }}>
                  由 AI 润色成侨批体；额度用尽或失败时自动改用内置规则转写。
                </div>
              )}
            </div>

            {/* ── preview column (framing live; body enters on 誊写) ── */}
            <div style={{ flex: '1 1 0', minWidth: 0, width: '100%', marginTop: isMobile ? 32 : 0 }}>
              <div style={{ fontFamily: '"EB Garamond", serif', fontStyle: 'italic', fontSize: 12, letterSpacing: 3, color: '#7a4828', textTransform: 'uppercase', marginBottom: 14 }}>
                Preview · 侨批誊本{liveLetter && !composed ? ' · 实时' : ''}
              </div>
              {liveLetter ? (
                <div>
                  <div style={{ display: 'flex', justifyContent: 'center', position: 'relative' }}>
                    <LetterScan letter={liveLetter} scale={isMobile ? 0.62 : 0.78} />
                    <div style={{ position: 'absolute', bottom: -6, right: isMobile ? 8 : 28 }}>
                      <ChopSeal text="網寄" size={42} rotate={-7} />
                    </div>
                  </div>

                  {composed ? (
                    <div style={{ marginTop: 26, padding: '18px 20px', background: 'rgba(42,31,23,0.04)', border: '1px solid rgba(106,58,38,0.25)' }}>
                      <div style={{ fontFamily: '"Noto Serif SC", serif', fontWeight: 700, fontSize: 14, marginBottom: 12, letterSpacing: 1 }}>
                        要把这封信公开到「网友寄存」吗？
                      </div>
                      <div style={{ fontSize: 12, color: '#5a3a22', lineHeight: 1.7, marginBottom: 16 }}>
                        公开后，它会出现在「网友寄存」展厅，与历史档案分开陈列。也可以只留存在你这台设备上。
                      </div>
                      <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
                        <button onClick={() => publish(true)} disabled={publishing}
                          style={{ ...primaryBtnLg, marginTop: 0, padding: '12px 18px', letterSpacing: 2, opacity: publishing ? 0.5 : 1, cursor: publishing ? 'wait' : 'pointer' }}>
                          {publishing ? '正在定位寄存…' : '公开寄存 →'}
                        </button>
                        <button onClick={() => publish(false)} disabled={publishing} style={{ ...ghostBtn, opacity: publishing ? 0.5 : 1 }}>仅自己留存</button>
                      </div>
                      <div style={{ marginTop: 12, fontSize: 11, color: '#7a4828', opacity: 0.75, lineHeight: 1.6 }}>
                        公开后会按你填的寄出地 / 收信地，在「网友寄存」的信路地图上画出这封信的航线。
                      </div>
                    </div>
                  ) : (
                    <div style={{ marginTop: 20, padding: '14px 16px', border: '1px dashed rgba(106,58,38,0.4)', borderRadius: 2, textAlign: 'center', fontFamily: '"Noto Serif SC", serif', fontSize: 12, color: '#7a4828', lineHeight: 1.8 }}>
                      称谓、地点、汇款、落款已随填随变。<br/>点左侧「誊成侨批」把正文誊入，即可寄存。
                    </div>
                  )}
                </div>
              ) : (
                <div style={{
                  border: '1px dashed rgba(106,58,38,0.4)', borderRadius: 2,
                  padding: '60px 24px', textAlign: 'center', color: '#7a4828',
                  fontFamily: '"EB Garamond", serif', fontStyle: 'italic', fontSize: 14, lineHeight: 1.7,
                }}>
                  开始填写左侧表格，<br/>称谓与落款会在这里实时显示；<br/>点「誊成侨批」再把正文誊入。
                </div>
              )}
            </div>
          </div>
        </div>
      </PaperBg>
    </div>
  );
}

// ─── local styles ─────────────────────────────────────────────────────
const backBtn = {
  background: 'transparent', border: '1px solid rgba(106,58,38,0.4)',
  color: '#5a3a22', fontFamily: '"EB Garamond", serif', fontStyle: 'italic',
  padding: '8px 14px', cursor: 'pointer', fontSize: 13, letterSpacing: 2,
};
const inp = {
  width: '100%', boxSizing: 'border-box', padding: '10px 12px',
  background: 'rgba(255,255,255,0.55)', border: '1px solid rgba(106,58,38,0.35)',
  color: '#2a1f17', fontSize: 14, fontFamily: '"Noto Serif SC", serif',
  outline: 'none', borderRadius: 2,
};
const row = { display: 'flex', gap: 14 };
const primaryBtnLg = {
  background: '#2a1f17', border: 'none', color: '#f1e8d4',
  fontFamily: '"Noto Serif SC", serif', fontSize: 14, letterSpacing: 3,
  padding: '12px 22px', cursor: 'pointer', borderRadius: 2, marginTop: 8,
};
const ghostBtn = {
  background: 'transparent', border: '1px solid rgba(106,58,38,0.45)',
  color: '#5a3a22', fontFamily: '"Noto Serif SC", serif', fontSize: 14, letterSpacing: 2,
  padding: '12px 18px', cursor: 'pointer', borderRadius: 2,
};

function Field({ label, children, style }) {
  return (
    <label style={{ display: 'block', marginBottom: 16, ...style }}>
      <div style={{ fontSize: 12, color: '#7a4828', letterSpacing: 1, marginBottom: 6, fontFamily: '"Noto Serif SC", serif' }}>{label}</div>
      {children}
    </label>
  );
}
