// 6W Tracking — weekly tables & product cards (split from 6w.jsx).
// EmWeeklyTable, WeekEntryModal, OtherProducts, FollowUpCard.
// Owns window.SixWView export.

// ============== EM Weekly Table (with OCR upload) ==============
function SixWEmWeeklyTable({ customer, onUpdate, weeks, title, tone }) {
  const toneCfg = tone === 'emerald'
    ? { color: '#10B981', tint: '#E7F8F1', headBg: '#D1FAE5' }
    : { color: '#2F5DE5', tint: '#EEF4FF', headBg: '#DBEAFE' };

  const tableKey = title === 'EM6W' ? 'em6w' : 'em13w';
  const data = customer[tableKey] || {};

  const [popupOpen, setPopupOpen] = useState(false);
  const [toast, setToast] = useState(null);

  const setCell = (week, metricId, val) => {
    onUpdate({ [tableKey]: { ...data, [week]: { ...(data[week] || {}), [metricId]: val } } });
  };
  const findNextWeek = () => weeks.find(w => !data[w]?.date) || weeks[weeks.length - 1];
  const applyValues = (weekKey, values, source) => {
    onUpdate({ [tableKey]: { ...data, [weekKey]: { ...(data[weekKey] || {}), ...values } } });
    setToast({ msg: `${source} → กรอก ${weekKey} เรียบร้อย`, week: weekKey });
    setTimeout(() => setToast(null), 3000);
  };

  const baseline = parseFloat(data[weeks[0]]?.uu);
  const last = [...weeks].reverse().map(w => data[w]?.uu).find(v => v);
  const loss = baseline && last ? (baseline - parseFloat(last)).toFixed(1) : null;

  return (
    <Card pad={false} className="relative">
      <div className="px-4 py-2 flex items-center justify-between border-b border-ink-100" style={{ background: toneCfg.tint }}>
        <h3 className="text-sm font-extrabold tracking-wide" style={{ color: toneCfg.color }}>
          {title === 'EM6W' ? 'EM6W / Weekly Body Stats' : 'EM13W · ต่อเนื่อง W7-W13'}
        </h3>
        <div className="flex items-center gap-2">
          {loss && (
            <Pill color={toneCfg.color} tint="white" size="xs" icon={<Icon name="weight" className="w-3 h-3" />}>
              <span className="num">▼{loss} kg</span>
            </Pill>
          )}
          <button onClick={() => setPopupOpen(true)} title="เพิ่มข้อมูลสัปดาห์ใหม่ — อัปโหลดรูปหรือกรอกเอง"
            className="w-8 h-8 rounded-lg flex items-center justify-center transition-all hover:opacity-90"
            style={{ background: toneCfg.color, color: 'white' }}>
            <SixWUploadCameraIcon className="w-4 h-4" />
          </button>
        </div>
      </div>
      <div className="overflow-x-auto scroll-thin">
        <table className="w-full text-xs num">
          <thead>
            <tr style={{ background: toneCfg.headBg }}>
              <th className="text-right font-bold text-ink-700 px-3 py-2 w-24"></th>
              {weeks.map(w => (
                <th key={w} className={`text-center font-bold px-1 py-2 transition-colors ${toast?.week === w ? 'animate-pulse' : ''}`}
                    style={{ color: toneCfg.color, minWidth: 64, background: toast?.week === w ? 'rgba(16,185,129,0.18)' : 'transparent' }}>
                  {w}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {SIXW_METRIC_ROWS.map((m, i) => (
              <tr key={m.id} className={i % 2 === 1 ? 'bg-ink-50/40' : ''}>
                <td className={`px-3 py-1 text-right font-medium ${m.accent ? 'text-ink-900' : 'text-ink-600'}`}
                    style={m.bold ? { fontWeight: 700 } : {}}>
                  <div className="leading-tight">
                    <div className={m.bold ? 'text-sm' : ''}>{m.label}</div>
                    <div className="text-[9px] text-ink-400 font-normal">{m.sub}</div>
                  </div>
                </td>
                {weeks.map(w => {
                  const val = data[w]?.[m.id] || '';
                  const isJustFilled = toast?.week === w;
                  return (
                    <td key={w} className="px-0.5 py-0.5 border-l border-ink-100">
                      <input value={val} onChange={e => setCell(w, m.id, e.target.value)}
                        className={`w-full px-1 py-1 text-center bg-transparent rounded outline-none focus:bg-white focus:ring-2 hover:bg-white/50 transition-all ${m.bold ? 'font-bold' : 'font-medium text-ink-700'} ${isJustFilled ? 'bg-emerald-50/80' : ''}`}
                        style={{
                          color: val && m.bold ? toneCfg.color : (val ? '#0F1E38' : '#94A3B8'),
                          '--tw-ring-color': toneCfg.color + '40',
                        }} />
                    </td>
                  );
                })}
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {popupOpen && (
        <SixWWeekEntryModal weeks={weeks} defaultWeek={findNextWeek()} customer={customer}
          tone={toneCfg} tableName={title} existingData={data}
          onClose={() => setPopupOpen(false)}
          onApply={(weekKey, values, source) => { applyValues(weekKey, values, source); setPopupOpen(false); }} />
      )}

      {toast && (
        <div className="absolute top-2 left-1/2 -translate-x-1/2 bg-white shadow-lift border border-emerald-200 rounded-full px-3 py-1.5 flex items-center gap-2 z-10 animate-[fadeInDown_.2s_ease]">
          <div className="w-5 h-5 rounded-full bg-emerald-500 flex items-center justify-center">
            <Icon name="check" className="w-3 h-3 text-white" strokeWidth={3} />
          </div>
          <span className="text-[11px] font-medium text-ink-800">{toast.msg}</span>
        </div>
      )}
      <style>{`@keyframes fadeInDown { from { opacity: 0; transform: translate(-50%, -8px); } to { opacity: 1; transform: translate(-50%, 0); } }`}</style>
    </Card>
  );
}

// ============== Week Entry Modal (Upload + OCR / Manual) ==============
function SixWWeekEntryModal({ weeks, defaultWeek, customer, tone, tableName, existingData, onClose, onApply }) {
  const [mode, setMode] = useState('upload');
  const [weekKey, setWeekKey] = useState(defaultWeek);

  const [imgUrl, setImgUrl] = useState(null);
  const [fileName, setFileName] = useState('');
  const [ocrStage, setOcrStage] = useState('idle');
  const [extracted, setExtracted] = useState(null);
  const fileRef = useRef(null);

  const today = new Date();
  const todayStr = _sixwFormatThaiDate(today);
  const [form, setForm] = useState({
    date: existingData[weekKey]?.date || todayStr,
    uu: existingData[weekKey]?.uu || '',
    fat: existingData[weekKey]?.fat || '',
    vfat: existingData[weekKey]?.vfat || '',
    muscle: existingData[weekKey]?.muscle || '',
    age: existingData[weekKey]?.age || '',
    bmi: existingData[weekKey]?.bmi || '',
  });

  useEffect(() => {
    setForm({
      date: existingData[weekKey]?.date || todayStr,
      uu: existingData[weekKey]?.uu || '',
      fat: existingData[weekKey]?.fat || '',
      vfat: existingData[weekKey]?.vfat || '',
      muscle: existingData[weekKey]?.muscle || '',
      age: existingData[weekKey]?.age || '',
      bmi: existingData[weekKey]?.bmi || '',
    });
  }, [weekKey]);

  const simulateOcr = (file) => {
    setOcrStage('processing');
    setTimeout(() => {
      const weekIdx = ['Before','W1','W2','W3','W4','W5','W6','W7','W8','W9','W10','W11','W12','W13'].indexOf(weekKey);
      const baseline = customer.em6w?.Before?.uu ? parseFloat(customer.em6w.Before.uu) : 78;
      const newWeight = (baseline - 0.9 * weekIdx).toFixed(1);
      const ht = Number(customer.height) || 160;
      setExtracted({
        date: todayStr,
        uu: newWeight,
        fat: (32 - weekIdx * 0.7).toFixed(0),
        vfat: Math.max(8, (14 - weekIdx * 0.4)).toFixed(0),
        muscle: (24 + weekIdx * 0.3).toFixed(1),
        age: Math.max(35, (42 - weekIdx * 0.5)).toFixed(0),
        bmi: (newWeight / Math.pow(ht / 100, 2)).toFixed(1),
      });
      setOcrStage('done');
    }, 1400);
  };

  const handleFile = (file) => {
    if (!file) return;
    setFileName(file.name);
    setImgUrl(URL.createObjectURL(file));
    simulateOcr(file);
  };

  const applyUpload = () => { if (extracted) onApply(weekKey, extracted, `OCR · ${fileName}`); };
  const applyManual = () => {
    const vals = { ...form };
    if (!vals.bmi && vals.uu && customer.height) {
      vals.bmi = (parseFloat(vals.uu) / Math.pow(Number(customer.height) / 100, 2)).toFixed(1);
    }
    onApply(weekKey, vals, 'กรอกเอง');
  };

  return (
    <Modal open={true} onClose={onClose} size="lg" title={
      <div className="flex items-center gap-2">
        <div className="w-7 h-7 rounded-md flex items-center justify-center text-white" style={{ background: tone.color }}>
          <SixWUploadCameraIcon className="w-4 h-4" />
        </div>
        <div>
          <div className="text-sm font-semibold text-ink-900">เพิ่มข้อมูลรายสัปดาห์</div>
          <div className="text-[10px] text-ink-400 uppercase tracking-wider font-semibold">{customer.name} · {tableName} · {weekKey}</div>
        </div>
      </div>
    } footer={
      <div className="flex items-center justify-between">
        <span className="text-[11px] text-ink-400">
          {mode === 'upload' && ocrStage === 'idle' && 'ลากรูปจากเครื่องชั่ง / InBody / Tanita / Xiaomi'}
          {mode === 'upload' && ocrStage === 'processing' && 'กำลังอ่านค่า…'}
          {mode === 'upload' && ocrStage === 'done' && 'ตรวจค่าและกดบันทึก'}
          {mode === 'manual' && 'กรอกข้อมูลด้วยตัวเอง'}
        </span>
        <div className="flex items-center gap-2">
          <Btn variant="ghost" size="sm" onClick={onClose}>ยกเลิก</Btn>
          {mode === 'upload' && ocrStage === 'done' && (
            <Btn variant="brand" size="sm" icon={<Icon name="check" className="w-3.5 h-3.5" />} onClick={applyUpload}>บันทึกใน {weekKey}</Btn>
          )}
          {mode === 'manual' && (
            <Btn variant="brand" size="sm" icon={<Icon name="check" className="w-3.5 h-3.5" />} onClick={applyManual}>บันทึกใน {weekKey}</Btn>
          )}
        </div>
      </div>
    }>
      <div className="space-y-4">
        {/* Week selector */}
        <div className="flex items-center gap-2 flex-wrap">
          <span className="text-[10px] uppercase tracking-wider text-ink-500 font-semibold">สัปดาห์:</span>
          {weeks.map(w => (
            <button key={w} onClick={() => setWeekKey(w)}
              className={`px-2.5 py-1 rounded-md text-[11px] font-semibold border transition-all ${weekKey === w ? 'border-transparent text-white' : 'border-ink-200 bg-white text-ink-600 hover:border-ink-300'}`}
              style={weekKey === w ? { background: tone.color } : {}}>
              {w}
            </button>
          ))}
        </div>

        <div className="grid grid-cols-2 gap-2 p-1 bg-ink-100/70 rounded-xl">
          <button onClick={() => setMode('upload')}
            className={`py-2 px-3 rounded-lg text-xs font-semibold transition-all flex items-center justify-center gap-1.5 ${mode === 'upload' ? 'bg-white shadow-card text-ink-900' : 'text-ink-500'}`}>
            <SixWUploadCameraIcon className="w-3.5 h-3.5" /> อัปโหลดรูปผลชั่ง
          </button>
          <button onClick={() => setMode('manual')}
            className={`py-2 px-3 rounded-lg text-xs font-semibold transition-all flex items-center justify-center gap-1.5 ${mode === 'manual' ? 'bg-white shadow-card text-ink-900' : 'text-ink-500'}`}>
            <svg viewBox="0 0 24 24" className="w-3.5 h-3.5" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
              <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
            </svg>
            กรอกค่าเอง
          </button>
        </div>

        {mode === 'upload' && (
          <div className="space-y-3">
            {ocrStage === 'idle' && (
              <div onClick={() => fileRef.current?.click()}
                onDragOver={e => e.preventDefault()}
                onDrop={e => { e.preventDefault(); handleFile(e.dataTransfer.files?.[0]); }}
                className="border-2 border-dashed rounded-xl p-8 text-center cursor-pointer transition-colors hover:bg-emerald-50/30"
                style={{ borderColor: tone.color + '60' }}>
                <div className="w-12 h-12 rounded-full flex items-center justify-center mx-auto mb-3" style={{ background: tone.color + '20' }}>
                  <SixWUploadCameraIcon className="w-6 h-6" style={{ color: tone.color }} />
                </div>
                <div className="text-sm font-semibold text-ink-900">คลิก หรือ ลากรูปมาวาง</div>
                <div className="text-[11px] text-ink-500 mt-1">หน้าจอเครื่องชั่ง / แอป InBody / Tanita / Xiaomi Body Composition</div>
                <input ref={fileRef} type="file" accept="image/*" className="hidden"
                  onChange={e => { handleFile(e.target.files?.[0]); e.target.value = ''; }} />
              </div>
            )}

            {ocrStage === 'processing' && (
              <div className="rounded-xl p-6 flex flex-col items-center justify-center" style={{ background: tone.color + '0F' }}>
                <svg className="w-10 h-10 animate-spin mb-3" viewBox="0 0 24 24" fill="none" stroke={tone.color} strokeWidth="2.5">
                  <path d="M12 4v4M12 16v4M4 12h4M16 12h4M6 6l3 3M15 15l3 3M6 18l3-3M15 9l3-3" strokeLinecap="round" />
                </svg>
                <div className="text-sm font-semibold" style={{ color: tone.color }}>กำลังอ่านค่าจากรูป…</div>
                <div className="text-[11px] text-ink-500 mt-1">{fileName}</div>
              </div>
            )}

            {ocrStage === 'done' && extracted && (
              <div className="grid grid-cols-12 gap-3">
                <div className="col-span-5">
                  <div className="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1.5">รูปที่อัปโหลด</div>
                  <div className="rounded-lg overflow-hidden bg-ink-100 aspect-square flex items-center justify-center">
                    {imgUrl ? <img src={imgUrl} alt="" className="w-full h-full object-cover" /> : <SixWUploadCameraIcon className="w-10 h-10 text-ink-300" />}
                  </div>
                  <div className="text-[10px] text-ink-400 mt-1.5 truncate">{fileName}</div>
                  <button onClick={() => { setOcrStage('idle'); setImgUrl(null); setExtracted(null); setFileName(''); }}
                    className="text-[10px] text-ink-500 hover:text-ink-900 mt-1 underline">เปลี่ยนรูป</button>
                </div>
                <div className="col-span-7">
                  <div className="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1.5">ค่าที่อ่านได้ (แก้ไขได้)</div>
                  <div className="space-y-1.5">
                    {SIXW_METRIC_ROWS.map(m => (
                      <div key={m.id} className="flex items-center gap-2">
                        <label className="text-[11px] text-ink-600 w-16 flex-shrink-0">{m.label}</label>
                        {m.id === 'date' ? (
                          <SixWDatePickerInput value={extracted[m.id] || ''} onChange={v => setExtracted({ ...extracted, date: v })}
                            tone={tone.color} className="flex-1" style={{ height: '28px' }} />
                        ) : (
                          <input value={extracted[m.id] || ''} onChange={e => setExtracted({ ...extracted, [m.id]: e.target.value })}
                            className="flex-1 h-7 px-2 text-xs num border border-ink-200 rounded-md outline-none focus:ring-2 bg-white"
                            style={{ '--tw-ring-color': tone.color + '40' }} />
                        )}
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            )}
          </div>
        )}

        {mode === 'manual' && (
          <div className="grid grid-cols-2 gap-3">
            {SIXW_METRIC_ROWS.map(m => (
              <div key={m.id}>
                <label className="text-[10px] uppercase tracking-wider text-ink-500 font-semibold block mb-1">
                  {m.label} {m.sub && <span className="text-ink-400 normal-case">({m.sub})</span>}
                </label>
                {m.id === 'date' ? (
                  <SixWDatePickerInput value={form[m.id] || ''} onChange={v => setForm({ ...form, date: v })} tone={tone.color} />
                ) : (
                  <input value={form[m.id] || ''} onChange={e => setForm({ ...form, [m.id]: e.target.value })}
                    placeholder={m.id === 'uu' ? '73.1' : ''}
                    className="w-full h-9 px-3 text-sm num border border-ink-200 rounded-lg outline-none focus:ring-2 bg-white"
                    style={{ '--tw-ring-color': tone.color + '40', borderColor: form[m.id] ? tone.color + '80' : '#C9D2E3' }} />
                )}
              </div>
            ))}
            <div className="col-span-2 text-[10px] text-ink-400 flex items-center gap-1.5">
              <Icon name="info" className="w-3 h-3" />
              BMI จะคำนวณอัตโนมัติจากน้ำหนัก + ส่วนสูง ({customer.height || '?'} cm) ถ้าเว้นว่างไว้
            </div>
          </div>
        )}
      </div>
    </Modal>
  );
}

function SixWUploadCameraIcon({ className = 'w-4 h-4', style }) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className} style={style}>
      <path d="M3 8h3l2-3h8l2 3h3a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1z" />
      <path d="M12 17v-7M9 12l3-3 3 3" />
    </svg>
  );
}

// ============== Other Products ==============
function SixWOtherProductsCard({ customer, onUpdate }) {
  const toggle = (prod, key) => {
    const cur = customer.products?.[prod] || { listened:false, used:false, rebuy:false, note:'' };
    onUpdate({ products: { ...(customer.products || {}), [prod]: { ...cur, [key]: !cur[key] } } });
  };
  const setNote = (prod, val) => {
    const cur = customer.products?.[prod] || { listened:false, used:false, rebuy:false, note:'' };
    onUpdate({ products: { ...(customer.products || {}), [prod]: { ...cur, note: val } } });
  };

  return (
    <Card pad={false}>
      <div className="px-4 py-2.5 border-b border-ink-100 flex items-center justify-between bg-gradient-to-r from-ink-50 to-white">
        <h3 className="text-sm font-extrabold tracking-wide text-ink-900">สินค้าอื่นๆ ที่สนใจ</h3>
        <span className="text-[10px] text-ink-400">ติ๊กสถานะของแต่ละสินค้า</span>
      </div>
      <table className="w-full text-xs">
        <thead>
          <tr className="bg-ink-50/60 border-b border-ink-100">
            <th className="text-right font-semibold text-ink-700 px-3 py-2"></th>
            {['เคยฟัง','ใช้แล้ว','ซื้อซ้ำ'].map(h => (
              <th key={h} className="text-center font-semibold text-ink-700 px-1 py-2 w-14">{h}</th>
            ))}
            <th className="text-left font-semibold text-ink-700 px-2 py-2">หมายเหตุ</th>
          </tr>
        </thead>
        <tbody>
          {SIXW_PRODUCT_LIST.map((prod, i) => {
            const p = (customer.products || {})[prod] || {};
            return (
              <tr key={prod} className={`border-b border-ink-100 ${i % 2 === 1 ? 'bg-ink-50/30' : ''}`}>
                <td className="px-3 py-1.5 text-right text-xs font-medium text-ink-700 whitespace-nowrap">{prod}</td>
                {['listened','used','rebuy'].map(k => (
                  <td key={k} className="text-center px-0.5 py-1 border-l border-ink-100">
                    <button onClick={() => toggle(prod, k)}
                      className={`w-5 h-5 rounded-sm border-2 inline-flex items-center justify-center transition-all ${p[k] ? (k==='rebuy' ? 'bg-emerald-500 border-emerald-500' : k==='used' ? 'bg-brand-500 border-brand-500' : 'bg-ink-700 border-ink-700') : 'border-ink-300 bg-white hover:border-ink-500'}`}>
                      {p[k] && <Icon name="check" className="w-3 h-3 text-white" strokeWidth={3} />}
                    </button>
                  </td>
                ))}
                <td className="px-2 py-1 border-l border-ink-100">
                  <input value={p.note || ''} onChange={e => setNote(prod, e.target.value)}
                    placeholder="—"
                    className="w-full px-1 py-0.5 bg-transparent text-[11px] text-ink-700 outline-none rounded focus:bg-white focus:ring-2 focus:ring-brand-500/30 transition-all" />
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </Card>
  );
}

// ============== Follow Up Timeline ==============
function SixWFollowUpCard({ customer, onUpdate }) {
  const [newNote, setNewNote] = useState('');
  const list = customer.followup || [];

  const addNote = () => {
    if (!newNote.trim()) return;
    const today = new Date();
    const date = `${String(today.getDate()).padStart(2,'0')} ${['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.','ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'][today.getMonth()]}`;
    onUpdate({ followup: [{ date, note: newNote }, ...list] });
    setNewNote('');
  };
  const removeNote = (idx) => onUpdate({ followup: list.filter((_, i) => i !== idx) });

  return (
    <Card pad={false}>
      <div className="px-4 py-2.5 border-b border-ink-100 flex items-center justify-between bg-gradient-to-r from-rose-50/40 to-white">
        <h3 className="text-sm font-extrabold tracking-wide text-ink-900">📒 Follow Up Timeline</h3>
        <span className="text-[10px] text-ink-400 num">{list.length} entries</span>
      </div>
      <div className="p-4 space-y-3">
        <div className="flex gap-2">
          <input value={newNote} onChange={e => setNewNote(e.target.value)}
            onKeyDown={e => e.key === 'Enter' && addNote()}
            placeholder="พิมพ์โน้ตใหม่ + Enter เพื่อบันทึก..."
            className="flex-1 h-9 px-3 text-xs border border-ink-200 rounded-lg outline-none focus:border-brand-500 focus:ring-2 focus:ring-brand-500/20 bg-white" />
          <Btn variant="brand" size="sm" icon={<Icon name="plus" className="w-3 h-3" />} onClick={addNote}>เพิ่ม</Btn>
        </div>
        <div className="space-y-0">
          {list.length === 0 ? (
            <div className="text-center py-8 text-[11px] text-ink-400">ยังไม่มีบันทึก follow up</div>
          ) : list.map((entry, i) => (
            <div key={i} className="group flex items-start gap-3 py-2.5 border-b border-dashed border-ink-100 last:border-b-0">
              <div className="flex flex-col items-center flex-shrink-0">
                <div className="w-2 h-2 rounded-full bg-rose-400 mt-1.5" />
                {i < list.length - 1 && <div className="w-px flex-1 bg-ink-100 mt-1" />}
              </div>
              <div className="flex-1 min-w-0">
                <div className="text-[10px] uppercase tracking-wider text-rose-600 font-bold">{entry.date}</div>
                <div className="text-xs text-ink-800 leading-relaxed mt-0.5">{entry.note}</div>
              </div>
              <button onClick={() => removeNote(i)}
                className="opacity-0 group-hover:opacity-100 w-5 h-5 rounded text-ink-300 hover:bg-rose-50 hover:text-rose-500 flex items-center justify-center transition-all flex-shrink-0">
                <Icon name="x" className="w-3 h-3" />
              </button>
            </div>
          ))}
        </div>
      </div>
    </Card>
  );
}

window.SixWView = SixWView;
