// weekly-brief-preview.jsx
// Weekly Coach Brief preview modal: Markdown preview + copy-to-clipboard.
// Read-only presentation over core/report/WeeklyCoachBriefData.js output.
// No AI, no browser-storage writes, no repository writes. Renders a deterministic
// markdown template only — no readiness/risk/recommendation/prescription language.

const { useState: wbpS, useEffect: wbpE, useMemo: wbpM } = React;

// 本周一至周日（本地日期格式化，不用 UTC 转换——同 training.jsx currentWeekMondayToSunday）。
function wbpCurrentWeekMondayToSunday() {
  const now = new Date();
  const day = now.getDay(); // 0=Sun..6=Sat
  const diffToMonday = day === 0 ? -6 : 1 - day;
  const monday = new Date(now.getFullYear(), now.getMonth(), now.getDate() + diffToMonday);
  const sunday = new Date(monday.getFullYear(), monday.getMonth(), monday.getDate() + 6);
  const fmt = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
  return { fromDate: fmt(monday), toDate: fmt(sunday) };
}

// Map a Coach Discussion reviewed-evidence row (see core/ui-contract/EvidenceUIContract.js
// toEvidenceUIRow output) into the confirmedResults shape WeeklyCoachBriefData expects.
// Missing fields become null — never fabricated.
function wbpRowToConfirmedResult(row) {
  const r = row || {};
  return {
    testType: r.evidenceTypeLabel || null,
    date: r.timestamp ? String(r.timestamp).slice(0, 10) : null,
    classification: (r.primaryLabel && r.primaryLabel !== '—') ? r.primaryLabel : null,
    trainingFocus: r.secondaryLabel || null,
    reviewRef: r.id || null,
  };
}

function wbpFormatDateRange(fromDate, toDate) {
  return `${fromDate || '—'} to ${toDate || '—'}`;
}

// Deterministic markdown template. Bilingual section headings. No suggestion/
// recommendation/prescription/readiness generation — factual restatement only.
function wbpRenderMarkdown(data, athleteName, fromDate, toDate) {
  const d = data || {};
  const header = d.header || {};
  const confirmedEvidence = Array.isArray(d.confirmedEvidence) ? d.confirmedEvidence : [];
  const trainingContext = d.trainingContext || {};
  const discussionPoints = Array.isArray(d.discussionPoints) ? d.discussionPoints : [];
  const limitations = Array.isArray(d.limitations) ? d.limitations : [];

  const lines = [];
  lines.push('# Weekly Coach Brief');
  lines.push('');
  lines.push(`**Athlete:** ${header.athleteName || athleteName || '—'}`);
  lines.push(`**Date range:** ${wbpFormatDateRange(header.fromDate || fromDate, header.toDate || toDate)}`);
  lines.push('');

  lines.push('## 1. Key Confirmed Results / 已确认结果');
  if (confirmedEvidence.length) {
    confirmedEvidence.forEach(c => {
      lines.push(`- ${c.testType || '—'} ${c.date || '—'}: classification ${c.classification || '—'}; training focus ${c.trainingFocus || '—'}`);
    });
  } else {
    lines.push('- No confirmed results in this date range. / 该日期范围内无已确认结果。');
  }
  lines.push('');

  lines.push('## 2. Training Context / 训练情况');
  lines.push(`- Sessions: ${trainingContext.sessions == null ? '—' : trainingContext.sessions}`);
  lines.push(`- Completed: ${trainingContext.completed == null ? '—' : trainingContext.completed}`);
  lines.push(`- Avg RPE: ${trainingContext.avgRPE == null ? '—' : trainingContext.avgRPE}`);
  lines.push(`- Total duration (min): ${trainingContext.totalDurationMin == null ? '—' : trainingContext.totalDurationMin}`);
  lines.push(`- Session load: ${trainingContext.sessionLoad == null ? '—' : trainingContext.sessionLoad}`);
  const notableComments = Array.isArray(trainingContext.notableComments) ? trainingContext.notableComments : [];
  if (notableComments.length) {
    lines.push('- Notable comments / 备注:');
    notableComments.forEach(c => {
      lines.push(`  - [${c.date || '—'}] (${c.source || '—'}) ${c.text || ''}`);
    });
  }
  lines.push('');

  lines.push('## 3. Coach Discussion Points / 教练沟通要点');
  if (discussionPoints.length) {
    discussionPoints.forEach(p => {
      const tag = p.manualNote ? '[manual note]' : `[${p.evidenceRef || '—'}]`;
      lines.push(`- ${p.text || ''} ${tag}`);
    });
  } else {
    lines.push('- No discussion points available. / 暂无沟通要点。');
  }
  lines.push('');

  lines.push('## 4. Limitations / 局限说明');
  if (limitations.length) {
    limitations.forEach(l => lines.push(`- ${l}`));
  } else {
    lines.push('- None noted for this date range. / 该日期范围内无需说明的局限。');
  }
  lines.push('');

  return lines.join('\n');
}

