// Calendar grid component

const { TH_MONTHS, TH_DAYS_SHORT, fmtISO, parseISO, isHoliday, isWorkDay } = window.APP_HELPERS;

function buildMonthCells(year, month) {
  // Returns 42-cell array (6 weeks * 7 days) — Monday-first
  const first = new Date(year, month, 1);
  const startDow = (first.getDay() + 6) % 7; // Mon=0..Sun=6
  const cells = [];
  for (let i = 0; i < 42; i++) {
    const d = new Date(year, month, 1 + (i - startDow));
    cells.push(d);
  }
  return cells;
}

// Display order: Mon Tue Wed Thu Fri Sat Sun
const WEEK_LABELS = ['จ.','อ.','พ.','พฤ.','ศ.','ส.','อา.'];
const WEEK_IS_SUN = [false, false, false, false, false, false, true];

// Aggregate day events for an employee-day
function getDayEvents(date, data) {
  const iso = fmtISO(date);
  const events = []; // {type, empId, label}

  data.leaves.forEach(l => {
    if (l.status === 'approved' && iso >= l.from && iso <= l.to) {
      events.push({ type: l.type, empId: l.empId, ref: l });
    }
  });
  data.swapRequests.forEach(s => {
    if (s.status === 'approved') {
      if (s.swapOffDate === iso) events.push({ type: 'swap-off', empId: s.empId, ref: s });
      if (s.swapWorkDate === iso) events.push({ type: 'swap-work', empId: s.empId, ref: s });
    }
  });
  data.otRequests.forEach(o => {
    if (o.status === 'approved' && o.date === iso) {
      events.push({ type: 'ot', empId: o.empId, ref: o });
    }
  });
  data.specialOffs.forEach(x => {
    if (x.date === iso) events.push({ type: 'special', empId: x.empId, ref: x });
  });
  return events;
}

// Returns counts {working, off}
function getHeadcount(date, data) {
  const total = data.employees.length;
  const events = getDayEvents(date, data);
  const isWeekend = !data.settings.workDays.includes(date.getDay());
  const isHol = isHoliday(date, data.holidays);

  if (isWeekend || isHol) {
    // Only workers if OT or swap-work
    const workers = new Set();
    events.forEach(e => { if (e.type === 'ot' || e.type === 'swap-work') workers.add(e.empId); });
    return { working: workers.size, off: total - workers.size, isOff: true };
  }
  // Work day
  const offEmployees = new Set();
  events.forEach(e => {
    if (['vacation', 'sick', 'personal', 'special', 'swap-off'].includes(e.type)) offEmployees.add(e.empId);
  });
  return { working: total - offEmployees.size, off: offEmployees.size, isOff: false };
}

const TYPE_TO_CLASS = {
  vacation: 'vac',
  sick: 'sick',
  personal: 'pers',
  ot: 'ot',
  'swap-work': 'swap',
  'swap-off': 'swap',
  special: 'special',
};

// Bullet character + color per leave type — shown as prefix in calendar cells
const TYPE_BULLET = {
  vacation:    { ch: 'V', color: 'var(--vac)' },
  sick:        { ch: 'S', color: 'var(--sick)' },
  personal:    { ch: 'P', color: 'var(--pers)' },
  ot:          { ch: 'O', color: 'var(--ot)' },
  'swap-work': { ch: '⇄', color: 'var(--swap)' },
  'swap-off':  { ch: '⇄', color: 'var(--swap)' },
  special:     { ch: '★', color: 'var(--special)' },
};

const TypeBullet = ({ type, size = 14 }) => {
  const b = TYPE_BULLET[type];
  if (!b) return null;
  return (
    <span style={{
      display: 'inline-grid',
      placeItems: 'center',
      width: size, height: size,
      borderRadius: '50%',
      background: b.color,
      color: 'white',
      fontSize: size * 0.6,
      fontWeight: 700,
      fontFamily: 'Inter, sans-serif',
      flexShrink: 0,
      lineHeight: 1,
    }}>{b.ch}</span>
  );
};

