/**
 * Events Calendar - React App
 * Month, Week, and List views with event bars. Similar to promotions calendar.
 * Basecamp UI aligned.
 */
const { useState, useEffect } = React;

const PAST_EVENT_GREY = '#D0D0D0';
const EVENT_TYPE_COLORS = {
  meeting: '#3b82f6',
  training: '#8b5cf6',
  social: '#ec4899',
  deadline: '#ef4444',
  holiday: '#10b981',
  bbq: '#f59e0b',
  'team-event': '#06b6d4',
  maintenance: '#6b7280',
  other: '#64748b'
};

function normalizeEvent(event) {
  const startDate = event.startDate?.toDate ? event.startDate.toDate() : (event.startDate?.seconds ? new Date(event.startDate.seconds * 1000) : new Date(event.startDate));
  const endDate = event.endDate?.toDate ? event.endDate.toDate() : (event.endDate?.seconds ? new Date(event.endDate.seconds * 1000) : null);
  return {
    ...event,
    _startDateStr: startDate.toISOString().split('T')[0],
    _endDateStr: endDate ? endDate.toISOString().split('T')[0] : startDate.toISOString().split('T')[0],
    _startDateObj: startDate,
    _endDateObj: endDate || startDate
  };
}

function isEventPast(evt) {
  const end = evt._endDateStr ? new Date(evt._endDateStr + 'T23:59:59') : null;
  if (!end) return false;
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  return end < today;
}

function getEventColor(evt) {
  if (isEventPast(evt)) return PAST_EVENT_GREY;
  const type = (evt.type || 'other').toLowerCase().replace(/\s+/g, '-');
  return EVENT_TYPE_COLORS[type] || EVENT_TYPE_COLORS.other;
}

function overlapsDateRange(evt, rangeStart, rangeEnd) {
  const start = new Date(evt._startDateStr + 'T00:00:00');
  const end = evt._endDateStr ? new Date(evt._endDateStr + 'T23:59:59') : new Date(evt._startDateStr + 'T23:59:59');
  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 formatEventTime(time24) {
  if (!time24) return '';
  const [hours, minutes] = time24.split(':');
  const hour = parseInt(hours);
  const ampm = hour >= 12 ? 'PM' : 'AM';
  const hour12 = hour === 0 ? 12 : (hour > 12 ? hour - 12 : hour);
  return `${hour12}:${minutes} ${ampm}`;
}

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 = () => onDateSelect(new Date(year, month - 1, 1));
  const goNextMonth = () => onDateSelect(new Date(year, month + 1, 1));

  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 getBarsForEvents(events, viewStart, viewEnd) {
  const bars = [];
  const rows = [];

  events.forEach((evt) => {
    const start = new Date(evt._startDateStr + 'T00:00:00');
    const end = evt._endDateStr ? new Date(evt._endDateStr + 'T23:59:59') : new Date(evt._startDateStr + 'T23:59:59');
    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 });

    bars.push({
      evt,
      row,
      colStart,
      colSpan,
      color: getEventColor(evt)
    });
  });

  return bars;
}