function WeeklyBriefPreviewModal({ athletes = [], confirmedResultRows = [], onClose }) {
  const week = wbpM(() => wbpCurrentWeekMondayToSunday(), []);
  const [athleteId, setAthleteId] = wbpS(athletes[0]?.id || '');
  const [fromDate, setFromDate] = wbpS(week.fromDate);
  const [toDate, setToDate] = wbpS(week.toDate);
  const [manualNotesText, setManualNotesText] = wbpS('');
  const [briefData, setBriefData] = wbpS(null);
  const [copyState, setCopyState] = wbpS('idle'); // idle | copied | failed

  const athlete = athletes.find(a => a.id === athleteId) || null;

  wbpE(() => {
    if (!athletes.length) { setAthleteId(''); return; }
    if (!athletes.some(a => a.id === athleteId)) setAthleteId(athletes[0].id);
  }, [athletes]); // eslint-disable-line react-hooks/exhaustive-deps

  const confirmedResults = wbpM(() => {
    // 归因严格化：athleteId优先，缺失时退athleteName精确匹配；两者都对不上的行排除。
    // 宁可少列一条，也不允许别人的已确认结果混入某个运动员的简报。
    return (confirmedResultRows || [])
      .filter(row => row.athleteId
        ? row.athleteId === athleteId
        : (!!row.athleteName && !!athlete && row.athleteName === athlete.name))
      .map(wbpRowToConfirmedResult);
  }, [confirmedResultRows, athleteId, athlete]);

  wbpE(() => {
    let alive = true;
    const FS = window.FieldDataStore;
    (async () => {
      let trainingLogs = [];
      if (FS && typeof FS.listTrainingLogsByAthlete === 'function' && athleteId) {
        try {
          trainingLogs = await FS.listTrainingLogsByAthlete(athleteId, fromDate, toDate);
        } catch (e) { trainingLogs = []; }
      }
      if (!alive) return;
      if (!window.WeeklyCoachBriefData || typeof window.WeeklyCoachBriefData.buildWeeklyCoachBriefData !== 'function') {
        setBriefData(null);
        return;
      }
      const manualNotes = manualNotesText.split('\n').map(l => l.trim()).filter(Boolean);
      const data = window.WeeklyCoachBriefData.buildWeeklyCoachBriefData({
        athleteName: athlete?.name || null,
        dateRange: { fromDate, toDate },
        confirmedResults,
        trainingLogs,
        manualNotes,
      });
      if (alive) setBriefData(data);
    })();
    return () => { alive = false; };
  }, [athleteId, fromDate, toDate, manualNotesText, confirmedResults, athlete]);

  const markdown = wbpM(
    () => wbpRenderMarkdown(briefData, athlete?.name, fromDate, toDate),
    [briefData, athlete, fromDate, toDate]
  );

  const handleCopy = () => {
    if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
      navigator.clipboard.writeText(markdown)
        .then(() => { setCopyState('copied'); setTimeout(() => setCopyState('idle'), 2000); })
        .catch(() => setCopyState('failed'));
    } else {
      setCopyState('failed');
    }
  };

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, zIndex: 2000,
      background: 'rgba(15,18,15,.45)',
      display: 'grid', placeItems: 'center', padding: 20,
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        background: 'var(--mac-panel-strong, var(--panel))',
        border: '1px solid var(--mac-stroke, var(--border))',
        borderRadius: 16,
        width: 'min(760px, 96vw)',
        maxHeight: '90vh',
        display: 'flex',
        flexDirection: 'column',
        overflow: 'hidden',
      }}>
        <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--mac-stroke, var(--border))', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <div style={{ fontSize: 15, fontWeight: 700, color: 'var(--text)' }}>Generate Coach Brief / 生成教练周简报</div>
            <div style={{ fontSize: 11.5, color: 'var(--muted)', marginTop: 2 }}>Read-only preview. No suggestions generated. / 只读预览，不生成建议。</div>
          </div>
          <button onClick={onClose} style={{ background: 'none', border: 0, color: 'var(--muted)', fontSize: 20, cursor: 'pointer' }}>×</button>
        </div>

        <div style={{ padding: '14px 18px', display: 'grid', gap: 10, borderBottom: '1px solid var(--mac-stroke, var(--border))' }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10 }}>
            <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
              <span style={{ fontSize: 10, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.05em' }}>Athlete</span>
              <select value={athleteId} onChange={e => setAthleteId(e.target.value)} style={{ padding: '6px 8px', borderRadius: 6, border: '1px solid var(--mac-stroke, var(--border))', fontSize: 12 }}>
                {athletes.map(a => <option key={a.id} value={a.id}>{a.name}</option>)}
              </select>
            </label>
            <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
              <span style={{ fontSize: 10, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.05em' }}>From date</span>
              <input type="date" value={fromDate} onChange={e => setFromDate(e.target.value)} style={{ padding: '6px 8px', borderRadius: 6, border: '1px solid var(--mac-stroke, var(--border))', fontSize: 12 }}/>
            </label>
            <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
              <span style={{ fontSize: 10, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.05em' }}>To date</span>
              <input type="date" value={toDate} onChange={e => setToDate(e.target.value)} style={{ padding: '6px 8px', borderRadius: 6, border: '1px solid var(--mac-stroke, var(--border))', fontSize: 12 }}/>
            </label>
          </div>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
            <span style={{ fontSize: 10, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.05em' }}>Manual notes (one per line) / 手动备注（每行一条）</span>
            <textarea
              value={manualNotesText}
              onChange={e => setManualNotesText(e.target.value)}
              rows={3}
              style={{ padding: '6px 8px', borderRadius: 6, border: '1px solid var(--mac-stroke, var(--border))', fontSize: 12, fontFamily: 'inherit', resize: 'vertical' }}
            />
          </label>
        </div>

        <div style={{ padding: '14px 18px', overflow: 'auto', flex: 1 }}>
          <pre style={{
            margin: 0,
            fontFamily: 'var(--font-mono, ui-monospace, monospace)',
            fontSize: 12,
            lineHeight: 1.5,
            whiteSpace: 'pre-wrap',
            wordBreak: 'break-word',
            color: 'var(--text)',
            background: 'var(--mac-panel-strong, var(--panel))',
            border: '1px solid var(--mac-stroke, var(--border))',
            borderRadius: 10,
            padding: 12,
            maxHeight: '48vh',
            overflow: 'auto',
          }}>{markdown}</pre>
        </div>

        <div style={{ padding: '12px 18px', borderTop: '1px solid var(--mac-stroke, var(--border))', display: 'flex', justifyContent: 'flex-end', gap: 8, alignItems: 'center' }}>
          {copyState === 'copied' && <span style={{ fontSize: 11.5, color: 'var(--pos, #16a34a)' }}>Copied / 已复制</span>}
          {copyState === 'failed' && <span style={{ fontSize: 11.5, color: '#9f1239' }}>Copy failed — select the text above and copy manually. / 复制失败，请手动选中文本复制。</span>}
          <button type="button" className="btn" onClick={handleCopy} style={{ padding: '7px 14px', fontSize: 12 }}>Copy Markdown / 复制Markdown</button>
          <button type="button" className="btn" onClick={onClose} style={{ padding: '7px 14px', fontSize: 12 }}>Close / 关闭</button>
        </div>
      </div>
    </div>
  );
}

if (typeof window !== 'undefined') window.WeeklyBriefPreviewModal = WeeklyBriefPreviewModal;
