// Smart Calendar view — drag & drop weekly calendar with prospect modal.
// Hero view (Module 5) of EMPHASIS Tracking System.

const HOURS = Array.from({ length: 14 }, (_, i) => 8 + i); // 8:00 - 21:00
const HOUR_PX = 56;
const SLOT_PX = HOUR_PX / 2; // 30-min slots

function CalendarView({ currentUser }) {
  const { apptTypes, leadSources } = useConfig();
  const [appts, setAppts] = useState(window.APPOINTMENTS.map(a => ({...a})));
  const [draftDrop, setDraftDrop] = useState(null); // {day,start,type}
  const [editing, setEditing] = useState(null); // appointment being edited
  const [typeDetailFor, setTypeDetailFor] = useState(null); // type id whose popup is open
  const [filterType, setFilterType] = useState('all');
  const [filterStatus, setFilterStatus] = useState('all');
  const [view, setView] = useState('week'); // week | month
  const [hoverCell, setHoverCell] = useState(null);

  const gridRef = useRef(null);
  const dragRef = useRef(null);

  // Filtered list
  const filtered = useMemo(() => appts.filter(a =>
    (filterType === 'all' || a.type === filterType) &&
    (filterStatus === 'all' || a.status === filterStatus)
  ), [appts, filterType, filterStatus]);

  // Drag from palette
  const handlePaletteDragStart = (e, typeId) => {
    dragRef.current = { source: 'palette', typeId };
    e.dataTransfer.effectAllowed = 'copy';
  };

  // Drag existing card
  const handleApptDragStart = (e, apptId) => {
    dragRef.current = { source: 'appt', apptId };
    e.dataTransfer.effectAllowed = 'move';
    e.target.classList.add('drag-ghost');
  };
  const handleApptDragEnd = (e) => {
    e.target.classList.remove('drag-ghost');
  };

  // Compute day/start from mouse position on a day column
  const cellFromEvent = (e, dayIdx) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const y = e.clientY - rect.top;
    const slot = Math.floor(y / SLOT_PX);
    const start = 8 + slot * 0.5;
    return { day: dayIdx, start: Math.max(8, Math.min(20.5, start)) };
  };

  const handleDayDragOver = (e, dayIdx) => {
    e.preventDefault();
    const cell = cellFromEvent(e, dayIdx);
    // Preview the dragged item's actual duration (palette type default, or moved appt's dur)
    const drag = dragRef.current;
    let dur = 0.5;
    let typeId = null;
    if (drag?.source === 'palette') {
      const t = apptTypes.find(t => t.id === drag.typeId);
      dur = t ? t.dur / 60 : 0.5;
      typeId = drag.typeId;
    } else if (drag?.source === 'appt') {
      const a = appts.find(a => a.id === drag.apptId);
      dur = a?.dur || 0.5;
      typeId = a?.type || null;
    }
    setHoverCell({ ...cell, dur, typeId });
  };

  const handleDayDrop = (e, dayIdx) => {
    e.preventDefault();
    const cell = cellFromEvent(e, dayIdx);
    const drag = dragRef.current;
    if (!drag) return;

    if (drag.source === 'palette') {
      // Create new — open prospect form
      const type = apptTypes.find(t => t.id === drag.typeId);
      setDraftDrop({ day: cell.day, start: cell.start, type: drag.typeId, dur: type.dur / 60 });
    } else if (drag.source === 'appt') {
      setAppts(prev => prev.map(a => a.id === drag.apptId ? { ...a, day: cell.day, start: cell.start } : a));
    }
    setHoverCell(null);
    dragRef.current = null;
  };

  const handleDayDragLeave = () => setHoverCell(null);

  const saveDraft = (data) => {
    const id = 'new-' + Date.now();
    setAppts(prev => [...prev, { id, day: draftDrop.day, start: draftDrop.start, dur: draftDrop.dur, type: draftDrop.type, owner: currentUser.id, ...data }]);
    setDraftDrop(null);
  };

  // Create an appointment programmatically (used by BM outcome flow → BI / reschedule).
  const createAppt = (data) => {
    const id = 'new-' + Date.now();
    const dt = apptTypes.find(t => t.id === data.type);
    const dur = data.dur || (dt ? dt.dur / 60 : 1);
    setAppts(prev => [...prev, { id, dur, owner: currentUser.id, status: 'pending', ...data }]);
  };

  const updateAppt = (id, patch) => setAppts(prev => prev.map(a => a.id === id ? { ...a, ...patch } : a));
  const deleteAppt = (id) => { setAppts(prev => prev.filter(a => a.id !== id)); setEditing(null); };

  return (
    <div className="flex flex-col gap-5">
      <SectionHead
        eyebrow="Module 5 · Smart Calendar"
        title="ตารางนัดหมาย & Prospect Tracking"
        sub="ลากกล่องประเภทนัด (BM / BI / 6W) มาวางในปฏิทินรายสัปดาห์ — ระบบจะถามข้อมูลผู้มุ่งหวังและบันทึกใน Activity Log อัตโนมัติ"
        right={
          <div className="flex items-center gap-2">
            <Tabs
              variant="pill"
              size="sm"
              active={view}
              onChange={setView}
              tabs={[
                { id: 'week', label: 'Week' },
                { id: 'month', label: 'Month' },
              ]}
            />
            <Btn variant="ghost" size="sm" icon={<Icon name="filter" />}>Filter</Btn>
            <Btn variant="brand" size="sm" icon={<Icon name="plus" />}>นัดใหม่</Btn>
          </div>
        }
      />

      {/* Top stats strip — type summary + follow-up watchlist */}
      <div className="grid grid-cols-12 gap-4">
        <div className="col-span-12 lg:col-span-8">
          <div className="grid gap-3" style={{ gridTemplateColumns: `repeat(${Math.max(apptTypes.length, 1)}, minmax(0, 1fr))` }}>
            {apptTypes.map(t => {
              const typeAppts = appts.filter(a => a.type === t.id);
              return (
                <TypeStatTile
                  key={t.id}
                  type={t}
                  appts={typeAppts}
                  onClick={() => setTypeDetailFor(t.id)}
                />
              );
            })}
          </div>
        </div>

        {/* Follow-up watchlist — who needs chase, who needs follow-up */}
        <div className="col-span-12 lg:col-span-4">
          <FollowUpCard
            appts={appts}
            onOpenAppt={setEditing}
          />
        </div>
      </div>

      {/* Main calendar area */}
      <div className="grid grid-cols-12 gap-4">
        {/* Palette / Sidebar */}
        <div className="col-span-12 lg:col-span-3 space-y-4">
          <Card title="ลากมาวางในปฏิทิน" pad={true}>
            <div className="text-[11px] text-ink-400 mb-3">Drag & drop types onto a time slot</div>
            <div className="space-y-2">
              {apptTypes.map(t => (
                <div
                  key={t.id}
                  draggable
                  onDragStart={(e) => handlePaletteDragStart(e, t.id)}
                  className="group flex items-center gap-3 p-3 rounded-xl border border-ink-100 hover:border-ink-200 hover:shadow-card cursor-grab active:cursor-grabbing bg-white transition-all"
                >
                  <div className="w-9 h-9 rounded-lg flex items-center justify-center text-white font-bold text-xs" style={{ background: t.color }}>
                    {t.label}
                  </div>
                  <div className="flex-1 min-w-0">
                    <div className="text-sm font-semibold text-ink-900">{t.full}</div>
                    <div className="text-[11px] text-ink-400 truncate">{t.desc}</div>
                  </div>
                  <div className="text-ink-300 group-hover:text-ink-500"><Icon name="drag" className="w-4 h-4" /></div>
                </div>
              ))}
            </div>
          </Card>

          {/* Filters */}
          <Card title="กรอง">
            <div className="space-y-3">
              <div>
                <div className="text-[11px] text-ink-500 mb-1.5">ประเภท</div>
                <div className="flex flex-wrap gap-1.5">
                  <FilterChip active={filterType==='all'} onClick={()=>setFilterType('all')}>ทั้งหมด</FilterChip>
                  {apptTypes.map(t => (
                    <FilterChip key={t.id} active={filterType===t.id} color={t.color} tint={t.tint} onClick={()=>setFilterType(t.id)}>{t.label}</FilterChip>
                  ))}
                </div>
              </div>
              <div>
                <div className="text-[11px] text-ink-500 mb-1.5">สถานะ</div>
                <div className="flex flex-wrap gap-1.5">
                  <FilterChip active={filterStatus==='all'} onClick={()=>setFilterStatus('all')}>ทั้งหมด</FilterChip>
                  {STATUS.map(s => (
                    <FilterChip key={s.id} active={filterStatus===s.id} color={s.color} tint={s.tint} onClick={()=>setFilterStatus(s.id)}>{s.label}</FilterChip>
                  ))}
                </div>
              </div>
            </div>
          </Card>

          <UpNext appts={filtered} onOpen={setEditing} />
        </div>

        {/* Calendar grid */}
        <Card className="col-span-12 lg:col-span-9" pad={false}>
          {/* Week header bar */}
          <div className="px-5 py-3 border-b border-ink-100 flex items-center justify-between">
            <div className="flex items-center gap-3">
              <button className="w-8 h-8 rounded-lg border border-ink-200 flex items-center justify-center hover:bg-ink-50"><Icon name="chevL" className="w-3.5 h-3.5" /></button>
              <div>
                <div className="text-sm font-semibold text-ink-900">11 – 17 พฤศจิกายน 2568</div>
                <div className="text-[11px] text-ink-400">Week 46 · 2025</div>
              </div>
              <button className="w-8 h-8 rounded-lg border border-ink-200 flex items-center justify-center hover:bg-ink-50"><Icon name="chevR" className="w-3.5 h-3.5" /></button>
              <button className="text-xs font-medium text-brand-600 hover:text-brand-700 ml-2">วันนี้</button>
            </div>
            <div className="flex items-center gap-3 text-[11px] text-ink-500">
              <Legend />
            </div>
          </div>

          {/* Grid */}
          <div ref={gridRef} className="relative overflow-x-auto scroll-thin">
            <div className="min-w-[860px]">
              {/* Days header */}
              <div className="grid sticky top-0 z-10 bg-white border-b border-ink-100" style={{ gridTemplateColumns: '56px repeat(7, 1fr)' }}>
                <div></div>
                {DAYS_FULL.map((d, i) => {
                  const isToday = i === 3;
                  return (
                    <div key={d} className={`py-3 px-2 text-center border-l border-ink-100 ${isToday ? 'bg-brand-50' : ''}`}>
                      <div className="text-[11px] uppercase tracking-wider font-semibold text-ink-400">{d.split(' ')[0]}</div>
                      <div className={`text-lg font-semibold mt-0.5 ${isToday ? 'text-brand-700' : 'text-ink-900'}`}>{d.split(' ')[1]}</div>
                    </div>
                  );
                })}
              </div>

              {/* Body: time gutter + 7 day columns */}
              <div className="grid relative" style={{ gridTemplateColumns: '56px repeat(7, 1fr)' }}>
                {/* Time gutter */}
                <div className="relative">
                  {HOURS.map(h => (
                    <div key={h} className="h-14 text-right pr-2 text-[11px] text-ink-400 num border-b border-ink-100/70 flex items-start pt-0.5 justify-end">
                      {String(h).padStart(2,'0')}:00
                    </div>
                  ))}
                </div>

                {/* Day columns */}
                {DAYS_FULL.map((_, dayIdx) => (
                  <DayColumn
                    key={dayIdx}
                    dayIdx={dayIdx}
                    appts={filtered.filter(a => a.day === dayIdx)}
                    onDragOver={(e) => handleDayDragOver(e, dayIdx)}
                    onDrop={(e) => handleDayDrop(e, dayIdx)}
                    onDragLeave={handleDayDragLeave}
                    onApptDragStart={handleApptDragStart}
                    onApptDragEnd={handleApptDragEnd}
                    onApptClick={setEditing}
                    hoverCell={hoverCell && hoverCell.day === dayIdx ? hoverCell : null}
                  />
                ))}

                {/* Current-time line */}
                <div className="absolute pointer-events-none" style={{ left: 56, right: 0, top: 14 * SLOT_PX + 12 }}>
                  <div className="flex items-center">
                    <div className="w-2 h-2 rounded-full bg-rose-500 -ml-1" />
                    <div className="flex-1 h-px bg-rose-500/60" />
                  </div>
                </div>
              </div>
            </div>
          </div>
        </Card>
      </div>

      {/* Activity log strip */}
      <ActivityLog appts={appts} />

      {/* Type detail popup */}
      <TypeDetailModal
        open={!!typeDetailFor}
        onClose={() => setTypeDetailFor(null)}
        typeId={typeDetailFor}
        appts={appts}
        onOpenAppt={(a) => { setTypeDetailFor(null); setEditing(a); }}
      />

      {/* New appointment prospect form */}
      <ProspectModal
        open={!!draftDrop}
        onClose={() => setDraftDrop(null)}
        draft={draftDrop}
        onSave={saveDraft}
      />

      {/* Edit appointment */}
      <EditApptModal
        open={!!editing}
        onClose={() => setEditing(null)}
        appt={editing}
        appts={appts}
        onSave={(patch) => { updateAppt(editing.id, patch); setEditing(null); }}
        onDelete={() => deleteAppt(editing.id)}
        onCreateAppt={createAppt}
      />
    </div>
  );
}

