// ABO Tracking — funnel & waiting-stage cards (split from abo.jsx).
// PipelineFunnel, GroupReportModal, WaitingStages, EmBeginFollowUpCard.

// ======================== Pipeline Funnel ========================
// Each tile shows the count of people who STILL NEED to be followed up to
// reach this stage (waitingGate), not the count currently sitting at that
// stage. Clicking a tile filters the sheet to those same waiting people.
function PipelineFunnel({ people, stageFilter, onStageClick }) {
  const counts = VISIBLE_STAGES.map(s => people.filter(p => s.waitingGate?.(p)).length);
  const max = Math.max(1, ...counts);

  return (
    <Card pad={false}>
      <div className="px-5 pt-4 pb-3 flex items-center justify-between border-b border-ink-100">
        <div className="flex items-center gap-2">
          <Icon name="arrowR" className="w-4 h-4 text-brand-600" />
          <h3 className="text-sm font-semibold text-ink-800">Pipeline · เส้นทาง follow up</h3>
          <span className="text-[11px] text-ink-400">คลิก stage เพื่อกรองรายชื่อ</span>
        </div>
        <span className="text-[11px] num text-ink-500">{people.length} คน</span>
      </div>
      <div className="p-5 grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-2 items-stretch">
        {VISIBLE_STAGES.map((s, i) => {
          const c = counts[i];
          const isActive = stageFilter === s.id;
          const ratio = c / max;
          return (
            <button key={s.id} onClick={() => onStageClick(s.id)}
              className={`relative text-left rounded-xl border-2 p-3 transition-all ${isActive ? 'shadow-lift' : 'border-transparent hover:border-ink-200'}`}
              style={{
                background: isActive ? s.color + '15' : 'white',
                borderColor: isActive ? s.color : undefined,
                boxShadow: !isActive ? '0 0 0 1px rgba(15,30,56,0.05)' : undefined,
              }}>
              <div className="flex items-center gap-1.5 mb-2">
                <div className="w-5 h-5 rounded-md flex items-center justify-center text-white text-[9px] font-bold" style={{ background: s.color }}>
                  {i + 1}
                </div>
                <span className="text-[10px] font-bold uppercase tracking-wider" style={{ color: s.color }}>{s.short}</span>
                {s.id === 's1' && <span className="text-[10px] text-gold-600">★</span>}
              </div>
              <div className="text-2xl font-semibold num text-ink-900 leading-none">{c}</div>
              <div className="mt-2 h-1 rounded-full overflow-hidden bg-ink-100">
                <div className="h-full rounded-full" style={{ width: `${ratio * 100}%`, background: s.color }} />
              </div>
              {i < VISIBLE_STAGES.length - 1 && (
                <div className="absolute top-1/2 -right-2 -translate-y-1/2 z-10 pointer-events-none hidden sm:block">
                  <div className="w-3 h-3 bg-white border-r border-b border-ink-200 rotate-[-45deg]" />
                </div>
              )}
            </button>
          );
        })}
      </div>
    </Card>
  );
}

