/**
 * Promotions Calendar - React App
 * Month, Week, and List views with promotion bars spanning start-to-end dates.
 * Basecamp UI aligned.
 */
const { useState, useEffect } = React;

const PAST_PROMO_GREY = '#D0D0D0';

function isPromotionPast(promo) {
  if (!promo.endDate) return false;
  const end = new Date(promo.endDate + 'T23:59:59');
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  return end < today;
}

function getPromotionColor(promo) {
  if (isPromotionPast(promo)) return PAST_PROMO_GREY;
  /* Pastel palette - 9 colors */
  const palette = [
    '#FFF0CA', '#F6CBD5', '#C4DCFF',
    '#EBCEFF', '#D4E9D8', '#FFDFBD',
    '#C6CFE0', '#AFC3C4', '#E2CDD9',
  ];
  const typeMap = { Standard: 0, SKU: 1, Bundle: 2, Seasonal: 3 };
  const typeIdx = typeMap[promo.type] !== undefined ? typeMap[promo.type] : null;
  if (typeIdx !== null) return palette[typeIdx % palette.length];
  const key = promo.id || promo.name || '';
  let hash = 0;
  for (let i = 0; i < key.length; i++) hash = ((hash << 5) - hash) + key.charCodeAt(i);
  return palette[Math.abs(hash) % palette.length];
}

function overlapsDateRange(promo, rangeStart, rangeEnd) {
  const start = new Date(promo.startDate + 'T00:00:00');
  const end = promo.endDate ? new Date(promo.endDate + 'T23:59:59') : new Date(start.getTime() + 365 * 24 * 60 * 60 * 1000);
  return start <= rangeEnd && end >= rangeStart;
}

function getWeekStart(d) {
  const date = new Date(d);
  const day = date.getDay();
  const diff = date.getDate() - day + (day === 0 ? -6 : 1);
  return new Date(date.setDate(diff));
}

function getDaysInMonth(year, month) {
  const first = new Date(year, month, 1);
  const start = new Date(first);
  start.setDate(start.getDate() - (start.getDay() === 0 ? 6 : start.getDay() - 1));
  const days = [];
  for (let i = 0; i < 42; i++) {
    const d = new Date(start);
    d.setDate(d.getDate() + i);
    days.push(d);
  }
  return days;
}

function getWeekDays(weekStart) {
  const days = [];
  const d = new Date(weekStart);
  for (let i = 0; i < 7; i++) {
    days.push(new Date(d));
    d.setDate(d.getDate() + 1);
  }
  return days;
}

function formatPromotionItemLabel(product, fallback = 'Item') {
  const itemCode = (product?.itemCode || '').toString().trim();
  const description = (product?.description || '').toString().trim();
  if (itemCode && description) return `${itemCode} | ${description}`;
  if (itemCode) return itemCode;
  if (description) return description;
  return fallback;
}