const FilterChip = ({ active, color, tint, onClick, children }) => (
  <button
    onClick={onClick}
    className={`text-[11px] font-medium px-2 py-1 rounded-md border transition-all ${
      active
        ? 'border-transparent text-white'
        : 'bg-white border-ink-200 text-ink-500 hover:border-ink-300'
    }`}
    style={active ? { background: color || '#0F1E38' } : {}}
  >{children}</button>
);

const Legend = () => {
  const { apptTypes } = useConfig();
  return (
  <div className="flex items-center gap-3">
    {apptTypes.map(t => (
      <div key={t.id} className="flex items-center gap-1.5">
        <div className="w-2.5 h-2.5 rounded-sm" style={{ background: t.color }} />
        <span className="text-[11px] text-ink-500">{t.full}</span>
      </div>
    ))}
  </div>
  );
};

function DayColumn({ dayIdx, appts, onDragOver, onDrop, onDragLeave, onApptDragStart, onApptDragEnd, onApptClick, hoverCell }) {
  const { apptTypes } = useConfig();
  const hoverType = hoverCell?.typeId ? apptTypes.find(t => t.id === hoverCell.typeId) : null;
  const isToday = dayIdx === 3;
  const isWeekend = dayIdx === 5 || dayIdx === 6;

  return (
    <div
      className={`relative border-l border-ink-100 ${isToday ? 'bg-brand-50/30' : isWeekend ? 'bg-ink-50/30' : 'bg-white'}`}
      style={{ height: HOURS.length * HOUR_PX }}
      onDragOver={onDragOver}
      onDrop={onDrop}
      onDragLeave={onDragLeave}
    >
      {/* hour lines */}
      {HOURS.map((_, i) => (
        <div key={i} className="absolute left-0 right-0 border-b border-ink-100/70" style={{ top: (i + 1) * HOUR_PX }} />
      ))}
      {/* half-hour lines (lighter) */}
      {HOURS.map((_, i) => (
        <div key={'h'+i} className="absolute left-0 right-0 border-b border-dashed border-ink-100/50" style={{ top: i * HOUR_PX + SLOT_PX }} />
      ))}

      {/* hover indicator — full default duration of the dragged type */}
      {hoverCell && (
        <div
          className="absolute left-1 right-1 rounded-md drop-target flex flex-col items-start justify-between p-1.5 overflow-hidden"
          style={{
            top: (hoverCell.start - 8) * HOUR_PX,
            height: (hoverCell.dur || 0.5) * HOUR_PX - 4,
            background: hoverType ? hoverType.tint : 'rgba(47,93,229,0.06)',
            borderColor: hoverType ? hoverType.color : '#2F5DE5',
          }}
        >
          {hoverType && (
            <>
              <div className="flex items-center gap-1.5">
                <span className="text-[10px] font-bold px-1.5 rounded-sm text-white" style={{ background: hoverType.color }}>{hoverType.label}</span>
                <span className="text-[10px] font-medium num" style={{ color: hoverType.color }}>{hoverType.dur} นาที</span>
              </div>
              <span className="text-[10px] num text-ink-500">{formatTime(hoverCell.start)} – {formatTime(hoverCell.start + (hoverCell.dur || 0.5))}</span>
            </>
          )}
        </div>
      )}

      {/* appointments */}
      {appts.map(a => <ApptCard key={a.id} appt={a} onDragStart={onApptDragStart} onDragEnd={onApptDragEnd} onClick={() => onApptClick(a)} />)}
    </div>
  );
}