// ======================== Waiting at each stage (2Y / Check in / Em Guide) ========================
// Renders one card per stage that has a `waitingGate` AND has at least one
// person matching it. If everyone is caught up at every gated stage, we
// show a single "all clear" card.
// The "ต้องเข้า X" cards stay hidden by default — they only show when the
// user clicks a stage tile in the PipelineFunnel above. That way the
// reminder area is quiet until you actively drill into a stage.
// BT never gets a card (it's only counted in the funnel).
// ======================== Group report / ส่งการบ้าน ========================
// Summary popup: for the chosen class/condition, list everyone in the filter
// grouped by who their upline (sponsor) is, showing attended ✅ + camera 📷.
// Produces a copy-ready text block to paste into the homework group chat.
const GR_HEART = ['💖', '🩵', '🤍', '💛', '💚', '🧡', '💜', '❤️', '🩷', '💙'];
function GroupReportModal({ stage, people, currentUser, onClose, onToast }) {
  // For EM Begin (s4) the user picks which of the 4 classes to report on.
  const EM_CLASSES = (FU_GROUPS.find(g => g.id === 'meeting')?.cols) || [];
  const isEmBegin = stage?.id === 's4';
  const [classId, setClassId] = useState(isEmBegin ? 'mtg1' : null);

  // Manual overrides — both attendance and camera are editable in the popup,
  // defaulting to whatever the ABO Tracking data already says. Keyed by id.
  const [att, setAtt] = useState({});       // id → bool
  const [camera, setCamera] = useState({}); // id → bool
  const [reason, setReason] = useState({}); // id → string (why absent)

  // Pool = only people who haven't yet attended the chosen class/stage in the
  // data — that's who you still need to chase. EM Begin: BM+BI done, not
  // MFinity'd, and the selected class still un-ticked.
  const pool = useMemo(() => {
    if (isEmBegin) return people.filter(p => !!p.filled.bmodel && !!p.filled.bincome && !p.filled.bt3 && !p.filled[classId]);
    return people.filter(p => stage?.waitingGate?.(p));
  }, [people, stage, isEmBegin, classId]);

  // Default: everyone เข้า + เปิดกล้อง — the user unchecks whoever was absent.
  // Reset overrides when the class changes.
  const dataAttended = () => true;
  useEffect(() => { setAtt({}); setCamera({}); setReason({}); }, [classId]);

  const attendedOf = (p) => (p.id in att) ? att[p.id] : dataAttended(p);
  const camOf = (p) => (p.id in camera) ? camera[p.id] : attendedOf(p);
  const reasonOf = (p) => reason[p.id] || '';
  // Which EM Begin attendance this class is for the person: classes already
  // done + 1. 1 → ครั้งแรก, 4 → ครั้งสุดท้าย, else ครั้งที่ N. EM Begin only.
  const attemptLabel = (p) => {
    const n = _mtgDone(p) + 1;
    if (n <= 1) return 'ครั้งแรก';
    if (n >= 4) return 'ครั้งสุดท้าย';
    return `ครั้งที่ ${n}`;
  };
  const toggleAtt = (p) => setAtt(prev => ({ ...prev, [p.id]: !attendedOf(p) }));
  const toggleCam = (p) => setCamera(prev => ({ ...prev, [p.id]: !camOf(p) }));

  // Group by sponsor (upline). sponsorId null → top group under the coach.
  const byId = useMemo(() => new Map(people.map(p => [p.id, p])), [people]);
  const groups = useMemo(() => {
    const m = new Map(); // sponsorId|'_top' → { name, members[] }
    for (const p of pool) {
      const key = p.sponsorId || '_top';
      const name = p.sponsorId ? (byId.get(p.sponsorId)?.name || 'อัปไลน์') : 'Front Line ติดตัว';
      if (!m.has(key)) m.set(key, { name, members: [] });
      m.get(key).members.push(p);
    }
    // top group first, then alpha
    return [...m.entries()].sort((a, b) => (a[0] === '_top' ? -1 : b[0] === '_top' ? 1 : a[1].name.localeCompare(b[1].name)));
  }, [pool, byId]);

  const classLabel = isEmBegin ? (EM_CLASSES.find(c => c.id === classId)?.label || '') : stage?.short;
  const attendedCount = pool.filter(attendedOf).length;

  // Build the copy text.
  const buildText = () => {
    const absentCount = pool.length - attendedCount;
    const camOffCount = pool.filter(p => attendedOf(p) && !camOf(p)).length;
    const lines = [];
    lines.push(`📋 สรุปการบ้าน · ${classLabel}`);
    lines.push(`✅ เข้าเรียน ${attendedCount}/${pool.length} คน · ❌ ขาด ${absentCount} คน`);
    lines.push(`🚫 ปิดกล้อง ${camOffCount} คน`);
    lines.push('');
    groups.forEach(([, g], gi) => {
      lines.push(`${GR_HEART[gi % GR_HEART.length]} ${g.name === 'Front Line ติดตัว' ? 'Front Line ติดตัว' : 'ของ ' + g.name}`);
      g.members.forEach((p, i) => {
        const att = attendedOf(p);
        const cam = camOf(p);
        const why = !att && reasonOf(p).trim() ? ` (${reasonOf(p).trim()})` : '';
        const times = isEmBegin ? ` · ${attemptLabel(p)}` : '';
        lines.push(`${i + 1}.${p.name}${times} ${att ? '✅' : '❌'}${att ? (cam ? ' 📷' : ' 🚫กล้อง') : why}`);
      });
      lines.push('');
    });
    return lines.join('\n').trim();
  };

  const copy = () => { try { navigator.clipboard.writeText(buildText()); } catch {} onToast?.('คัดลอกการบ้านแล้ว · เอาไปวางในกลุ่มได้เลย', '#10B981'); };

  return (
    <div className="fixed inset-0 z-[60] bg-black/40 flex items-center justify-center p-4" onClick={onClose}>
      <div className="bg-white rounded-2xl w-full max-w-lg max-h-[88vh] flex flex-col overflow-hidden" onClick={e => e.stopPropagation()}>
        <div className="px-5 py-4 border-b border-ink-100 flex items-center justify-between" style={{ background: (stage?.color || '#7C3AED') + '12' }}>
          <div>
            <div className="text-sm font-bold text-ink-900">สรุป + ส่งการบ้าน</div>
            <div className="text-[11px] text-ink-500">{classLabel} · เข้าเรียน {attendedCount}/{pool.length} คน · แตะ ✅/❌ เพื่อเช็คชื่อ</div>
          </div>
          <button onClick={onClose} className="text-ink-400 hover:text-ink-700 text-lg leading-none">✕</button>
        </div>

        {/* Class filter (EM Begin only) */}
        {isEmBegin && (
          <div className="px-4 pt-3 flex flex-wrap gap-1.5">
            {EM_CLASSES.map(c => (
              <button key={c.id} onClick={() => setClassId(c.id)}
                className={`px-2.5 h-8 rounded-lg text-[12px] font-semibold transition-all ${classId === c.id ? 'bg-purple-600 text-white' : 'bg-ink-100 text-ink-600 hover:bg-ink-200'}`}>
                {c.label}
              </button>
            ))}
          </div>
        )}

        {/* Grouped list */}
        <div className="flex-1 overflow-y-auto p-4 space-y-3">
          {groups.length === 0 && <div className="text-center text-xs text-ink-400 py-8">ไม่มีคนในกลุ่มนี้</div>}
          {groups.map(([key, g], gi) => (
            <div key={key}>
              <div className="text-[13px] font-bold text-ink-800 mb-1">{GR_HEART[gi % GR_HEART.length]} {g.name === 'Front Line ติดตัว' ? 'Front Line ติดตัว' : 'ของ ' + g.name}</div>
              <div className="space-y-1">
                {g.members.map((p, i) => {
                  const att = attendedOf(p);
                  const cam = camOf(p);
                  return (
                    <div key={p.id} className="px-2.5 py-1.5 rounded-lg bg-ink-50/60">
                      <div className="flex items-center gap-2">
                        <span className="text-[12px] text-ink-400 num w-5 flex-shrink-0">{i + 1}.</span>
                        <div className="flex-1 min-w-0 flex items-center gap-1.5">
                          <span className="text-[13px] font-medium text-ink-800 truncate">{p.name}</span>
                          {isEmBegin && (
                            <span className="text-[10px] font-semibold text-purple-600 bg-purple-50 px-1.5 py-0.5 rounded-full flex-shrink-0">
                              {attemptLabel(p)}
                            </span>
                          )}
                        </div>
                        <button onClick={() => toggleAtt(p)}
                          title="กดเพื่อสลับ เข้า/ขาด"
                          className={`px-2 h-6 rounded text-[11px] font-semibold transition-colors ${att ? 'bg-emerald-100 text-emerald-700' : 'bg-rose-100 text-rose-600'}`}>
                          {att ? '✅ เข้า' : '❌ ขาด'}
                        </button>
                        {att && (
                          <button onClick={() => toggleCam(p)}
                            title="สลับสถานะเปิดกล้อง"
                            className={`px-1.5 h-6 rounded text-[11px] font-medium ${cam ? 'bg-emerald-100 text-emerald-700' : 'bg-ink-200 text-ink-500'}`}>
                            {cam ? '📷 เปิด' : '🚫 ปิด'}
                          </button>
                        )}
                      </div>
                      {!att && (
                        <input
                          value={reasonOf(p)}
                          onChange={e => setReason(prev => ({ ...prev, [p.id]: e.target.value }))}
                          placeholder="เหตุผลที่ขาด (เช่น ติดงาน, ป่วย)..."
                          className="mt-1.5 ml-7 w-[calc(100%-1.75rem)] h-7 px-2 text-[12px] border border-rose-200 rounded-md outline-none focus:border-rose-400 focus:ring-1 focus:ring-rose-300/40 bg-white"
                        />
                      )}
                    </div>
                  );
                })}
              </div>
            </div>
          ))}
        </div>

        {/* Copy */}
        <div className="border-t border-ink-100 p-4">
          <button onClick={copy} className="w-full h-10 rounded-lg bg-gradient-to-r from-purple-600 to-brand-600 text-white text-sm font-bold inline-flex items-center justify-center gap-1.5">📋 คัดลอกการบ้าน</button>
        </div>
      </div>
    </div>
  );
}