function EventDetailModal({ event, stores, departments, onClose }) {
  if (!event) return null;

  const startDate = event._startDateObj ? event._startDateObj.toLocaleDateString() : '-';
  const endDate = event._endDateStr && event._endDateStr !== event._startDateStr
    ? (event._endDateObj ? event._endDateObj.toLocaleDateString() : event._endDateStr)
    : null;
  const timeStr = event.startTime ? formatEventTime(event.startTime) : '';
  const endTimeStr = event.endTime ? formatEventTime(event.endTime) : '';

  const locationNames = event.locations && event.locations.length > 0
    ? event.locations.includes('all')
      ? 'All Locations'
      : event.locations.map(id => {
          const store = (stores || []).find(s => s.id === id);
          return store ? (store.name || id) : id;
        }).join(', ')
    : 'No location specified';

  const departmentNames = event.departments && event.departments.length > 0
    ? event.departments.includes('all')
      ? 'All Departments'
      : event.departments.map(id => {
          const dept = (departments || []).find(d => d.id === id);
          return dept ? dept.name : id;
        }).join(', ')
    : 'No departments specified';

  const typeLabel = event.type === 'other' && event.customType ? event.customType : (event.type || 'Event').replace(/-/g, ' ');

  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">{event.title}</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 me-2"
                style={{ backgroundColor: getEventColor(event) + '40', color: getEventColor(event) }}
              >
                {typeLabel}
              </span>
              <span className="text-secondary">
                <i className="fas fa-calendar-alt me-1"></i>
                {startDate}
                {endDate && endDate !== startDate ? ` – ${endDate}` : ''}
              </span>
            </div>
            {(timeStr || endTimeStr) && (
              <div className="mb-2 text-secondary">
                <i className="fas fa-clock me-1"></i>
                {timeStr}{endTimeStr ? ` – ${endTimeStr}` : ''}
              </div>
            )}
            {event.locationDetails && (
              <div className="mb-2 text-secondary">
                <i className="fas fa-map-marker-alt me-1"></i>{event.locationDetails}
              </div>
            )}
            <div className="mb-2">
              <span className="badge bg-secondary me-1">{locationNames}</span>
              <span className="badge bg-info">{departmentNames}</span>
            </div>
            {event.description && (
              <div className="mt-3 text-secondary small">
                <p className="mb-0">{event.description}</p>
              </div>
            )}
          </div>
          <div className="modal-footer">
            <button type="button" className="btn btn-secondary" onClick={onClose}>Close</button>
            {typeof window !== 'undefined' && window.location.href.includes('events-calendar') && (
              <a href="events.html" className="btn btn-primary">Back to Events</a>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

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

  events.forEach((evt) => {
    const start = new Date(evt._startDateStr + 'T00:00:00');
    const end = evt._endDateStr ? new Date(evt._endDateStr + 'T23:59:59') : new Date(evt._startDateStr + 'T23:59:59');
    if (end < weekStart || start > weekEnd) return;

    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));
    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({
      evt,
      row,
      colStart: colStart + 1,
      colSpan: span,
      color: getEventColor(evt)
    });
  });

  return bars;
}

function eventsInMonth(events, 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 events.filter((e) => overlapsDateRange(e, monthStart, monthEnd));
}

function MonthView({ events, currentDate, onEventClick }) {
  const year = currentDate.getFullYear();
  const month = currentDate.getMonth();
  const days = getDaysInMonth(year, month);
  const dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
  const eventsThisMonth = eventsInMonth(events, 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(eventsThisMonth, 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={() => onEventClick(b.evt)}
                    title={b.evt.title}
                  >
                    {b.evt.title}
                  </div>
                ))}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function WeekView({ events, currentDate, onEventClick }) {
  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 = getBarsForEvents(events, 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={() => onEventClick(b.evt)}
            title={b.evt.title}
          >
            {b.evt.title}
          </div>
        ))}
      </div>
    </div>
  );
}