function ApptCard({ appt, onDragStart, onDragEnd, onClick }) {
  const { apptTypes, leadSources } = useConfig();
  const type = apptTypes.find(t => t.id === appt.type);
  const status = STATUS.find(s => s.id === appt.status);
  const src = leadSources.find(s => s.id === appt.source);
  const top = (appt.start - 8) * HOUR_PX;
  const height = appt.dur * HOUR_PX - 4;
  const cancelled = appt.status === 'cancelled';
  const completed = appt.status === 'completed';

  const startStr = formatTime(appt.start);
  const endStr = formatTime(appt.start + appt.dur);

  return (
    <div
      draggable
      onDragStart={(e) => onDragStart(e, appt.id)}
      onDragEnd={onDragEnd}
      onClick={onClick}
      className={`absolute left-1 right-1 rounded-lg p-2 cursor-grab active:cursor-grabbing hover:shadow-lift transition-all overflow-hidden text-left border ${cancelled ? 'stripe-bg' : ''}`}
      style={{
        top, height,
        background: cancelled ? '#F1F5F9' : type.tint,
        borderColor: cancelled ? '#CBD5E1' : type.color + '40',
        borderLeft: `3px solid ${cancelled ? '#94A3B8' : type.color}`,
        opacity: cancelled ? 0.6 : 1,
      }}
    >
      <div className="flex items-center gap-1.5 mb-0.5">
        <span className="text-[10px] font-bold px-1.5 rounded-sm text-white" style={{ background: type.color }}>{type.label}</span>
        {(() => {
          const c = window.COUNTRIES.find(c => c.id === (appt.country || 'th'));
          return c && <span className="text-[11px] leading-none" title={c.label}>{c.flag}</span>;
        })()}
        {completed && <span className="text-[10px] font-medium text-emerald-600 flex items-center gap-0.5"><Icon name="check" className="w-3 h-3" />ปิด</span>}
        {appt.status === 'followup' && <span className="text-[10px] font-medium text-brand-600">↻ FU</span>}
        <span className="text-[10px] num text-ink-500 ml-auto">{startStr}</span>
      </div>
      <div className="text-xs font-semibold text-ink-900 truncate leading-tight flex items-center gap-1" style={{ textDecoration: cancelled ? 'line-through' : 'none' }}>
        {appt.igAvatar && <img src={appt.igAvatar} alt="" className="w-3.5 h-3.5 rounded-full flex-shrink-0" />}
        {appt.prospect}
      </div>
      {height > 40 && (
        <div className="flex items-center gap-1 mt-1">
          <div className="w-1.5 h-1.5 rounded-full" style={{ background: src.color }} />
          <span className="text-[10px] text-ink-500 truncate">{src.label}</span>
        </div>
      )}
    </div>
  );
}

function formatTime(h) {
  const hour = Math.floor(h);
  const min = Math.round((h - hour) * 60);
  return `${String(hour).padStart(2,'0')}:${String(min).padStart(2,'0')}`;
}

function UpNext({ appts, onOpen }) {
  const { apptTypes, leadSources } = useConfig();
  const upcoming = appts
    .filter(a => a.status === 'pending' || a.status === 'followup')
    .slice(0, 3);

  return (
    <Card title="Up Next">
      <div className="space-y-2.5">
        {upcoming.map(a => {
          const t = apptTypes.find(x => x.id === a.type);
          return (
            <button key={a.id} onClick={() => onOpen(a)} className="w-full text-left flex items-start gap-2.5 p-2 rounded-lg hover:bg-ink-50 transition-colors">
              <div className="flex-shrink-0 w-9 h-9 rounded-lg flex flex-col items-center justify-center text-white text-[10px] font-bold" style={{ background: t.color }}>
                <div className="leading-none">{t.label}</div>
                <div className="text-[8px] opacity-80 mt-0.5">{formatTime(a.start)}</div>
              </div>
              <div className="flex-1 min-w-0">
                <div className="text-xs font-semibold text-ink-900 truncate">{a.prospect}</div>
                <div className="text-[10px] text-ink-400">{DAYS_FULL[a.day]} · {leadSources.find(s=>s.id===a.source).label}</div>
              </div>
            </button>
          );
        })}
      </div>
    </Card>
  );
}