const CalendarMonth = ({ view, setView, selected, setSelected, data, today }) => {
  const { year, month } = view;
  const cells = React.useMemo(() => buildMonthCells(year, month), [year, month]);
  const empMap = React.useMemo(() => Object.fromEntries(data.employees.map(e => [e.id, e])), [data.employees]);

  const goPrev = () => setView({ year: month === 0 ? year - 1 : year, month: (month + 11) % 12 });
  const goNext = () => setView({ year: month === 11 ? year + 1 : year, month: (month + 1) % 12 });
  const goToday = () => setView({ year: today.getFullYear(), month: today.getMonth() });

  return (
    <div>
      <div className="cal-toolbar">
        <div className="cal-nav">
          <button onClick={goPrev} title="เดือนก่อน"><Icon name="chevLeft" size={14}/></button>
          <button onClick={goNext} title="เดือนถัดไป"><Icon name="chevRight" size={14}/></button>
        </div>
        <button className="btn btn-ghost btn-sm" onClick={goToday}>วันนี้</button>
        <div className="cal-month">
          {TH_MONTHS[month]}
          <span className="cal-month-year">{year + 543}</span>
        </div>
        <div style={{ marginLeft: 'auto' }} className="legend">
          <span className="legend-item"><TypeBullet type="vacation" size={14}/>พักร้อน</span>
          <span className="legend-item"><TypeBullet type="sick" size={14}/>ลาป่วย</span>
          <span className="legend-item"><TypeBullet type="personal" size={14}/>ลากิจ</span>
          <span className="legend-item"><TypeBullet type="ot" size={14}/>OT</span>
          <span className="legend-item"><TypeBullet type="swap-work" size={14}/>สลับ</span>
          <span className="legend-item"><TypeBullet type="special" size={14}/>หยุดพิเศษ</span>
          <span className="legend-item"><span className="legend-swatch" style={{background:'var(--hol)'}}/>นักขัตฤกษ์</span>
        </div>
      </div>

      <div className="cal-grid">
        <div className="cal-headers">
          {WEEK_LABELS.map((d, i) => (
            <div key={i} className={`cal-header ${WEEK_IS_SUN[i] ? 'sun' : ''}`}>{d}</div>
          ))}
        </div>
        <div className="cal-body">
          {cells.map((d, i) => {
            const inMonth = d.getMonth() === month;
            const isToday = fmtISO(d) === fmtISO(today);
            const isSel = selected && fmtISO(d) === fmtISO(selected);
            const hol = isHoliday(d, data.holidays);
            const isSun = d.getDay() === 0;
            const events = getDayEvents(d, data);
            const head = getHeadcount(d, data);
            const total = data.employees.length;

            const classes = [
              'cal-cell',
              !inMonth && 'other-month',
              isSun && 'weekend',
              hol && 'holiday',
              isToday && 'today',
              isSel && 'selected',
            ].filter(Boolean).join(' ');

            // Show up to 3 events visibly
            const shown = events.slice(0, 3);
            const overflow = events.length - shown.length;

            return (
              <div key={i} className={classes} onClick={() => setSelected(d)}>
                <div className="cal-day-head">
                  <span className={`cal-day-num ${isToday ? 'today' : ''}`}>{d.getDate()}</span>
                  {hol && <span className="cal-day-label" title={hol.name}>{hol.name}</span>}
                </div>

                {shown.map((ev, k) => {
                  const emp = empMap[ev.empId];
                  if (!emp) return null;
                  const cls = TYPE_TO_CLASS[ev.type] || '';
                  const typeLabel = {
                    vacation: 'พักร้อน', sick: 'ป่วย', personal: 'กิจ',
                    ot: 'OT', 'swap-work': 'มาแทน', 'swap-off': 'หยุดแทน',
                    special: 'หยุดพิเศษ',
                  }[ev.type];
                  return (
                    <div key={k} className={`cal-event ${cls}`} title={`${emp.name} · ${typeLabel}`}>
                      <TypeBullet type={ev.type}/>
                      <span>{emp.name.split(' ')[0]} · {typeLabel}</span>
                    </div>
                  );
                })}
                {overflow > 0 && <div className="cal-more">+{overflow} อีก</div>}

                {inMonth && (
                  <div className="cal-headroom">
                    {head.isOff ? (
                      head.working > 0 && (
                        <span className="headcount" title="ทำงาน/OT">
                          {head.working} คน OT
                        </span>
                      )
                    ) : (
                      <span className={`headcount ${head.working === 0 ? 'low' : (head.working === total ? 'full' : '')}`} title="คนทำงานวันนี้">
                        {head.working}/{total} คน
                      </span>
                    )}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
};

window.CalendarMonth = CalendarMonth;
window.getDayEvents = getDayEvents;
window.getHeadcount = getHeadcount;
window.TYPE_TO_CLASS = TYPE_TO_CLASS;