function EventsCalendarApp() {
  const [events, setEvents] = useState([]);
  const [stores, setStores] = useState([]);
  const [departments, setDepartments] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [currentView, setCurrentView] = useState('month');
  const [currentDate, setCurrentDate] = useState(() => new Date());
  const [weekStart, setWeekStart] = useState(() => getWeekStart(new Date()));
  const [selectedEvent, setSelectedEvent] = useState(null);
  const [searchQuery, setSearchQuery] = useState('');

  const normalizedEvents = React.useMemo(() =>
    events.map(normalizeEvent),
    [events]
  );

  const filteredEvents = React.useMemo(() => {
    if (!searchQuery.trim()) return normalizedEvents;
    const q = searchQuery.trim().toLowerCase();
    return normalizedEvents.filter((e) => {
      const titleMatch = (e.title || '').toLowerCase().includes(q);
      const typeMatch = (e.type || '').toLowerCase().includes(q) || (e.customType || '').toLowerCase().includes(q);
      const descMatch = (e.description || '').toLowerCase().includes(q);
      return titleMatch || typeMatch || descMatch;
    });
  }, [normalizedEvents, searchQuery]);

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

  const loadStoresAndDepartments = async () => {
    if (!window.db || !window.collection || !window.getDocs) return;
    try {
      const [storesSnap, deptsSnap] = await Promise.all([
        window.getDocs(window.collection(window.db, 'stores')),
        window.getDocs(window.collection(window.db, 'departments'))
      ]);
      setStores(storesSnap.docs.map((d) => ({ id: d.id, ...d.data() })));
      setDepartments(deptsSnap.docs.map((d) => ({ id: d.id, ...d.data() })));
    } catch (err) {
      console.warn('Could not load stores/departments:', err);
    }
  };

  useEffect(() => {
    loadEvents();
    loadStoresAndDepartments();
  }, []);

  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 formatNavTitle = () => {
    if (currentView === 'month') {
      return currentDate.toLocaleDateString('en-AU', { month: 'long', year: 'numeric' });
    }
    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' })}`;
  };

  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 events...</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 events: {error}
        </div>
      </div>
    );
  }

  const isStandalone = typeof window !== 'undefined' && window.location.href.includes('events-calendar');

  return (
    <div className="container-fluid py-4 px-5 mx-auto" style={{ maxWidth: '100%', width: '100%' }}>
      {isStandalone && (
        <div className="mb-4">
          <h1 className="h2 mb-1 fw-bold">Events Calendar</h1>
          <p className="text-secondary mb-0" style={{ fontSize: '0.95rem' }}>
            View company events across months.
          </p>
          <a href="events.html" className="btn btn-outline-secondary btn-sm mt-2">
            <i className="fas fa-arrow-left me-2"></i>Back to Events
          </a>
        </div>
      )}

      <div className="promo-calendar-layout">
        <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'].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="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="Search events..."
                    value={searchQuery}
                    onChange={(e) => setSearchQuery(e.target.value)}
                    aria-label="Search events"
                  />
                </div>
                {searchQuery && (
                  <div className="promo-search-dropdown">
                    {filteredEvents.length === 0 ? (
                      <div className="promo-search-dropdown-item text-muted py-2 px-3">
                        No events found
                      </div>
                    ) : (
                      filteredEvents.slice(0, 8).map((e) => (
                        <button
                          key={e.id || e.title}
                          type="button"
                          className="promo-search-dropdown-item d-flex flex-column align-items-start"
                          onClick={() => {
                            setSelectedEvent(e);
                            setSearchQuery('');
                          }}
                        >
                          <span className="fw-medium text-start">{e.title}</span>
                          <span className="text-secondary small">
                            {e.type || 'Event'} · {e._startDateStr}
                          </span>
                        </button>
                      ))
                    )}
                    {filteredEvents.length > 8 && (
                      <div className="promo-search-dropdown-item text-secondary small py-1 px-3">
                        +{filteredEvents.length - 8} more — refine search
                      </div>
                    )}
                  </div>
                )}
              </div>
            </div>

            {currentView === 'month' && (
              <MonthView
                events={filteredEvents}
                currentDate={currentDate}
                onEventClick={setSelectedEvent}
              />
            )}
            {currentView === 'week' && (
              <WeekView
                events={filteredEvents}
                currentDate={weekStart}
                onEventClick={setSelectedEvent}
              />
            )}
          </div>
        </div>
      </div>

      {selectedEvent && (
        <EventDetailModal
          event={selectedEvent}
          stores={stores}
          departments={departments}
          onClose={() => setSelectedEvent(null)}
        />
      )}
    </div>
  );
}

const calendarRoot = document.getElementById('events-calendar-root');
if (calendarRoot) {
  const root = ReactDOM.createRoot(calendarRoot);
  root.render(<EventsCalendarApp />);
}