function ProspectModal({ open, onClose, draft, onSave }) {
  const { apptTypes, leadSources } = useConfig();
  const type = draft ? apptTypes.find(t => t.id === draft.type) : null;
  const [name, setName] = useState('');
  const [source, setSource] = useState('fb');
  const [status, setStatus] = useState('pending');
  const [dur, setDur] = useState(1);
  const [notes, setNotes] = useState('');
  const [dlId, setDlId] = useState(window.TEAM[0].id);
  const [country, setCountry] = useState('th');
  const [igHandle, setIgHandle] = useState('');
  const [igProfile, setIgProfile] = useState(null); // {avatar, name, fetched}
  const [igFetching, setIgFetching] = useState(false);

  useEffect(() => {
    if (open && draft) {
      setName(''); setSource('fb'); setStatus('pending'); setDur(draft.dur || 1); setNotes('');
      setDlId(window.TEAM[0].id); setCountry('th'); setIgHandle(''); setIgProfile(null);
    }
  }, [open, draft]);

  // Mock IG fetch — in production this calls a backend endpoint that wraps the IG Graph API.
  // Here we deterministically generate a friendly avatar from the handle.
  const fetchIgProfile = async () => {
    const handle = igHandle.trim().replace(/^@/, '');
    if (!handle) return;
    setIgFetching(true);
    setIgProfile(null);
    // Simulate network latency
    await new Promise(r => setTimeout(r, 700));
    const avatar = `https://api.dicebear.com/9.x/notionists/svg?seed=${encodeURIComponent(handle)}&backgroundColor=ffd5dc,ffdfbf,d1d4f9,c0aede,b6e3f4`;
    setIgProfile({ avatar, handle, fetched: true });
    if (!name) setName('@' + handle);
    setIgFetching(false);
  };

  if (!draft) return null;

  const sourceObj = leadSources.find(s => s.id === source);
  const isIG = source === 'ig';

  return (
    <Modal
      open={open}
      onClose={onClose}
      size="lg"
      title={
        <div className="flex items-center gap-2">
          <div className="w-7 h-7 rounded-md text-white font-bold text-xs flex items-center justify-center" style={{ background: type.color }}>{type.label}</div>
          <div>
            <div className="text-sm font-semibold text-ink-900">นัดหมายใหม่ · {type.full}</div>
            <div className="text-[11px] text-ink-400 num">{DAYS_FULL[draft.day]} · {formatTime(draft.start)}</div>
          </div>
        </div>
      }
      footer={
        <div className="flex items-center justify-between">
          <span className="text-[11px] text-ink-400 flex items-center gap-1.5"><Icon name="info" className="w-3.5 h-3.5" /> บันทึกใน Activity Log อัตโนมัติ</span>
          <div className="flex items-center gap-2">
            <Btn variant="ghost" size="sm" onClick={onClose}>ยกเลิก</Btn>
            <Btn variant="brand" size="sm" icon={<Icon name="check" className="w-3.5 h-3.5" />}
              onClick={() => onSave({
                prospect: name || 'ผู้มุ่งหวังใหม่',
                source, status, notes,
                dlId, country,
                igHandle: isIG ? igHandle.trim().replace(/^@/, '') : null,
                igAvatar: isIG ? igProfile?.avatar : null,
              })}>บันทึก</Btn>
          </div>
        </div>
      }
    >
      <div className="space-y-4">
        {/* DL + Country row */}
        <div className="grid grid-cols-12 gap-3">
          <div className="col-span-7">
            <Field label={
              <div className="flex items-center gap-2">
                <span>เจ้าของเคส</span>
                {dlId === window.TEAM[0].id
                  ? <Pill color="#B87C00" tint="#FFECB8" size="xs">★ เคสของตัวเอง</Pill>
                  : <Pill color="#2F5DE5" tint="#EEF4FF" size="xs">DL</Pill>}
              </div>
            }>
              <select value={dlId} onChange={e => setDlId(e.target.value)} className="input">
                <optgroup label="── เคสของตัวเอง ──">
                  <option value={window.TEAM[0].id}>★ เคสของตัวเอง · {window.TEAM[0].name} ({window.TEAM[0].role})</option>
                </optgroup>
                <optgroup label="── Downline (DL) ──">
                  {window.TEAM.slice(1).map(u => (
                    <option key={u.id} value={u.id}>{u.name} · {u.role}</option>
                  ))}
                </optgroup>
              </select>
            </Field>
          </div>
          <div className="col-span-5">
            <Field label="ประเทศ">
              <div className="grid grid-cols-4 gap-1">
                {COUNTRIES.map(c => (
                  <button key={c.id} onClick={() => setCountry(c.id)}
                    title={c.label}
                    className={`flex flex-col items-center justify-center py-1.5 rounded-md border transition-all ${country === c.id ? 'border-brand-500 bg-brand-50' : 'bg-white border-ink-200 hover:border-ink-300'}`}>
                    <span className="text-lg leading-none">{c.flag}</span>
                    <span className={`text-[9px] mt-0.5 ${country === c.id ? 'text-brand-700 font-semibold' : 'text-ink-500'}`}>{c.label}</span>
                  </button>
                ))}
              </div>
            </Field>
          </div>
        </div>

        <Field label="ชื่อผู้มุ่งหวัง (Prospect Name)">
          <div className="relative">
            {igProfile?.avatar && (
              <img src={igProfile.avatar} alt="" className="absolute left-2 top-1/2 -translate-y-1/2 w-6 h-6 rounded-full bg-white border border-ink-200" />
            )}
            <input autoFocus value={name} onChange={e => setName(e.target.value)}
              placeholder="เช่น คุณวริศรา ม."
              className={`input ${igProfile?.avatar ? 'pl-10' : ''}`} />
          </div>
        </Field>

        <Field label="แหล่งที่มา (Lead Source)">
          <div className="grid grid-cols-3 gap-2">
            {leadSources.map(s => (
              <button key={s.id} onClick={() => setSource(s.id)}
                className={`flex items-center gap-2 p-2 rounded-lg border text-xs font-medium transition-all ${source === s.id ? 'border-transparent text-white' : 'bg-white border-ink-200 text-ink-700 hover:border-ink-300'}`}
                style={source === s.id ? { background: s.color } : {}}>
                <div className="w-2 h-2 rounded-full" style={{ background: source === s.id ? 'white' : s.color }} />
                {s.label}
              </button>
            ))}
          </div>
        </Field>

        {/* IG handle (conditional) */}
        {isIG && (
          <div className="rounded-xl border border-pink-200 bg-gradient-to-br from-pink-50 to-orange-50 p-3 space-y-3">
            <div className="flex items-center gap-2">
              <svg viewBox="0 0 24 24" className="w-4 h-4" fill="none" stroke="#E1306C" strokeWidth="2"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="1.2" fill="#E1306C"/></svg>
              <span className="text-[11px] font-semibold text-pink-700">Instagram account</span>
              <span className="text-[10px] text-pink-500/70 ml-auto">ระบบจะดึงรูปโปรไฟล์อัตโนมัติ</span>
            </div>
            <div className="flex gap-2">
              <div className="relative flex-1">
                <span className="absolute left-3 top-1/2 -translate-y-1/2 text-ink-400 font-medium">@</span>
                <input value={igHandle} onChange={e => { setIgHandle(e.target.value); setIgProfile(null); }}
                  placeholder="username"
                  onKeyDown={e => e.key === 'Enter' && (e.preventDefault(), fetchIgProfile())}
                  className="input pl-7" />
              </div>
              <button onClick={fetchIgProfile} disabled={!igHandle.trim() || igFetching}
                className="h-9 px-3 text-xs font-semibold rounded-lg bg-gradient-to-r from-pink-500 to-orange-500 text-white disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-1.5 transition-all hover:shadow-md">
                {igFetching ? (
                  <>
                    <svg className="w-3.5 h-3.5 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 4v4M12 16v4M4 12h4M16 12h4" /></svg>
                    Fetching…
                  </>
                ) : igProfile ? (
                  <><Icon name="check" className="w-3.5 h-3.5" /> Re-fetch</>
                ) : (
                  <><Icon name="arrowR" className="w-3.5 h-3.5" /> ดึงรูป</>
                )}
              </button>
            </div>
            {igProfile && (
              <div className="flex items-center gap-3 p-2 bg-white rounded-lg border border-pink-100">
                <img src={igProfile.avatar} alt="" className="w-12 h-12 rounded-full" />
                <div className="flex-1 min-w-0">
                  <div className="text-xs font-semibold text-ink-900">@{igProfile.handle}</div>
                  <div className="text-[10px] text-ink-400">Profile · fetched from IG Graph API (mock)</div>
                </div>
                <Pill color="#10B981" tint="#E7F8F1" size="xs" icon={<Icon name="check" className="w-3 h-3" />}>OK</Pill>
              </div>
            )}
            <div className="text-[10px] text-ink-400 leading-snug">
              <code className="font-mono">GET /api/ig/profile?handle={igHandle || 'USER'}</code> · backend wraps Instagram Graph API & caches avatar in S3
            </div>
          </div>
        )}

        <div className="grid grid-cols-2 gap-3">
          <Field label="ระยะเวลา">
            <select value={dur} onChange={e => setDur(parseFloat(e.target.value))} className="input">
              <option value={0.5}>30 นาที</option>
              <option value={0.75}>45 นาที</option>
              <option value={1}>1 ชั่วโมง</option>
              <option value={1.5}>1.5 ชั่วโมง</option>
              <option value={2}>2 ชั่วโมง</option>
            </select>
          </Field>
          <Field label="สถานะเริ่มต้น">
            <select value={status} onChange={e => setStatus(e.target.value)} className="input">
              {STATUS.map(s => <option key={s.id} value={s.id}>{s.label}</option>)}
            </select>
          </Field>
        </div>

        <Field label="โน้ตเพิ่มเติม (ถ้ามี)">
          <textarea value={notes} onChange={e => setNotes(e.target.value)} rows={2}
            placeholder="เป้าหมาย / รายละเอียดเพิ่มเติม" className="input resize-none" />
        </Field>
      </div>
      <style>{`
        .input {
          width: 100%; padding: 8px 12px; font-size: 13px;
          border: 1px solid #C9D2E3; border-radius: 8px; background: white;
          outline: none; transition: all .15s; color: #0F1E38;
        }
        .input:focus { border-color: #2F5DE5; box-shadow: 0 0 0 3px rgba(47,93,229,0.15); }
      `}</style>
    </Modal>
  );
}