function WaitingStages({ people, onMarkInactive, stageFilter, onGroupReport }) {
  if (!stageFilter || stageFilter === 's4') return null;
  const stage = VISIBLE_STAGES.find(s => s.id === stageFilter);
  if (!stage || typeof stage.waitingGate !== 'function') return null;
  const waiting = people.filter(stage.waitingGate);
  if (waiting.length === 0) {
    return (
      <Card className="bg-emerald-50/40 border-emerald-100">
        <div className="flex items-center gap-3">
          <div className="w-10 h-10 rounded-lg bg-emerald-500 text-white flex items-center justify-center">
            <Icon name="check" className="w-5 h-5" />
          </div>
          <div className="flex-1">
            <div className="text-sm font-semibold text-emerald-800">ไม่มีใครต้องตามที่ {stage.short} 🎉</div>
            <div className="text-[11px] text-emerald-700/70">ทุกคนผ่าน {stage.short} แล้ว</div>
          </div>
        </div>
      </Card>
    );
  }
  return <WaitingStageCard stage={stage} waiting={waiting} people={people} onMarkInactive={onMarkInactive} onGroupReport={onGroupReport} />;
}

function WaitingStageCard({ stage, waiting, people, onMarkInactive, onGroupReport }) {
  const byId = new Map((people || []).map(p => [p.id, p]));
  return (
    <Card pad={false} style={{ borderColor: stage.color + '40' }} className="bg-gradient-to-br from-white to-white">
      <div className="px-5 pt-4 pb-3 flex items-center justify-between border-b" style={{ borderColor: stage.color + '22' }}>
        <div className="flex items-center gap-2.5">
          <div className="w-9 h-9 rounded-lg text-white flex items-center justify-center font-bold text-base" style={{ background: stage.color }}>★</div>
          <div>
            <h3 className="text-sm font-semibold text-ink-900">
              ต้องเข้า {stage.short} · <span className="num" style={{ color: stage.color }}>{waiting.length} คน</span>
            </h3>
            <p className="text-[11px] text-ink-500">ยังไม่ได้ติ๊ก {stage.short} — ตามต่อ</p>
          </div>
        </div>
        <Btn variant="gold" size="sm" icon={<Icon name="bell" className="w-3.5 h-3.5" />} onClick={() => onGroupReport?.(stage)}>สรุป + ส่งการบ้าน</Btn>
      </div>
      <div className="p-3 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
        {waiting.map(p => {
          const country = window.COUNTRIES?.find(c => c.id === p.country);
          const upline = p.sponsorId ? byId.get(p.sponsorId) : null;
          return (
            <div key={p.id} className="flex items-center gap-2.5 p-2.5 rounded-lg bg-white border transition-colors"
              style={{ borderColor: stage.color + '20' }}>
              <Avatar user={{ avatar_url: p.photoUrl, avatar: p.name.charAt(p.name.indexOf(' ')+1) || 'ค', color: stage.color }} size={32} />
              <div className="flex-1 min-w-0">
                <div className="flex items-center gap-1.5">
                  <span className="text-xs font-semibold text-ink-900 truncate">{p.name}</span>
                  {country && <span className="text-[11px] leading-none">{country.flag}</span>}
                  {upline && <span className="text-[10px] text-ink-400 truncate">(↑{upline.name})</span>}
                </div>
                <div className="text-[10px] text-ink-400">
                  <span style={{ color: stage.color }}>⏳ {stage.short}</span>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </Card>
  );
}

// ======================== EM Begin follow-up tracker ========================
// Lists who hasn't yet attended each EM Begin class — but only for people
// who:
//   1. have actually finished BM + BI (no point chasing them into a class
//      they haven't met the prerequisite for), and
//   2. haven't reached MFinity (BT ข้อ 3) — once MFinity is ticked the
//      EM Begin group is closed for that person, so they drop out.
//
// EM Begin classes come from the 'meeting' group in FU_GROUPS — the four
// mtg1..mtg4 columns. The card stays hidden when nobody's waiting.
function EmBeginFollowUpCard({ people, onMarkInactive, onGroupReport }) {
  const meetingGroup = FU_GROUPS.find(g => g.id === 'meeting');
  // Lookup so each row can show its upline (UL) name in parentheses.
  const byId = useMemo(() => new Map((people || []).map(p => [p.id, p])), [people]);
  if (!meetingGroup) return null;
  const classes = meetingGroup.cols;

  // BM + BI done, not MFinity'd yet — that's the chase pool.
  const eligible = people.filter(p => !!p.filled.bmodel && !!p.filled.bincome && !p.filled.bt3);

  const groups = classes
    .map(cls => ({ cls, missing: eligible.filter(p => !p.filled[cls.id]) }))
    .filter(g => g.missing.length > 0);

  // Empty state (everyone caught up or already MFinity'd)
  if (groups.length === 0) {
    return (
      <Card className="bg-emerald-50/40 border-emerald-100">
        <div className="flex items-center gap-3">
          <div className="w-10 h-10 rounded-lg bg-emerald-500 text-white flex items-center justify-center">
            <Icon name="check" className="w-5 h-5" />
          </div>
          <div className="flex-1">
            <div className="text-sm font-semibold text-emerald-800">ไม่มีใครต้องตามเข้า EM Begin 🎉</div>
            <div className="text-[11px] text-emerald-700/70">ทุกคนเข้าครบหรือผ่าน MFinity ไปแล้ว</div>
          </div>
        </div>
      </Card>
    );
  }

  const totalMissing = groups.reduce((s, g) => s + g.missing.length, 0);

  return (
    <Card pad={false} style={{ borderColor: meetingGroup.color + '40' }}>
      <div className="px-5 pt-4 pb-3 flex items-center justify-between border-b" style={{ borderColor: meetingGroup.color + '22', background: meetingGroup.tint }}>
        <div className="flex items-center gap-2.5">
          <div className="w-9 h-9 rounded-lg text-white flex items-center justify-center font-bold text-sm" style={{ background: meetingGroup.color }}>EB</div>
          <div>
            <h3 className="text-sm font-semibold text-ink-900">
              ตามเข้าเรียน EM Begin · <span className="num" style={{ color: meetingGroup.color }}>{totalMissing} รายการ</span>
            </h3>
            <p className="text-[11px] text-ink-500">
              เฉพาะคนที่ยังไม่ผ่าน MFinity · กลุ่มจะปิดอัตโนมัติเมื่อติ๊ก MFinity
            </p>
          </div>
        </div>
        <div className="flex items-center gap-2">
          <Pill color={meetingGroup.color} tint="white" size="xs">{eligible.length} คน eligible</Pill>
          <Btn variant="gold" size="sm" icon={<Icon name="bell" className="w-3.5 h-3.5" />} onClick={() => onGroupReport?.()}>สรุป + ส่งการบ้าน</Btn>
        </div>
      </div>
      <div className="p-3 space-y-3">
        {groups.map(({ cls, missing }) => (
          <div key={cls.id} className="rounded-lg border" style={{ borderColor: meetingGroup.color + '20' }}>
            <div className="px-3 py-2 flex items-center justify-between border-b" style={{ borderColor: meetingGroup.color + '15', background: meetingGroup.tint + '80' }}>
              <div className="text-[11px] font-bold uppercase tracking-wider" style={{ color: meetingGroup.color }}>
                {cls.label} <span className="num text-ink-500 font-medium normal-case">· ขาด {missing.length} คน</span>
              </div>
            </div>
            <div className="p-2 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
              {missing.map(p => {
                const country = window.COUNTRIES?.find(c => c.id === p.country);
                const done = _mtgDone(p); // EM Begin classes already attended (0-4)
                const upline = p.sponsorId ? byId.get(p.sponsorId) : null;
                return (
                  <div key={p.id} className="flex items-center gap-2.5 p-2 rounded-lg bg-white border border-ink-100">
                    <Avatar user={{ avatar: p.name.charAt(p.name.indexOf(' ')+1) || 'ค', color: meetingGroup.color }} size={28} />
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-1.5">
                        <span className="text-xs font-semibold text-ink-900 truncate">{p.name}</span>
                        {country && <span className="text-[11px] leading-none">{country.flag}</span>}
                        {upline && <span className="text-[10px] text-amber-600 font-medium truncate flex-shrink-0" title={`UL: ${upline.name}`}>(UL: {upline.name})</span>}
                        <span
                          title={`เข้า EM Begin แล้ว ${done} จาก 4 คลาส`}
                          className="num text-[9px] font-bold leading-none px-1.5 py-0.5 rounded-full flex-shrink-0"
                          style={{ background: meetingGroup.color + '1A', color: meetingGroup.color }}>
                          {done}/4
                        </span>
                      </div>
                      <div className="text-[9px] text-ink-400 leading-tight">
                        {p.source === 'EM6W' ? '🥤 EM6W' : '💼 Sponsor'}{p.abo_code ? ` · ${p.abo_code}` : ''}
                      </div>
                    </div>
                    <button onClick={() => onMarkInactive(p.id)}
                      title="ย้ายไป Inactive"
                      className="w-5 h-5 rounded text-ink-300 hover:bg-rose-50 hover:text-rose-500 flex items-center justify-center transition-colors flex-shrink-0">
                      <Icon name="x" className="w-3 h-3" />
                    </button>
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>
    </Card>
  );
}