function MiniCalendar({ currentDate, onDateSelect }) {
  const year = currentDate.getFullYear();
  const month = currentDate.getMonth();
  const days = getDaysInMonth(year, month);
  const dayLabels = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
  const today = new Date();

  const goPrevMonth = () => {
    const d = new Date(year, month - 1, 1);
    onDateSelect(d);
  };
  const goNextMonth = () => {
    const d = new Date(year, month + 1, 1);
    onDateSelect(d);
  };

  return (
    <div className="promo-mini-calendar">
      <div className="promo-mini-calendar-header">
        <span className="promo-mini-calendar-title">
          {currentDate.toLocaleDateString('en-AU', { month: 'long', year: 'numeric' })}
        </span>
        <div className="promo-mini-calendar-nav">
          <button type="button" className="promo-mini-calendar-btn" onClick={goPrevMonth} aria-label="Previous month">
            <i className="fas fa-chevron-left"></i>
          </button>
          <button type="button" className="promo-mini-calendar-btn" onClick={goNextMonth} aria-label="Next month">
            <i className="fas fa-chevron-right"></i>
          </button>
        </div>
      </div>
      <div className="promo-mini-calendar-grid">
        {dayLabels.map((l, i) => (
          <div key={i} className="promo-mini-calendar-day-label">{l}</div>
        ))}
        {days.map((d) => {
          const isCurrentMonth = d.getMonth() === month;
          const isToday = d.toDateString() === today.toDateString();
          const isSelected = d.getDate() === currentDate.getDate() && d.getMonth() === currentDate.getMonth() && d.getFullYear() === currentDate.getFullYear();
          return (
            <button
              key={d.toISOString()}
              type="button"
              className={`promo-mini-calendar-date ${!isCurrentMonth ? 'other-month' : ''} ${isToday ? 'today' : ''} ${isSelected ? 'selected' : ''}`}
              onClick={() => onDateSelect(new Date(d))}
            >
              {d.getDate()}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function getBarsForPromotions(promotions, viewStart, viewEnd) {
  const bars = [];
  const rows = [];

  promotions.forEach((promo, idx) => {
    const start = new Date(promo.startDate + 'T00:00:00');
    const end = promo.endDate ? new Date(promo.endDate + 'T23:59:59') : new Date(start.getTime() + 365 * 24 * 60 * 60 * 1000);
    if (end < viewStart || start > viewEnd) return;

    const barStart = start < viewStart ? viewStart : start;
    const barEnd = end > viewEnd ? viewEnd : end;
    const colStart = Math.floor((barStart - viewStart) / (24 * 60 * 60 * 1000));
    const colSpan = Math.max(1, Math.ceil((barEnd - barStart) / (24 * 60 * 60 * 1000)) + 1);

    let row = 0;
    while (rows[row] && rows[row].some(r => r.colStart + r.colSpan > colStart && r.colStart < colStart + colSpan)) {
      row++;
    }
    if (!rows[row]) rows[row] = [];
    rows[row].push({ colStart, colSpan, promo, color: getPromotionColor(promo) });

    bars.push({
      promo,
      row,
      colStart,
      colSpan,
      color: getPromotionColor(promo),
    });
  });

  return bars;
}

function PromotionDetailModal({ promotion, onClose }) {
  if (!promotion) return null;

  const products = promotion.products || [];
  const formatPrice = (p) => (!p || p === '0' || p === '') ? '-' : `$${parseFloat(p).toFixed(2)}`;
  const startDate = promotion.startDate ? new Date(promotion.startDate).toLocaleDateString() : '-';
  const endDate = promotion.endDate ? new Date(promotion.endDate).toLocaleDateString() : promotion.isOngoing ? 'Ongoing' : '-';

  return (
    <div className="modal show d-block" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }} onClick={onClose}>
      <div className="modal-dialog modal-xl modal-dialog-centered" onClick={e => e.stopPropagation()}>
        <div className="modal-content" style={{ borderRadius: 'var(--card-radius)' }}>
          <div className="modal-header border-bottom">
            <h5 className="modal-title fw-semibold">{promotion.name}</h5>
            <button type="button" className="btn-close" onClick={onClose} aria-label="Close"></button>
          </div>
          <div className="modal-body">
            <div className="mb-3">
              <span className="badge bg-primary me-2">{promotion.type || 'Standard'}</span>
              <span className="text-secondary">
                <i className="fas fa-calendar-alt me-1"></i>
                {startDate} – {endDate}
              </span>
            </div>
            {promotion.notes && (
              <div className="mb-3 text-secondary small">
                <i className="fas fa-sticky-note me-1"></i>{promotion.notes}
              </div>
            )}
            <h6 className="mb-2">Products ({products.length})</h6>
            <div className="table-responsive">
              <table className="table table-sm table-hover">
                <thead>
                  <tr>
                    <th>Item Code</th>
                    <th>Description</th>
                    <th>RRP</th>
                    <th>Web Price</th>
                    <th>Rebate</th>
                  </tr>
                </thead>
                <tbody>
                  {products.length === 0 ? (
                    <tr>
                      <td colSpan="5" className="text-center text-muted py-4">
                        <i className="fas fa-box-open fa-2x mb-2"></i>
                        <br />No products in this promotion
                      </td>
                    </tr>
                  ) : (
                    products.map((p, i) => (
                      <tr key={i}>
                        <td className="fw-medium">{p.itemCode || 'N/A'}</td>
                        <td><small className="text-secondary">{p.description || 'N/A'}</small></td>
                        <td>{formatPrice(p.rrp)}</td>
                        <td>{p.webPrice ? `$${parseFloat(p.webPrice).toFixed(2)}` : '-'}</td>
                        <td>
                          {p.rebate && parseFloat(p.rebate) > 0 ? (
                            <span className="badge bg-primary">${parseFloat(p.rebate).toFixed(2)}</span>
                          ) : '-'}
                        </td>
                      </tr>
                    ))
                  )}
                </tbody>
              </table>
            </div>
          </div>
          <div className="modal-footer">
            <button type="button" className="btn btn-secondary" onClick={onClose}>Close</button>
          </div>
        </div>
      </div>
    </div>
  );
}

function flattenPromotionItems(promotions) {
  const items = [];
  promotions.forEach((promo) => {
    const products = Array.isArray(promo.products) ? promo.products : [];
    products.forEach((product, idx) => {
      const itemCode = (product.itemCode || '').toString().trim();
      const description = (product.description || '').toString().trim();
      const label = formatPromotionItemLabel(product, `Item ${idx + 1}`);
      items.push({
        id: `${promo.id || promo.name || 'promo'}::${itemCode || description || idx}`,
        name: label,
        startDate: promo.startDate,
        endDate: promo.endDate,
        type: promo.type || 'Standard',
        notes: promo.notes || '',
        item: product,
        promotion: {
          id: promo.id,
          name: promo.name,
          type: promo.type,
          startDate: promo.startDate,
          endDate: promo.endDate,
          notes: promo.notes,
        },
      });
    });
  });
  return items;
}

function ItemDetailModal({ itemEntry, onClose }) {
  if (!itemEntry) return null;
  const p = itemEntry.promotion || {};
  const i = itemEntry.item || {};

  const formatPrice = (v) => (!v || v === '0' || v === '') ? '-' : `$${parseFloat(v).toFixed(2)}`;
  const dateRange = `${p.startDate ? new Date(p.startDate).toLocaleDateString() : '-'} - ${p.endDate ? new Date(p.endDate).toLocaleDateString() : 'Ongoing'}`;

  return (
    <div className="modal show d-block" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }} onClick={onClose}>
      <div className="modal-dialog modal-lg modal-dialog-centered" onClick={e => e.stopPropagation()}>
        <div className="modal-content" style={{ borderRadius: 'var(--card-radius)' }}>
          <div className="modal-header border-bottom">
            <h5 className="modal-title fw-semibold">{itemEntry.name}</h5>
            <button type="button" className="btn-close" onClick={onClose} aria-label="Close"></button>
          </div>
          <div className="modal-body">
            <div className="mb-3">
              <span className="badge bg-primary me-2">{p.type || 'Standard'}</span>
              <span className="text-secondary small">
                <i className="fas fa-calendar-alt me-1"></i>{dateRange}
              </span>
            </div>
            <div className="card mb-3">
              <div className="card-body">
                <div className="small text-secondary mb-1">Promotion</div>
                <div className="fw-semibold">{p.name || 'Unknown Promotion'}</div>
              </div>
            </div>
            <div className="table-responsive">
              <table className="table table-sm table-hover mb-0">
                <tbody>
                  <tr><th style={{ width: 160 }}>Item Code</th><td>{i.itemCode || '-'}</td></tr>
                  <tr><th>Description</th><td>{i.description || '-'}</td></tr>
                  <tr><th>RRP</th><td>{formatPrice(i.rrp)}</td></tr>
                  <tr><th>Web Price</th><td>{i.webPrice ? `$${parseFloat(i.webPrice).toFixed(2)}` : '-'}</td></tr>
                  <tr><th>Rebate</th><td>{i.rebate && parseFloat(i.rebate) > 0 ? `$${parseFloat(i.rebate).toFixed(2)}` : '-'}</td></tr>
                </tbody>
              </table>
            </div>
          </div>
          <div className="modal-footer">
            <button type="button" className="btn btn-secondary" onClick={onClose}>Close</button>
          </div>
        </div>
      </div>
    </div>
  );
}

function getBarsForWeek(promotions, weekStart, weekEnd, monthStart, monthEnd) {
  const bars = [];
  const rows = [];

  promotions.forEach((promo) => {
    const start = new Date(promo.startDate + 'T00:00:00');
    const end = promo.endDate ? new Date(promo.endDate + 'T23:59:59') : new Date(start.getTime() + 365 * 24 * 60 * 60 * 1000);
    if (end < weekStart || start > weekEnd) return;

    /* Strictly clip to month frame - bars must stay within month boundaries */
    const barStart = new Date(Math.max(start.getTime(), weekStart.getTime(), monthStart.getTime()));
    const barEnd = new Date(Math.min(end.getTime(), weekEnd.getTime(), monthEnd.getTime()));
    if (barStart > barEnd) return;

    const msPerDay = 24 * 60 * 60 * 1000;
    const colStart = Math.max(0, Math.floor((barStart - weekStart) / msPerDay));
    /* Use floor to ensure span never exceeds actual days (no overflow past month end) */
    const daySpan = Math.floor((barEnd - barStart) / msPerDay) + 1;
    const span = Math.max(1, Math.min(daySpan, 7 - colStart));

    let row = 0;
    while (rows[row] && rows[row].some((r) => r.colStart + r.colSpan > colStart && r.colStart < colStart + span)) {
      row++;
    }
    if (!rows[row]) rows[row] = [];

    rows[row].push({ colStart, colSpan: span });
    bars.push({
      promo,
      row,
      colStart: colStart + 1,
      colSpan: span,
      color: getPromotionColor(promo),
    });
  });

  return bars;
}

function promotionsInMonth(promotions, year, month) {
  const monthStart = new Date(year, month, 1);
  monthStart.setHours(0, 0, 0, 0);
  const monthEnd = new Date(year, month + 1, 0);
  monthEnd.setHours(23, 59, 59, 999);
  return promotions.filter((p) => overlapsDateRange(p, monthStart, monthEnd));
}

function MonthView({ promotions, currentDate, onPromotionClick }) {
  const year = currentDate.getFullYear();
  const month = currentDate.getMonth();
  const days = getDaysInMonth(year, month);
  const dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
  const promotionsThisMonth = promotionsInMonth(promotions, year, month);
  const monthStart = new Date(year, month, 1);
  monthStart.setHours(0, 0, 0, 0);
  const monthEnd = new Date(year, month + 1, 0);
  monthEnd.setHours(23, 59, 59, 999);

  const weekChunks = [];
  for (let i = 0; i < days.length; i += 7) {
    weekChunks.push(days.slice(i, i + 7));
  }

  return (
    <div className="promo-calendar-month">
      <div className="promo-calendar-grid-header">
        {dayNames.map((name, i) => (
          <div key={i} className="promo-calendar-header-cell">{name}</div>
        ))}
      </div>
      <div className="promo-calendar-grid-body">
        {weekChunks.map((week, wi) => {
          const weekStart = new Date(week[0]);
          weekStart.setHours(0, 0, 0, 0);
          const weekEnd = new Date(week[6]);
          weekEnd.setHours(23, 59, 59, 999);
          const bars = getBarsForWeek(promotionsThisMonth, weekStart, weekEnd, monthStart, monthEnd);
          return (
            <div key={wi} className="promo-calendar-week-row">
              <div className="promo-calendar-day-cells">
                {week.map((d) => (
                  <div
                    key={`${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`}
                    className={`promo-calendar-day-cell ${d.getMonth() !== month ? 'other-month' : ''} ${d.toDateString() === new Date().toDateString() ? 'today' : ''}`}
                  >
                    <span className="promo-calendar-day-num">{d.getDate()}</span>
                  </div>
                ))}
              </div>
              <div className="promo-calendar-month-bars">
                {bars.map((b, bi) => (
                  <div
                    key={bi}
                    className="promo-calendar-month-bar"
                    style={{
                      gridColumn: b.colStart,
                      gridColumnEnd: `span ${b.colSpan}`,
                      gridRow: b.row + 1,
                      backgroundColor: b.color,
                    }}
                    onClick={() => onPromotionClick(b.promo)}
                    title={b.promo.name}
                  >
                    {b.promo.name}
                  </div>
                ))}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function WeekView({ promotions, currentDate, onPromotionClick }) {
  const weekStart = getWeekStart(currentDate);
  weekStart.setHours(0, 0, 0, 0);
  const days = getWeekDays(weekStart);
  const viewEnd = new Date(days[6]);
  viewEnd.setHours(23, 59, 59, 999);

  const bars = getBarsForPromotions(promotions, weekStart, viewEnd);
  const dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];

  return (
    <div className="promo-calendar-week">
      <div className="promo-calendar-week-header">
        {days.map((d, i) => {
          const isToday = d.toDateString() === new Date().toDateString();
          return (
            <div key={i} className="promo-calendar-week-day-header">
              <div className="promo-calendar-week-day-name">{dayNames[i]}</div>
              <div className={`promo-calendar-week-day-date ${isToday ? 'today' : ''}`}>{d.getDate()}</div>
            </div>
          );
        })}
      </div>
      <div className="promo-calendar-week-body">
        {bars.map((b, bi) => (
          <div
            key={bi}
            className="promo-calendar-week-bar"
            style={{
              gridColumn: b.colStart + 1,
              gridColumnEnd: `span ${b.colSpan}`,
              gridRow: b.row + 1,
              backgroundColor: b.color,
            }}
            onClick={() => onPromotionClick(b.promo)}
            title={b.promo.name}
          >
            {b.promo.name}
          </div>
        ))}
      </div>
    </div>
  );
}

function toDateInputValue(d) {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`;
}

function ListView({ promotions, rangeStart, rangeEnd, onRangeChange }) {
  const filtered = promotions.filter((p) => overlapsDateRange(p, rangeStart, rangeEnd));
  const [expandedIds, setExpandedIds] = useState(() => new Set(filtered.map((p, i) => p.id || p.name || i)));

  const filteredKey = filtered.map((p, i) => p.id || p.name || i).join(',');
  React.useEffect(() => {
    setExpandedIds(new Set(filtered.map((p, i) => p.id || p.name || i)));
  }, [filteredKey]);

  const formatDate = (d) => d ? new Date(d).toLocaleDateString() : '-';
  const formatPrice = (val) => (!val || val === '0' || val === '') ? '-' : `$${parseFloat(val).toFixed(2)}`;

  const toggleExpand = (p, index) => {
    const id = p.id || p.name || index;
    setExpandedIds((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  return (
    <div className="promo-calendar-list">
      <div className="promo-calendar-list-filters card mb-3" style={{ borderRadius: 'var(--card-radius)' }}>
        <div className="card-body">
          <div className="row g-2 align-items-end">
            <div className="col-md-4">
              <label className="form-label small mb-0">Start Date</label>
              <input
                type="date"
                className="form-control form-control-sm"
                value={toDateInputValue(rangeStart)}
                onChange={(e) => onRangeChange(new Date(e.target.value + 'T00:00:00'))}
              />
            </div>
            <div className="col-md-4">
              <label className="form-label small mb-0">End Date</label>
              <input
                type="date"
                className="form-control form-control-sm"
                value={toDateInputValue(rangeEnd)}
                onChange={(e) => onRangeChange(null, new Date(e.target.value + 'T23:59:59'))}
              />
            </div>
            <div className="col-md-4">
              <span className="text-secondary small">{filtered.length} promotion(s)</span>
            </div>
          </div>
        </div>
      </div>
      <div className="promo-calendar-list-cards">
        {filtered.length === 0 ? (
          <div className="text-center py-5 text-muted">
            <i className="fas fa-inbox fa-3x mb-3"></i>
            <p>No promotions in this date range</p>
          </div>
        ) : (
          filtered.map((p, i) => {
            const id = p.id || p.name || i;
            const isExpanded = expandedIds.has(id);
            const products = p.products || [];
            return (
              <div
                key={id}
                className="card promo-calendar-list-card"
                style={{ borderRadius: 'var(--card-radius)' }}
              >
                <div
                  className="card-body promo-calendar-list-card-header"
                  onClick={() => toggleExpand(p, i)}
                  role="button"
                  tabIndex={0}
                  onKeyDown={(e) => e.key === 'Enter' && toggleExpand(p, i)}
                  aria-expanded={isExpanded}
                >
                  <div className="d-flex justify-content-between align-items-start">
                    <div>
                      <h6 className="mb-1">{p.name}</h6>
                      <span className="badge bg-primary me-2">{p.type || 'Standard'}</span>
                      <span className="text-secondary small">
                        {formatDate(p.startDate)} – {p.isOngoing ? 'Ongoing' : formatDate(p.endDate)}
                      </span>
                    </div>
                    <span className="badge bg-secondary">{products.length} products</span>
                    <i className={`fas fa-chevron-${isExpanded ? 'up' : 'down'} ms-2 text-secondary`} style={{ fontSize: '0.75rem' }}></i>
                  </div>
                </div>
                {isExpanded && (
                  <div className="promo-calendar-list-card-details">
                    {p.notes && (
                      <div className="promo-list-notes">
                        <i className="fas fa-sticky-note"></i>
                        <span>{p.notes}</span>
                      </div>
                    )}
                    <div className="promo-list-products">
                      <div className="promo-list-products-header">
                        <span>Products</span>
                        <span className="promo-list-products-count">{products.length} item{products.length !== 1 ? 's' : ''}</span>
                      </div>
                      {products.length === 0 ? (
                        <div className="promo-list-products-empty">
                          <i className="fas fa-box-open"></i>
                          <span>No products in this promotion</span>
                        </div>
                      ) : (
                        <div className="promo-list-products-table-wrap">
                          <table className="promo-list-products-table">
                            <thead>
                              <tr>
                                <th>Item Code</th>
                                <th>Description</th>
                                <th>RRP</th>
                                <th>Web Price</th>
                                <th>Rebate</th>
                              </tr>
                            </thead>
                            <tbody>
                              {products.map((prod, j) => (
                                <tr key={j}>
                                  <td>{prod.itemCode || 'N/A'}</td>
                                  <td>{prod.description || '—'}</td>
                                  <td>{formatPrice(prod.rrp)}</td>
                                  <td>{prod.webPrice ? `$${parseFloat(prod.webPrice).toFixed(2)}` : '—'}</td>
                                  <td>{prod.rebate && parseFloat(prod.rebate) > 0 ? `$${parseFloat(prod.rebate).toFixed(2)}` : '—'}</td>
                                </tr>
                              ))}
                            </tbody>
                          </table>
                        </div>
                      )}
                    </div>
                  </div>
                )}
              </div>
            );
          })
        )}
      </div>
    </div>
  );
}

function ItemListView({ items, rangeStart, rangeEnd, onRangeChange, onItemClick }) {
  const filtered = items.filter((entry) => overlapsDateRange(entry, rangeStart, rangeEnd));
  const formatDate = (d) => d ? new Date(d).toLocaleDateString() : '-';
  const formatPrice = (val) => (!val || val === '0' || val === '') ? '-' : `$${parseFloat(val).toFixed(2)}`;

  return (
    <div className="promo-calendar-list">
      <div className="promo-calendar-list-filters card mb-3" style={{ borderRadius: 'var(--card-radius)' }}>
        <div className="card-body">
          <div className="row g-2 align-items-end">
            <div className="col-md-4">
              <label className="form-label small mb-0">Start Date</label>
              <input
                type="date"
                className="form-control form-control-sm"
                value={toDateInputValue(rangeStart)}
                onChange={(e) => onRangeChange(new Date(e.target.value + 'T00:00:00'))}
              />
            </div>
            <div className="col-md-4">
              <label className="form-label small mb-0">End Date</label>
              <input
                type="date"
                className="form-control form-control-sm"
                value={toDateInputValue(rangeEnd)}
                onChange={(e) => onRangeChange(null, new Date(e.target.value + 'T23:59:59'))}
              />
            </div>
            <div className="col-md-4">
              <span className="text-secondary small">{filtered.length} item(s)</span>
            </div>
          </div>
        </div>
      </div>
      <div className="card" style={{ borderRadius: 'var(--card-radius)' }}>
        <div className="table-responsive">
          <table className="table table-hover table-sm mb-0">
            <thead>
              <tr>
                <th>Item</th>
                <th>Promotion</th>
                <th>Date Range</th>
                <th>RRP</th>
                <th>Web Price</th>
                <th>Rebate</th>
              </tr>
            </thead>
            <tbody>
              {filtered.length === 0 ? (
                <tr>
                  <td colSpan="6" className="text-center text-muted py-4">
                    <i className="fas fa-inbox me-2"></i>No items in this date range
                  </td>
                </tr>
              ) : (
                filtered.map((entry, idx) => (
                  <tr key={entry.id || idx} style={{ cursor: 'pointer' }} onClick={() => onItemClick(entry)}>
                    <td>
                      <div className="fw-semibold">{entry.name}</div>
                      <div className="text-secondary small">{entry.item?.description || '-'}</div>
                    </td>
                    <td>
                      <div className="fw-medium">{entry.promotion?.name || '-'}</div>
                      <div className="text-secondary small">{entry.promotion?.type || 'Standard'}</div>
                    </td>
                    <td className="small">{formatDate(entry.startDate)} - {formatDate(entry.endDate)}</td>
                    <td>{formatPrice(entry.item?.rrp)}</td>
                    <td>{entry.item?.webPrice ? `$${parseFloat(entry.item.webPrice).toFixed(2)}` : '-'}</td>
                    <td>{entry.item?.rebate && parseFloat(entry.item.rebate) > 0 ? `$${parseFloat(entry.item.rebate).toFixed(2)}` : '-'}</td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

function PromotionsCalendarApp() {
  const [promotions, setPromotions] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [accessChecked, setAccessChecked] = useState(false);
  const [hasAccess, setHasAccess] = useState(false);
  const [currentView, setCurrentView] = useState('month');
  const [displayMode, setDisplayMode] = useState('grouped');
  const [currentDate, setCurrentDate] = useState(() => new Date());
  const [weekStart, setWeekStart] = useState(() => getWeekStart(new Date()));
  const [listRangeStart, setListRangeStart] = useState(() => {
    const d = new Date();
    d.setDate(1);
    return d;
  });
  const [listRangeEnd, setListRangeEnd] = useState(() => {
    const d = new Date();
    d.setMonth(d.getMonth() + 1);
    d.setDate(0);
    return d;
  });
  const [selectedPromotion, setSelectedPromotion] = useState(null);
  const [selectedItem, setSelectedItem] = useState(null);
  const [searchQuery, setSearchQuery] = useState('');
  const allPromotionItems = React.useMemo(() => flattenPromotionItems(promotions), [promotions]);
  const activeEntries = displayMode === 'items' ? allPromotionItems : promotions;

  const filteredPromotions = React.useMemo(() => {
    if (!searchQuery.trim()) return activeEntries;
    const q = searchQuery.trim().toLowerCase();
    return activeEntries.filter((p) => {
      const nameMatch = (p.name || '').toLowerCase().includes(q);
      const typeMatch = (p.type || '').toLowerCase().includes(q);
      const notesMatch = (p.notes || '').toLowerCase().includes(q);
      const productMatch = displayMode === 'items'
        ? ((p.item?.itemCode || '').toLowerCase().includes(q)
          || (p.item?.description || '').toLowerCase().includes(q)
          || (p.promotion?.name || '').toLowerCase().includes(q))
        : (p.products || []).some(
          (prod) =>
            (prod.itemCode || '').toLowerCase().includes(q) ||
            (prod.description || '').toLowerCase().includes(q)
        );
      return nameMatch || typeMatch || notesMatch || productMatch;
    });
  }, [activeEntries, searchQuery, displayMode]);

  const loadPromotions = async () => {
    if (!window.db || !window.collection || !window.getDocs || !window.query || !window.orderBy) {
      setTimeout(loadPromotions, 100);
      return;
    }
    try {
      setLoading(true);
      setError(null);
      const q = window.query(
        window.collection(window.db, 'promotions'),
        window.orderBy('startDate', 'asc')
      );
      const snap = await window.getDocs(q);
      const list = snap.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
      setPromotions(list);
    } catch (err) {
      console.error('Error loading promotions:', err);
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    let mounted = true;
    const checkAccess = async () => {
      try {
        if (typeof window.ensureAuthIsInitialized === 'function') {
          await window.ensureAuthIsInitialized();
        }
        const isAdmin = typeof window.hasPermission === 'function' && window.hasPermission(null, 'IS_ADMIN');
        const isManager = typeof window.hasPermission === 'function' && window.hasPermission(null, 'IS_MANAGER');
        if (!mounted) return;
        setHasAccess(Boolean(isAdmin || isManager));
      } catch (err) {
        console.error('Error checking promotions calendar access:', err);
        if (!mounted) return;
        setHasAccess(false);
      } finally {
        if (mounted) setAccessChecked(true);
      }
    };
    checkAccess();
    return () => {
      mounted = false;
    };
  }, []);

  useEffect(() => {
    if (!accessChecked) return;
    if (accessChecked && hasAccess) {
      loadPromotions();
      return;
    }
    setLoading(false);
    setError(null);
  }, [accessChecked, hasAccess]);

  if (!accessChecked) {
    return (
      <div className="container py-5">
        <div className="text-center py-5">
          <div className="spinner-border text-primary" role="status"></div>
          <p className="mt-2 text-secondary">Checking access...</p>
        </div>
      </div>
    );
  }

  if (!hasAccess) {
    return (
      <div className="container py-5">
        <div className="alert alert-warning">
          <i className="fas fa-lock me-2"></i>
          Access restricted. Promotions Calendar is available to Admin and Manager users only.
        </div>
      </div>
    );
  }

  const goPrev = () => {
    if (currentView === 'month') {
      const d = new Date(currentDate);
      d.setMonth(d.getMonth() - 1);
      setCurrentDate(d);
    } else if (currentView === 'week') {
      const d = new Date(weekStart);
      d.setDate(d.getDate() - 7);
      setWeekStart(d);
    }
  };

  const goNext = () => {
    if (currentView === 'month') {
      const d = new Date(currentDate);
      d.setMonth(d.getMonth() + 1);
      setCurrentDate(d);
    } else if (currentView === 'week') {
      const d = new Date(weekStart);
      d.setDate(d.getDate() + 7);
      setWeekStart(d);
    }
  };

  const goToday = () => {
    const d = new Date();
    setCurrentDate(d);
    setWeekStart(getWeekStart(d));
  };

  const handleMiniCalendarDateSelect = (date) => {
    setCurrentDate(new Date(date));
    setWeekStart(getWeekStart(date));
  };

  const handleListRangeChange = (start, end) => {
    if (start) setListRangeStart(start);
    if (end) setListRangeEnd(end);
  };

  const formatNavTitle = () => {
    if (currentView === 'month') {
      return currentDate.toLocaleDateString('en-AU', { month: 'long', year: 'numeric' });
    }
    if (currentView === 'week') {
      const end = new Date(weekStart);
      end.setDate(end.getDate() + 6);
      return `${weekStart.toLocaleDateString('en-AU', { day: 'numeric', month: 'short' })} – ${end.toLocaleDateString('en-AU', { day: 'numeric', month: 'short', year: 'numeric' })}`;
    }
    return 'List';
  };

  if (loading) {
    return (
      <div className="container py-5">
        <div className="text-center py-5">
          <div className="spinner-border text-primary" role="status"></div>
          <p className="mt-2 text-secondary">Loading promotions...</p>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="container py-5">
        <div className="alert alert-danger">
          <i className="fas fa-exclamation-triangle me-2"></i>
          Error loading promotions: {error}
        </div>
      </div>
    );
  }

  return (
    <div className="container-fluid py-4 px-5 mx-auto" style={{ maxWidth: '100%', width: '100%' }}>
      <div className="mb-4">
        <h1 className="h2 mb-1 fw-bold">Promotions Calendar</h1>
        <p className="text-secondary mb-0" style={{ fontSize: '0.95rem' }}>
          View and manage your marketing promotions across months. Click a date in the mini calendar to jump to that date.
        </p>
      </div>

      <div className="promo-calendar-layout">
        <div className="promo-calendar-mini-wrapper">
          <MiniCalendar currentDate={currentDate} onDateSelect={handleMiniCalendarDateSelect} />
        </div>
        <div className="promo-calendar-main card mb-4" style={{ borderRadius: 'var(--card-radius)', flex: 1 }}>
          <div className="card-body p-5">
            <div className="d-flex flex-wrap align-items-center gap-3 mb-3">
            <div className="btn-group" role="group">
              {['month', 'week', 'list'].map((v) => (
                <button
                  key={v}
                  type="button"
                  className={`btn btn-sm ${currentView === v ? 'btn-primary' : 'btn-outline-secondary'}`}
                  onClick={() => setCurrentView(v)}
                >
                  {v.charAt(0).toUpperCase() + v.slice(1)}
                </button>
              ))}
            </div>
            <div
              className={`promo-display-toggle ${displayMode === 'items' ? 'items-active' : 'grouped-active'}`}
              role="group"
              aria-label="Calendar display mode"
            >
              <span className="promo-display-toggle-thumb" aria-hidden="true" />
              <button
                type="button"
                className={`promo-display-toggle-option ${displayMode === 'grouped' ? 'is-active' : ''}`}
                onClick={() => setDisplayMode('grouped')}
                aria-pressed={displayMode === 'grouped'}
                title="Show promotions grouped by campaign"
              >
                <i className="fas fa-layer-group promo-display-toggle-icon" aria-hidden="true" />
                <span>Grouped</span>
              </button>
              <button
                type="button"
                className={`promo-display-toggle-option ${displayMode === 'items' ? 'is-active' : ''}`}
                onClick={() => setDisplayMode('items')}
                aria-pressed={displayMode === 'items'}
                title="Show each product line item separately"
              >
                <i className="fas fa-list-ul promo-display-toggle-icon" aria-hidden="true" />
                <span>Items</span>
              </button>
            </div>
            {currentView !== 'list' && (
              <div className="d-flex align-items-center gap-2">
                <button className="btn btn-sm btn-outline-secondary" onClick={goPrev}>
                  <i className="fas fa-chevron-left"></i>
                </button>
                <span className="fw-semibold" style={{ minWidth: 200, textAlign: 'center' }}>
                  {formatNavTitle()}
                </span>
                <button className="btn btn-sm btn-outline-secondary" onClick={goNext}>
                  <i className="fas fa-chevron-right"></i>
                </button>
                <button className="btn btn-sm btn-outline-primary ms-2" onClick={goToday}>
                  Today
                </button>
              </div>
            )}
            <div className="promo-search-toolbar ms-auto position-relative">
                  <div className="input-group input-group-sm" style={{ width: 200 }}>
                    <span className="input-group-text bg-white border-end-0 py-1">
                      <i className="fas fa-search text-secondary" style={{ fontSize: '0.75rem' }}></i>
                    </span>
                    <input
                      type="text"
                      className="form-control border-start-0 py-1 promo-search-input"
                      placeholder={displayMode === 'items' ? 'Search items or promotions...' : 'Search promotions...'}
                      value={searchQuery}
                      onChange={(e) => setSearchQuery(e.target.value)}
                      aria-label={displayMode === 'items' ? 'Search items and promotions' : 'Search promotions'}
                    />
                  </div>
                  {searchQuery && (
                    <div className="promo-search-dropdown">
                      {filteredPromotions.length === 0 ? (
                        <div className="promo-search-dropdown-item text-muted py-2 px-3">
                          {displayMode === 'items' ? 'No items found' : 'No promotions found'}
                        </div>
                      ) : (
                        filteredPromotions.slice(0, 8).map((p) => (
                          <button
                            key={p.id || p.name}
                            type="button"
                            className="promo-search-dropdown-item d-flex flex-column align-items-start"
                            onClick={() => {
                              if (displayMode === 'items') {
                                setSelectedItem(p);
                              } else {
                                setSelectedPromotion(p);
                              }
                              setSearchQuery('');
                            }}
                          >
                            <span className="fw-medium text-start">
                              {displayMode === 'items'
                                ? formatPromotionItemLabel(p.item, p.name)
                                : p.name}
                            </span>
                            <span className="text-secondary small">
                              {displayMode === 'items'
                                ? `${p.promotion?.name || '-'} - ${p.startDate || '-'}`
                                : `${p.type || 'Standard'} - ${p.startDate || '-'}`
                              }
                            </span>
                          </button>
                        ))
                      )}
                      {filteredPromotions.length > 8 && (
                        <div className="promo-search-dropdown-item text-secondary small py-1 px-3">
                          +{filteredPromotions.length - 8} more - refine search
                        </div>
                      )}
                    </div>
                  )}
                </div>
          </div>

          {currentView === 'month' && (
            <MonthView
              promotions={filteredPromotions}
              currentDate={currentDate}
              onPromotionClick={displayMode === 'items' ? setSelectedItem : setSelectedPromotion}
            />
          )}
          {currentView === 'week' && (
            <WeekView
              promotions={filteredPromotions}
              currentDate={weekStart}
              onPromotionClick={displayMode === 'items' ? setSelectedItem : setSelectedPromotion}
            />
          )}
          {currentView === 'list' && (
            displayMode === 'items' ? (
              <ItemListView
                items={filteredPromotions}
                rangeStart={listRangeStart}
                rangeEnd={listRangeEnd}
                onRangeChange={handleListRangeChange}
                onItemClick={setSelectedItem}
              />
            ) : (
              <ListView
                promotions={filteredPromotions}
                rangeStart={listRangeStart}
                rangeEnd={listRangeEnd}
                onRangeChange={handleListRangeChange}
              />
            )
          )}
          </div>
        </div>
      </div>

      {selectedPromotion && (
        <PromotionDetailModal
          promotion={selectedPromotion}
          onClose={() => setSelectedPromotion(null)}
        />
      )}
      {selectedItem && (
        <ItemDetailModal
          itemEntry={selectedItem}
          onClose={() => setSelectedItem(null)}
        />
      )}
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('promotions-calendar-root'));
root.render(<PromotionsCalendarApp />);