function EditApptModal({ open, onClose, appt, appts = [], onSave, onDelete, onCreateAppt }) {
  const { apptTypes, leadSources } = useConfig();
  const [notes, setNotes] = useState('');
  const [outcome, setOutcome] = useState(null); // 'bi' | 'skip' | 'postpone' | null
  const [nextDay, setNextDay] = useState(4);
  const [nextStart, setNextStart] = useState(10);
  const [sendBoarding, setSendBoarding] = useState(true);
  const [copied, setCopied] = useState(false);
  const [photos, setPhotos] = useState([]);  // data URLs for preview
  const fileInputRef = useRef(null);

  useEffect(() => {
    if (appt) {
      setNotes(appt.notes || '');
      setOutcome(null);
      setNextDay(Math.min(6, (appt.day || 0) + 2));
      setNextStart(appt.start || 10);
      setSendBoarding(true);
      setPhotos(appt.photos || []);
    }
  }, [appt]);

  if (!appt) return null;
  const type = apptTypes.find(t => t.id === appt.type);
  const src = leadSources.find(s => s.id === appt.source);
  const country = window.COUNTRIES.find(c => c.id === (appt.country || 'th'));
  const dl = window.TEAM.find(u => u.id === (appt.dlId || appt.owner));

  const STATUS_BY_OUTCOME = { bi: 'completed', skip: 'cancelled', postpone: 'followup' };

  // Locate the appointment's place in the Follow Up flow (BM → BI → S3 → S4 → S5)
  const currentStep = window.FOLLOW_UP_STEPS.find(s => s.type === appt.type) || null;
  const nextStep    = currentStep ? window.FOLLOW_UP_STEPS.find(s => s.step === currentStep.step + 1) : null;

  // The next appointment's type (BI if "ผ่าน" advances the flow, otherwise same type for postpone)
  const nextType = outcome === 'bi' && nextStep ? nextStep.type : appt.type;
  const nextDur = (apptTypes.find(t => t.id === nextType)?.dur || 60) / 60;

  // Find overlapping appointments at (nextDay, nextStart, nextDur) — excluding current appt being edited
  const conflicts = useMemo(() => {
    if (!outcome || outcome === 'skip') return [];
    return appts.filter(a =>
      a.id !== appt.id &&
      a.status !== 'cancelled' &&
      a.day === nextDay &&
      a.start < nextStart + nextDur &&
      nextStart < a.start + a.dur
    );
  }, [appts, appt.id, outcome, nextDay, nextStart, nextDur]);

  const handlePhotoUpload = (e) => {
    const files = Array.from(e.target.files || []);
    files.forEach(f => {
      const reader = new FileReader();
      reader.onload = () => setPhotos(prev => [...prev, reader.result]);
      reader.readAsDataURL(f);
    });
    e.target.value = '';
  };
  const removePhoto = (i) => setPhotos(prev => prev.filter((_, idx) => idx !== i));

  const handleSave = () => {
    const newStatus = outcome ? STATUS_BY_OUTCOME[outcome] : appt.status;
    onSave({ status: newStatus, notes, outcome, photos });
    // "ผ่าน" + next step exists → advance the flow
    if (outcome === 'bi' && nextStep) {
      onCreateAppt({
        day: nextDay, start: nextStart, type: nextStep.type,
        prospect: appt.prospect, source: appt.source,
        dlId: appt.dlId, country: appt.country,
        igHandle: appt.igHandle, igAvatar: appt.igAvatar,
        step: nextStep.step,
        notes: sendBoarding && currentStep?.link ? `📦 ส่ง ${currentStep.link.label} แล้ว · ต่อจาก Step ${currentStep.step}` : `ต่อจาก Step ${currentStep?.step || ''}`,
      });
    } else if (outcome === 'postpone') {
      onCreateAppt({
        day: nextDay, start: nextStart, type: appt.type,
        prospect: appt.prospect, source: appt.source,
        dlId: appt.dlId, country: appt.country,
        igHandle: appt.igHandle, igAvatar: appt.igAvatar,
        step: currentStep?.step,
        notes: `เลื่อนจากนัด ${type.label} เดิม`,
      });
    }
  };

  const copyLink = async (url) => {
    try {
      await navigator.clipboard.writeText(url);
      setCopied(true);
      setTimeout(() => setCopied(false), 1500);
    } catch {}
  };

  const canSave = outcome !== null;

  return (
    <Modal open={open} onClose={onClose} size="lg" title={
      <div className="flex items-center gap-2">
        <div className="w-7 h-7 rounded-md text-white font-bold text-xs flex items-center justify-center" style={{ background: type.color }}>{type.label}</div>
        <div>
          <div className="flex items-center gap-2">
            {appt.igAvatar && <img src={appt.igAvatar} alt="" className="w-5 h-5 rounded-full border border-ink-200" />}
            <span className="text-sm font-semibold text-ink-900">{appt.prospect}</span>
            {country && <span className="text-base leading-none" title={country.label}>{country.flag}</span>}
          </div>
          <div className="text-[11px] text-ink-400 num">{DAYS_FULL[appt.day]} · {formatTime(appt.start)} ({appt.dur*60} นาที){dl ? (dl.id === window.TEAM[0].id ? ' · ★ เคสของตัวเอง' : ` · DL: ${dl.name}`) : ''}</div>
        </div>
      </div>
    } footer={
      <div className="flex items-center justify-between">
        <button onClick={onDelete} className="text-xs font-medium text-rose-500 hover:text-rose-700">ลบนัดนี้</button>
        <div className="flex items-center gap-2">
          {!outcome && (
            <span className="text-[11px] text-gold-600 font-medium">เลือกผลการนัดก่อนบันทึก ↑</span>
          )}
          <Btn variant="ghost" size="sm" onClick={onClose}>ยกเลิก</Btn>
          <Btn variant="brand" size="sm" onClick={handleSave} disabled={!canSave}
               icon={<Icon name="check" className="w-3.5 h-3.5" />}>บันทึก</Btn>
        </div>
      </div>
    }>
      <div className="space-y-4">
        {/* Source / DL bar */}
        <div className="flex items-center gap-3 p-3 rounded-lg bg-ink-50 flex-wrap">
          <div className="flex items-center gap-1.5">
            <div className="w-2 h-2 rounded-full" style={{ background: src.color }} />
            <span className="text-xs text-ink-700">{src.label}</span>
            {appt.igHandle && <span className="text-xs text-pink-600 font-medium">@{appt.igHandle}</span>}
          </div>
          {dl && (
            <div className="flex items-center gap-1.5 pl-3 border-l border-ink-200">
              <Avatar user={dl} size={16} />
              <span className="text-xs text-ink-700">
                {dl.id === window.TEAM[0].id
                  ? <><span className="text-amber-500">★</span> เคสของตัวเอง</>
                  : <>DL · {dl.name}</>}
              </span>
            </div>
          )}
          <span className="text-xs text-ink-400 ml-auto">{type.full}</span>
        </div>

        {/* Current step header — what to do during this appointment */}
        {currentStep && (
          <div className="rounded-xl border-2 p-3 space-y-2.5" style={{ borderColor: type.color + '40', background: type.tint }}>
            <div className="flex items-center gap-2">
              <span className="px-2 py-0.5 rounded text-[10px] font-bold text-white" style={{ background: type.color }}>STEP {currentStep.step}</span>
              <span className="text-sm font-bold" style={{ color: type.color }}>{currentStep.title}</span>
              <span className="ml-auto text-[10px] text-ink-400 num">{currentStep.step}/5</span>
            </div>
            <div className="text-[11px] text-ink-600 font-medium uppercase tracking-wide">สิ่งที่ต้องทำในนัดนี้</div>
            <ul className="space-y-1">
              {currentStep.items.map((it, i) => (
                <li key={i} className="flex items-center gap-2 text-xs text-ink-700">
                  <div className="w-1.5 h-1.5 rounded-full flex-shrink-0" style={{ background: type.color }} />
                  {it}
                </li>
              ))}
            </ul>
          </div>
        )}

        {/* Follow Up Process — choose outcome */}
        <div className="rounded-xl border border-brand-200 bg-brand-50/50 p-3 space-y-3">
          <div className="flex items-center gap-2">
            <Icon name="sparkles" className="w-4 h-4 text-brand-600" />
            <span className="text-xs font-semibold text-brand-800">Follow Up Process · เลือกผลการนัด</span>
          </div>

          <div className="grid grid-cols-3 gap-2">
            {[
              { id: 'bi',       label: nextStep ? `ผ่าน → Step ${nextStep.step}` : 'ผ่าน (จบ flow)', desc: nextStep ? `นัด ${nextStep.title} ต่อ` : '🎉 BT to Silver · เสร็จสิ้น', color: '#10B981', tint: '#E7F8F1', icon: 'arrowR' },
              { id: 'skip',     label: 'ยังไม่สนใจ',     desc: 'ปิดเคส, เก็บไว้ในระบบ', color: '#94A3B8', tint: '#F1F5F9', icon: 'x' },
              { id: 'postpone', label: 'เลื่อน',         desc: `นัด ${type.label} ใหม่อีกครั้ง`,  color: '#F59E0B', tint: '#FFF6E0', icon: 'clock' },
            ].map(o => (
              <button key={o.id} onClick={() => setOutcome(o.id)}
                className={`text-left p-3 rounded-lg border-2 transition-all ${outcome === o.id ? 'shadow-card' : 'border-transparent hover:border-ink-200'}`}
                style={outcome === o.id ? { borderColor: o.color, background: o.tint } : { background: 'white' }}>
                <div className="flex items-center gap-1.5 mb-1">
                  <div className="w-6 h-6 rounded-md flex items-center justify-center text-white" style={{ background: o.color }}>
                    <Icon name={o.icon} className="w-3 h-3" strokeWidth={2.5} />
                  </div>
                  <span className="text-xs font-semibold" style={{ color: outcome === o.id ? o.color : '#0F1E38' }}>{o.label}</span>
                </div>
                <div className="text-[10px] text-ink-500 leading-snug">{o.desc}</div>
              </button>
            ))}
          </div>

          {/* ผ่าน — advance to next step */}
          {outcome === 'bi' && nextStep && (() => {
            const nextTypeDef = apptTypes.find(t => t.id === nextStep.type) || type;
            return (
              <div className="space-y-3 pt-2 border-t border-brand-200/60">
                <div className="flex items-center gap-2">
                  <span className="px-2 py-0.5 rounded text-[10px] font-bold text-white" style={{ background: nextTypeDef.color }}>STEP {nextStep.step}</span>
                  <span className="text-xs font-bold" style={{ color: nextTypeDef.color }}>นัด {nextStep.title} ต่อ</span>
                </div>
                <DateTimePicker day={nextDay} start={nextStart} onDay={setNextDay} onStart={setNextStart} color={nextTypeDef.color} />
                <ConflictWarning conflicts={conflicts} apptTypes={apptTypes} />

                {/* What to prepare before next step (current step items + link if any) */}
                {currentStep?.link && (
                  <div className="rounded-lg border border-gold-200 bg-gradient-to-br from-gold-50 to-white p-3">
                    <label className="flex items-start gap-2.5 cursor-pointer">
                      <input type="checkbox" checked={sendBoarding} onChange={e => setSendBoarding(e.target.checked)}
                        className="mt-0.5 w-4 h-4 accent-gold-500" />
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2">
                          <span className="text-lg leading-none">📦</span>
                          <span className="text-xs font-semibold text-ink-900">ส่ง {currentStep.link.label} ก่อนนัดถัดไป</span>
                          <Pill color="#B87C00" tint="#FFECB8" size="xs">Step {currentStep.step}</Pill>
                        </div>
                        <div className="mt-2 flex items-center gap-2 p-2 bg-white rounded border border-ink-100">
                          <Icon name="line" className="w-3.5 h-3.5 text-emerald-600 flex-shrink-0" />
                          <code className="text-[10px] font-mono text-ink-600 truncate flex-1">{currentStep.link.url}</code>
                          <button onClick={(e) => { e.preventDefault(); copyLink(currentStep.link.url); }}
                            className="text-[10px] font-semibold px-2 py-1 rounded bg-ink-900 text-white hover:bg-ink-700 transition-colors flex-shrink-0">
                            {copied ? '✓ Copied' : 'Copy link'}
                          </button>
                        </div>
                        <div className="text-[10px] text-ink-400 mt-1.5">ระบบจะส่ง LINE Push พร้อมลิงก์ให้ผู้มุ่งหวังโดยอัตโนมัติ</div>
                      </div>
                    </label>
                  </div>
                )}

                {/* Preview of next step's actions */}
                <div className="rounded-lg bg-white border border-ink-100 p-3">
                  <div className="text-[11px] font-semibold uppercase tracking-wide mb-1.5" style={{ color: nextTypeDef.color }}>
                    เตรียมตัว · สิ่งที่จะคุยใน Step {nextStep.step}
                  </div>
                  <ul className="space-y-1">
                    {nextStep.items.map((it, i) => (
                      <li key={i} className="flex items-center gap-2 text-[11px] text-ink-600">
                        <div className="w-1 h-1 rounded-full" style={{ background: nextTypeDef.color }} />{it}
                      </li>
                    ))}
                  </ul>
                </div>
              </div>
            );
          })()}

          {/* ผ่าน + ไม่มี next step (Step 5 จบ flow, หรือ type นอก flow เช่น 6W) */}
          {outcome === 'bi' && !nextStep && (
            <div className="pt-2 border-t border-brand-200/60">
              <div className="rounded-lg bg-gradient-to-br from-emerald-50 to-amber-50 border border-emerald-200 p-3 text-center">
                <div className="text-2xl mb-1">🎉</div>
                <div className="text-sm font-semibold text-emerald-700">{currentStep ? `จบ Follow Up Process · ${currentStep.title} เสร็จสิ้น` : 'เคสปิดสำเร็จ'}</div>
                <div className="text-[11px] text-ink-500 mt-0.5">{currentStep?.step === 5 ? 'ผู้มุ่งหวังเข้าสู่ระดับ BT to Silver แล้ว' : 'บันทึกเป็น Completed'}</div>
              </div>
            </div>
          )}

          {/* Postpone outcome */}
          {outcome === 'postpone' && (
            <div className="space-y-3 pt-2 border-t border-brand-200/60">
              <div className="text-[11px] font-semibold text-gold-700 uppercase tracking-wide">นัด {type.label} ใหม่</div>
              <DateTimePicker day={nextDay} start={nextStart} onDay={setNextDay} onStart={setNextStart} color={type.color} />
              <ConflictWarning conflicts={conflicts} apptTypes={apptTypes} />
            </div>
          )}

          {/* Skip outcome */}
          {outcome === 'skip' && (
            <div className="p-3 rounded-lg bg-ink-50 text-[11px] text-ink-600 border-t border-brand-200/60">
              เก็บข้อมูลผู้มุ่งหวังไว้ในระบบ — อาจติดต่อใหม่ใน 3-6 เดือน
            </div>
          )}
        </div>

        {/* Upload photo after case completed — skip when postponing (case not done yet) */}
        {outcome && outcome !== 'postpone' && (
          <Field label={
            <div className="flex items-center gap-2">
              <span>📷 รูปหลังทำเคส</span>
              <Pill color="#94A3B8" tint="#F1F5F9" size="xs">{photos.length} รูป</Pill>
            </div>
          }>
            <div className="space-y-2">
              <input ref={fileInputRef} type="file" accept="image/*" multiple onChange={handlePhotoUpload} className="hidden" />
              {photos.length === 0 ? (
                <button onClick={() => fileInputRef.current?.click()}
                  className="w-full border-2 border-dashed border-ink-200 rounded-lg p-5 flex flex-col items-center gap-2 text-ink-500 hover:border-brand-400 hover:bg-brand-50/30 hover:text-brand-600 transition-all">
                  <Icon name="plus" className="w-5 h-5" strokeWidth={2} />
                  <span className="text-xs font-medium">เพิ่มรูป (ภาพหน้างาน / สลิป / ใบเสร็จ)</span>
                  <span className="text-[10px] text-ink-400">รองรับหลายรูป · JPG / PNG</span>
                </button>
              ) : (
                <div className="grid grid-cols-4 gap-2">
                  {photos.map((url, i) => (
                    <div key={i} className="relative aspect-square rounded-lg overflow-hidden border border-ink-200 group">
                      <img src={url} alt={`photo ${i+1}`} className="w-full h-full object-cover" />
                      <button onClick={() => removePhoto(i)}
                        className="absolute top-1 right-1 w-5 h-5 rounded-full bg-ink-900/80 text-white flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
                        <Icon name="x" className="w-3 h-3" strokeWidth={2.5} />
                      </button>
                    </div>
                  ))}
                  <button onClick={() => fileInputRef.current?.click()}
                    className="aspect-square rounded-lg border-2 border-dashed border-ink-200 flex items-center justify-center text-ink-400 hover:border-brand-400 hover:text-brand-600 hover:bg-brand-50/30 transition-all">
                    <Icon name="plus" className="w-5 h-5" strokeWidth={2} />
                  </button>
                </div>
              )}
            </div>
          </Field>
        )}

        <Field label="โน้ต">
          <textarea value={notes} onChange={e => setNotes(e.target.value)} rows={3} className="input resize-none" placeholder="ผลการนัด, สิ่งที่ต้องตามต่อ" />
        </Field>
      </div>
      <style>{`
        .input { width: 100%; padding: 8px 12px; font-size: 13px; border: 1px solid #C9D2E3; border-radius: 8px; background: white; outline: none; color: #0F1E38; }
        .input:focus { border-color: #2F5DE5; box-shadow: 0 0 0 3px rgba(47,93,229,0.15); }
      `}</style>
    </Modal>
  );
}

// Warning shown when the proposed BI/postpone slot overlaps existing appointments
function ConflictWarning({ conflicts, apptTypes }) {
  if (!conflicts || conflicts.length === 0) {
    return (
      <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-emerald-50 border border-emerald-200 text-[11px] text-emerald-700">
        <Icon name="check" className="w-3.5 h-3.5" strokeWidth={2.5} />
        <span className="font-medium">ช่วงเวลานี้ว่าง · ไม่ชนกับนัดอื่น</span>
      </div>
    );
  }
  return (
    <div className="rounded-lg bg-rose-50 border border-rose-200 p-3">
      <div className="flex items-center gap-2 text-rose-700 mb-2">
        <span className="text-base leading-none">⚠️</span>
        <span className="text-xs font-semibold">เวลานี้ชนกับ {conflicts.length} นัดอื่น</span>
      </div>
      <ul className="space-y-1.5">
        {conflicts.map(c => {
          const t = apptTypes.find(x => x.id === c.type);
          return (
            <li key={c.id} className="flex items-center gap-2 text-[11px] text-ink-700">
              <span className="px-1.5 py-0.5 rounded text-[10px] font-bold text-white" style={{ background: t?.color || '#94A3B8' }}>{t?.label || c.type}</span>
              <span className="num text-ink-500">{DAYS_FULL[c.day]} · {formatTime(c.start)}–{formatTime(c.start + c.dur)}</span>
              <span className="text-ink-300">·</span>
              <span className="font-medium truncate flex-1">{c.prospect}</span>
            </li>
          );
        })}
      </ul>
      <div className="text-[10px] text-rose-600 mt-2">ลองเปลี่ยนวัน/เวลา หรือยืนยันถ้าตั้งใจซ้อน</div>
    </div>
  );
}

// Simple inline day + time picker (works for week-of-current-view)
function DateTimePicker({ day, start, onDay, onStart, color = '#2F5DE5' }) {
  const days = DAYS_FULL;
  return (
    <div className="grid grid-cols-12 gap-3">
      <div className="col-span-8">
        <div className="text-[10px] font-medium text-ink-500 mb-1.5 uppercase tracking-wide">วัน</div>
        <div className="grid grid-cols-7 gap-1">
          {days.map((d, i) => (
            <button key={i} onClick={() => onDay(i)}
              className={`py-1.5 rounded-md text-[10px] font-semibold transition-all border ${day === i ? 'text-white border-transparent' : 'bg-white border-ink-200 text-ink-600 hover:border-ink-300'}`}
              style={day === i ? { background: color } : {}}>
              <div className="text-[9px] opacity-70 leading-none">{d.split(' ')[0]}</div>
              <div className="text-xs num mt-0.5 leading-none">{d.split(' ')[1]}</div>
            </button>
          ))}
        </div>
      </div>
      <div className="col-span-4">
        <div className="text-[10px] font-medium text-ink-500 mb-1.5 uppercase tracking-wide">เวลา</div>
        <select value={start} onChange={e => onStart(parseFloat(e.target.value))}
          className="w-full h-8 px-2 text-xs num border border-ink-200 rounded-md bg-white focus:outline-none focus:border-brand-500">
          {Array.from({ length: 26 }, (_, i) => 8 + i * 0.5).map(t => (
            <option key={t} value={t}>{formatTime(t)}</option>
          ))}
        </select>
      </div>
    </div>
  );
}

const Field = ({ label, children }) => (
  <div>
    <div className="text-[11px] font-medium text-ink-500 mb-1.5 uppercase tracking-wide">{label}</div>
    {children}
  </div>
);

function ActivityLog({ appts }) {
  const { apptTypes, leadSources } = useConfig();
  // Build event entries from appointments
  const events = useMemo(() => {
    const list = [];
    appts.forEach(a => {
      const t = apptTypes.find(x => x.id === a.type);
      const s = STATUS.find(x => x.id === a.status);
      const src = leadSources.find(x => x.id === a.source);
      list.push({
        day: a.day,
        time: a.start,
        type: t,
        status: s,
        source: src,
        prospect: a.prospect,
        notes: a.notes,
      });
    });
    return list.sort((a, b) => (a.day - b.day) || (a.time - b.time));
  }, [appts]);

  return (
    <Card pad={false}>
      <div className="px-5 pt-4 pb-2 flex items-center justify-between">
        <div>
          <h3 className="text-sm font-semibold text-ink-800">Activity Log สัปดาห์นี้</h3>
          <p className="text-[11px] text-ink-400">Auto-synced จาก calendar · Leader เห็นแบบ real-time</p>
        </div>
        <button className="text-xs font-medium text-brand-600 hover:text-brand-700">ดูทั้งหมด →</button>
      </div>
      <div className="px-5 pb-5">
        <div className="overflow-x-auto scroll-thin">
          <table className="w-full text-xs min-w-[640px]">
            <thead>
              <tr className="text-ink-400 text-[10px] uppercase tracking-wider">
                <th className="text-left font-medium py-2 pr-3">When</th>
                <th className="text-left font-medium py-2 pr-3">Type</th>
                <th className="text-left font-medium py-2 pr-3">Prospect</th>
                <th className="text-left font-medium py-2 pr-3">Source</th>
                <th className="text-left font-medium py-2 pr-3">Status</th>
                <th className="text-left font-medium py-2 pr-3">Notes</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-ink-100">
              {events.slice(0, 6).map((e, i) => (
                <tr key={i} className="hover:bg-ink-50/50">
                  <td className="py-2.5 pr-3 num text-ink-700">{DAYS_FULL[e.day].split(' ')[0]} · {formatTime(e.time)}</td>
                  <td className="py-2.5 pr-3">
                    <Pill color={e.type.color} tint={e.type.tint}>{e.type.label}</Pill>
                  </td>
                  <td className="py-2.5 pr-3 font-medium text-ink-900">{e.prospect}</td>
                  <td className="py-2.5 pr-3 text-ink-600">
                    <span className="inline-flex items-center gap-1.5">
                      <span className="w-1.5 h-1.5 rounded-full" style={{ background: e.source.color }} />
                      {e.source.label}
                    </span>
                  </td>
                  <td className="py-2.5 pr-3">
                    <Pill color={e.status.color} tint={e.status.tint}>{e.status.label}</Pill>
                  </td>
                  <td className="py-2.5 pr-3 text-ink-500 truncate max-w-[200px]">{e.notes || '—'}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </Card>
  );
}

window.CalendarView = CalendarView;

// ============== Type summary tile (clickable) ==============
function TypeStatTile({ type, appts, onClick }) {
  const total = appts.length;
  const completed = appts.filter(a => a.status === 'completed').length;
  const pending   = appts.filter(a => a.status === 'pending').length;
  const followup  = appts.filter(a => a.status === 'followup').length;
  const closeRate = total > 0 ? Math.round(completed / total * 100) : 0;

  return (
    <button onClick={onClick}
      className="group relative text-left bg-white rounded-2xl border border-ink-100 hover:border-ink-200 hover:shadow-lift transition-all overflow-hidden">
      {/* Top color band */}
      <div className="h-1" style={{ background: type.color }} />
      <div className="p-4">
        <div className="flex items-center gap-2 mb-3">
          <div className="w-8 h-8 rounded-lg flex items-center justify-center text-white font-bold text-xs" style={{ background: type.color }}>
            {type.label}
          </div>
          <div className="min-w-0 flex-1">
            <div className="text-sm font-semibold text-ink-900 truncate">{type.full}</div>
            <div className="text-[10px] text-ink-400 truncate">{type.desc}</div>
          </div>
          <Icon name="chevR" className="w-3.5 h-3.5 text-ink-300 group-hover:text-ink-700 group-hover:translate-x-0.5 transition-all" />
        </div>

        <div className="flex items-baseline gap-2 mb-3">
          <span className="text-3xl font-semibold num text-ink-900">{total}</span>
          <span className="text-xs text-ink-400">cases · {closeRate}% close</span>
        </div>

        {/* Status mini bar */}
        <div className="flex h-1.5 rounded-full overflow-hidden bg-ink-100 mb-2.5">
          <div style={{ width: total ? `${completed/total*100}%` : 0, background: '#10B981' }} />
          <div style={{ width: total ? `${pending/total*100}%`   : 0, background: '#F59E0B' }} />
          <div style={{ width: total ? `${followup/total*100}%`  : 0, background: '#2F5DE5' }} />
        </div>

        <div className="flex items-center justify-between text-[11px]">
          <span className="inline-flex items-center gap-1 text-emerald-600 num font-medium">
            <span className="w-1.5 h-1.5 rounded-full bg-emerald-500" />ปิด {completed}
          </span>
          <span className="inline-flex items-center gap-1 text-gold-600 num font-medium">
            <span className="w-1.5 h-1.5 rounded-full bg-gold-500" />ค้าง {pending}
          </span>
          <span className="inline-flex items-center gap-1 text-brand-600 num font-medium">
            <span className="w-1.5 h-1.5 rounded-full bg-brand-500" />FU {followup}
          </span>
        </div>
      </div>
    </button>
  );
}

// ============== Follow-up watchlist card ==============
function FollowUpCard({ appts, onOpenAppt }) {
  const { apptTypes } = useConfig();
  const [tab, setTab] = useState('pending');

  const pending  = appts.filter(a => a.status === 'pending').sort((a,b) => (a.day-b.day) || (a.start-b.start));
  const followup = appts.filter(a => a.status === 'followup').sort((a,b) => (a.day-b.day) || (a.start-b.start));
  const list = tab === 'pending' ? pending : followup;

  return (
    <Card pad={false} className="h-full">
      <div className="px-5 pt-4 pb-3 flex items-center justify-between">
        <div className="flex items-center gap-2">
          <div className="w-7 h-7 rounded-md bg-gold-50 text-gold-600 flex items-center justify-center">
            <Icon name="bell" className="w-3.5 h-3.5" />
          </div>
          <div>
            <h3 className="text-sm font-semibold text-ink-800">ต้องตามต่อ</h3>
            <p className="text-[10px] text-ink-400">รายชื่อที่ต้องติดตาม</p>
          </div>
        </div>
        <span className="text-[11px] num font-semibold text-rose-500">{pending.length + followup.length} เคส</span>
      </div>

      {/* Tabs */}
      <div className="px-5 pb-2 flex items-center gap-1">
        <button onClick={() => setTab('pending')}
          className={`flex items-center gap-1.5 px-2.5 py-1 rounded-md text-[11px] font-semibold transition-all ${tab === 'pending' ? 'bg-gold-100 text-gold-700' : 'text-ink-500 hover:bg-ink-50'}`}>
          <span className="w-1.5 h-1.5 rounded-full bg-gold-500" />
          Pending <span className="num">{pending.length}</span>
        </button>
        <button onClick={() => setTab('followup')}
          className={`flex items-center gap-1.5 px-2.5 py-1 rounded-md text-[11px] font-semibold transition-all ${tab === 'followup' ? 'bg-brand-100 text-brand-700' : 'text-ink-500 hover:bg-ink-50'}`}>
          <span className="w-1.5 h-1.5 rounded-full bg-brand-500" />
          Follow-up <span className="num">{followup.length}</span>
        </button>
      </div>

      {/* List */}
      <div className="px-3 pb-3 max-h-[280px] overflow-y-auto scroll-thin">
        {list.length === 0 ? (
          <div className="text-center py-8 text-[11px] text-ink-400">ไม่มีรายการที่ต้องตาม 🎉</div>
        ) : (
          <ul className="space-y-1">
            {list.map(a => {
              const t = apptTypes.find(x => x.id === a.type) || { label: '?', color: '#94A3B8' };
              const overdue = a.day < 3;
              return (
                <li key={a.id}>
                  <button onClick={() => onOpenAppt(a)}
                    className="w-full flex items-center gap-2.5 p-2 rounded-lg hover:bg-ink-50 transition-colors text-left group">
                    <div className="w-9 h-9 rounded-md flex-shrink-0 flex flex-col items-center justify-center text-white text-[9px] font-bold leading-none" style={{ background: t.color }}>
                      <div>{t.label}</div>
                      <div className="text-[8px] opacity-80 mt-0.5">{formatTime(a.start)}</div>
                    </div>
                    <div className="flex-1 min-w-0">
                      <div className="text-xs font-semibold text-ink-900 truncate">{a.prospect}</div>
                      <div className="text-[10px] text-ink-400 num">{DAYS_FULL[a.day].split(' ')[0]} · {DAYS_FULL[a.day].split(' ')[1]} พ.ย.</div>
                    </div>
                    {overdue && <Pill color="#EF4444" tint="#FEE2E2" size="xs">เลย</Pill>}
                    <Icon name="chevR" className="w-3 h-3 text-ink-300 group-hover:text-ink-700 group-hover:translate-x-0.5 transition-all flex-shrink-0" />
                  </button>
                </li>
              );
            })}
          </ul>
        )}
      </div>
    </Card>
  );
}

// ============== Type detail modal ==============
function TypeDetailModal({ open, onClose, typeId, appts, onOpenAppt }) {
  const { apptTypes, leadSources } = useConfig();
  if (!typeId) return null;
  const type = apptTypes.find(t => t.id === typeId);
  if (!type) return null;
  const list = appts.filter(a => a.type === typeId).sort((a, b) => (a.day - b.day) || (a.start - b.start));

  const grouped = {
    pending:   list.filter(a => a.status === 'pending'),
    completed: list.filter(a => a.status === 'completed'),
    followup:  list.filter(a => a.status === 'followup'),
    cancelled: list.filter(a => a.status === 'cancelled'),
  };

  return (
    <Modal open={open} onClose={onClose} size="lg" title={
      <div className="flex items-center gap-2.5">
        <div className="w-9 h-9 rounded-lg flex items-center justify-center text-white font-bold" style={{ background: type.color }}>
          {type.label}
        </div>
        <div>
          <div className="text-sm font-semibold text-ink-900">{type.full}</div>
          <div className="text-[11px] text-ink-400">{list.length} เคส · สัปดาห์นี้</div>
        </div>
      </div>
    } footer={
      <div className="flex items-center justify-between">
        <span className="text-[11px] text-ink-400">คลิกแถวเพื่อแก้ไขนัด</span>
        <Btn variant="ghost" size="sm" onClick={onClose}>ปิด</Btn>
      </div>
    }>
      {/* Status summary chips */}
      <div className="grid grid-cols-4 gap-2 mb-4">
        {[
          { id: 'pending',   label: 'Pending',   color: '#F59E0B', tint: '#FFF6E0' },
          { id: 'completed', label: 'Completed', color: '#10B981', tint: '#E7F8F1' },
          { id: 'followup',  label: 'Follow-up', color: '#2F5DE5', tint: '#EEF4FF' },
          { id: 'cancelled', label: 'Cancelled', color: '#94A3B8', tint: '#F1F5F9' },
        ].map(s => (
          <div key={s.id} className="rounded-lg p-2 text-center" style={{ background: s.tint }}>
            <div className="text-xl font-semibold num" style={{ color: s.color }}>{grouped[s.id].length}</div>
            <div className="text-[10px] font-medium" style={{ color: s.color }}>{s.label}</div>
          </div>
        ))}
      </div>

      {/* List */}
      <div className="max-h-[360px] overflow-y-auto scroll-thin -mx-2">
        {list.length === 0 ? (
          <div className="text-center py-12 text-sm text-ink-400">ยังไม่มีเคสในสัปดาห์นี้</div>
        ) : (
          <ul className="space-y-1 px-2">
            {list.map(a => {
              const src = leadSources.find(x => x.id === a.source) || { label: '—', color: '#94A3B8' };
              const status = window.STATUS.find(x => x.id === a.status);
              return (
                <li key={a.id}>
                  <button onClick={() => onOpenAppt(a)}
                    className="w-full flex items-center gap-3 p-2.5 rounded-lg hover:bg-ink-50 transition-colors text-left">
                    {/* Date pill */}
                    <div className="w-12 text-center flex-shrink-0">
                      <div className="text-[10px] uppercase font-bold text-ink-400 leading-none">{DAYS_FULL[a.day].split(' ')[0]}</div>
                      <div className="text-base font-semibold num text-ink-900 mt-1">{DAYS_FULL[a.day].split(' ')[1]}</div>
                    </div>
                    <div className="w-px h-9 bg-ink-100 flex-shrink-0" />
                    {/* Body */}
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-2 mb-0.5">
                        <span className="text-sm font-semibold text-ink-900 truncate">{a.prospect}</span>
                        <span className="text-[11px] num text-ink-500 flex-shrink-0">{formatTime(a.start)}</span>
                      </div>
                      <div className="flex items-center gap-2 text-[11px] text-ink-500">
                        <span className="inline-flex items-center gap-1">
                          <span className="w-1.5 h-1.5 rounded-full" style={{ background: src.color }} />
                          {src.label}
                        </span>
                        {a.notes && (
                          <>
                            <span className="text-ink-300">·</span>
                            <span className="truncate text-ink-400">{a.notes}</span>
                          </>
                        )}
                      </div>
                    </div>
                    {/* Status */}
                    <Pill color={status.color} tint={status.tint} size="xs">{status.label}</Pill>
                  </button>
                </li>
              );
            })}
          </ul>
        )}
      </div>
    </Modal>
  );
}
