import { useState } from 'react';
import { useIntegrations, useOffice365CalendarRange } from '../crm/hooks';
import type { M365CalendarEvent } from '../crm/types';
import styles from './DashboardCalendarTab.module.css';

export type CalendarViewMode = 'month' | 'week' | 'agenda';

// ── Date Helpers ───────────────────────────────────────────────────────────────

function startOfWeekMonday(date: Date): Date {
  const d = new Date(date);
  const dow = (d.getDay() + 6) % 7; // Mon=0 … Sun=6
  d.setDate(d.getDate() - dow);
  d.setHours(0, 0, 0, 0);
  return d;
}

function addDays(date: Date, n: number): Date {
  const d = new Date(date);
  d.setDate(d.getDate() + n);
  return d;
}

function isSameDay(a: Date, b: Date): boolean {
  return (
    a.getFullYear() === b.getFullYear() &&
    a.getMonth() === b.getMonth() &&
    a.getDate() === b.getDate()
  );
}

/** 6×7 Tageszellen für die Monatsansicht */
function getMonthCells(date: Date): Date[] {
  const firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
  const gridStart = startOfWeekMonday(firstDay);
  return Array.from({ length: 42 }, (_, i) => addDays(gridStart, i));
}

/** 5 Arbeitstage der Woche (Mo–Fr) */
function getWorkWeekDays(date: Date): Date[] {
  const monday = startOfWeekMonday(date);
  return Array.from({ length: 5 }, (_, i) => addDays(monday, i));
}

function toISODate(date: Date): string {
  return date.toISOString().slice(0, 10);
}

function formatTime(iso: string): string {
  return new Date(iso).toLocaleTimeString('de-DE', {
    hour: '2-digit',
    minute: '2-digit',
  });
}

function getEventsForDay(events: M365CalendarEvent[], day: Date): M365CalendarEvent[] {
  return events
    .filter((e) => isSameDay(new Date(e.start.dateTime), day))
    .sort(
      (a, b) =>
        new Date(a.start.dateTime).getTime() - new Date(b.start.dateTime).getTime(),
    );
}

// Deterministische Farbe anhand Event-ID
const EVENT_COLORS = ['#3b82f6', '#8b5cf6', '#ec4899', '#f59e0b', '#10b981', '#ef4444'];
function eventColor(id: string): string {
  let h = 0;
  for (const ch of id) h = (h * 31 + ch.charCodeAt(0)) % EVENT_COLORS.length;
  return EVENT_COLORS[h];
}

// ── Day Agenda (Tages-Detailansicht, auch für Home) ───────────────────────────

export function DayAgenda({
  day,
  events,
}: {
  day: Date;
  events: M365CalendarEvent[];
}) {
  const dayEvents = getEventsForDay(events, day);

  return (
    <aside className={styles.agenda}>
      <div className={styles.agendaHeader}>
        <span className={styles.agendaWeekday}>
          {day.toLocaleDateString('de-DE', { weekday: 'long' })}
        </span>
        <span className={styles.agendaDateNum}>
          {day.toLocaleDateString('de-DE', { day: 'numeric', month: 'long' })}
        </span>
      </div>

      {dayEvents.length === 0 ? (
        <p className={styles.agendaEmpty}>Keine Termine</p>
      ) : (
        <div className={styles.agendaList}>
          {dayEvents.map((event) => (
            <a
              key={event.id}
              href={event.webLink}
              target="_blank"
              rel="noopener noreferrer"
              className={styles.agendaItem}
              style={{ borderLeftColor: eventColor(event.id) }}
            >
              <div className={styles.agendaTime}>
                {formatTime(event.start.dateTime)}
                {' – '}
                {formatTime(event.end.dateTime)}
                {event.isOnlineMeeting && (
                  <span className={styles.onlineBadge}>Online</span>
                )}
              </div>
              <div className={styles.agendaSubject}>{event.subject}</div>
              {event.location?.displayName && (
                <div className={styles.agendaMeta}>
                  📍 {event.location.displayName}
                </div>
              )}
              {event.attendees && event.attendees.length > 0 && (
                <div className={styles.agendaMeta}>
                  👥{' '}
                  {event.attendees
                    .slice(0, 2)
                    .map((a) => a.emailAddress.name || a.emailAddress.address)
                    .join(', ')}
                  {event.attendees.length > 2 && ` +${event.attendees.length - 2}`}
                </div>
              )}
            </a>
          ))}
        </div>
      )}
    </aside>
  );
}

// ── Agenda-Listenansicht (eigene Ansicht, zeigt mehrere Tage) ─────────────────

function AgendaView({
  currentDate,
  events,
  selectedDay,
  onDayClick,
}: {
  currentDate: Date;
  events: M365CalendarEvent[];
  selectedDay: Date;
  onDayClick: (d: Date) => void;
}) {
  const today = new Date();
  // 14 Tage ab currentDate
  const days = Array.from({ length: 14 }, (_, i) => addDays(currentDate, i));

  return (
    <div className={styles.agendaFullView}>
      {days.map((day) => {
        const dayEvents = getEventsForDay(events, day);
        const isToday = isSameDay(day, today);
        const isSelected = isSameDay(day, selectedDay);
        return (
          <div
            key={day.toISOString()}
            className={`${styles.agendaFullDay} ${isSelected ? styles.agendaFullDaySelected : ''}`}
            onClick={() => onDayClick(day)}
          >
            <div className={`${styles.agendaFullDayHdr} ${isToday ? styles.agendaFullDayHdrToday : ''}`}>
              <span className={styles.agendaFullWeekday}>
                {day.toLocaleDateString('de-DE', { weekday: 'short' })}
              </span>
              <span className={`${styles.agendaFullNum} ${isToday ? styles.agendaFullNumToday : ''}`}>
                {day.getDate()}
              </span>
              <span className={styles.agendaFullMonth}>
                {day.toLocaleDateString('de-DE', { month: 'short' })}
              </span>
            </div>
            <div className={styles.agendaFullEvents}>
              {dayEvents.length === 0 ? (
                <span className={styles.agendaFullEmpty}>Kein Termin</span>
              ) : (
                dayEvents.map((e) => (
                  <a
                    key={e.id}
                    href={e.webLink}
                    target="_blank"
                    rel="noopener noreferrer"
                    className={styles.agendaFullEvent}
                    style={{ borderLeftColor: eventColor(e.id) }}
                    onClick={(ev) => ev.stopPropagation()}
                  >
                    <span className={styles.agendaFullEventTime}>
                      {formatTime(e.start.dateTime)}
                    </span>
                    <span className={styles.agendaFullEventSubj}>{e.subject}</span>
                    {e.isOnlineMeeting && (
                      <span className={styles.onlineBadge}>Online</span>
                    )}
                  </a>
                ))
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ── Monatsansicht ─────────────────────────────────────────────────────────────

const WEEKDAY_LABELS = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];

function MonthView({
  currentDate,
  selectedDay,
  events,
  onDayClick,
}: {
  currentDate: Date;
  selectedDay: Date;
  events: M365CalendarEvent[];
  onDayClick: (d: Date) => void;
}) {
  const today = new Date();
  const cells = getMonthCells(currentDate);
  const month = currentDate.getMonth();

  return (
    <div className={styles.monthGrid}>
      {/* Wochentag-Header */}
      {WEEKDAY_LABELS.map((d) => (
        <div key={d} className={styles.monthWeekdayHdr}>
          {d}
        </div>
      ))}

      {/* Tageszellen */}
      {cells.map((day, i) => {
        const inMonth = day.getMonth() === month;
        const isToday = isSameDay(day, today);
        const isSelected = isSameDay(day, selectedDay);
        const dayEvents = getEventsForDay(events, day);

        return (
          <div
            key={i}
            className={[
              styles.dayCell,
              !inMonth ? styles.dayCellOther : '',
              isSelected ? styles.dayCellSelected : '',
            ]
              .filter(Boolean)
              .join(' ')}
            onClick={() => onDayClick(day)}
          >
            <span
              className={`${styles.dayNum} ${isToday ? styles.dayNumToday : ''}`}
            >
              {day.getDate()}
            </span>
            <div className={styles.dayCellEvents}>
              {dayEvents.slice(0, 2).map((e) => (
                <div
                  key={e.id}
                  className={styles.eventChip}
                  style={{ background: eventColor(e.id) }}
                  title={`${formatTime(e.start.dateTime)} ${e.subject}`}
                >
                  {formatTime(e.start.dateTime)} {e.subject}
                </div>
              ))}
              {dayEvents.length > 2 && (
                <div className={styles.eventMore}>+{dayEvents.length - 2}</div>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ── Wochenansicht (Mo–Fr) ─────────────────────────────────────────────────────

function WeekView({
  currentDate,
  selectedDay,
  events,
  onDayClick,
}: {
  currentDate: Date;
  selectedDay: Date;
  events: M365CalendarEvent[];
  onDayClick: (d: Date) => void;
}) {
  const today = new Date();
  const weekDays = getWorkWeekDays(currentDate); // nur Mo–Fr

  return (
    <div className={styles.weekGrid}>
      {weekDays.map((day) => {
        const isToday = isSameDay(day, today);
        const isSelected = isSameDay(day, selectedDay);
        const dayEvents = getEventsForDay(events, day);

        return (
          <div
            key={day.toISOString()}
            className={`${styles.weekCol} ${isSelected ? styles.weekColSelected : ''}`}
            onClick={() => onDayClick(day)}
          >
            <div
              className={`${styles.weekColHdr} ${isToday ? styles.weekColHdrToday : ''}`}
            >
              <span className={styles.weekColDay}>
                {day.toLocaleDateString('de-DE', { weekday: 'short' })}
              </span>
              <span
                className={`${styles.weekColNum} ${isToday ? styles.weekColNumToday : ''}`}
              >
                {day.getDate()}
              </span>
            </div>
            <div className={styles.weekColEvents}>
              {dayEvents.map((e) => (
                <div
                  key={e.id}
                  className={styles.weekEvent}
                  style={{ borderLeftColor: eventColor(e.id) }}
                  title={e.subject}
                  onClick={(ev) => {
                    ev.stopPropagation();
                    window.open(e.webLink, '_blank', 'noopener,noreferrer');
                  }}
                >
                  <span className={styles.weekEventTime}>
                    {formatTime(e.start.dateTime)}
                  </span>
                  <span className={styles.weekEventSubj}>{e.subject}</span>
                </div>
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ── DashboardCalendarTab ──────────────────────────────────────────────────────

export function DashboardCalendarTab() {
  const { data: integrationsData, isLoading: intLoading } = useIntegrations();
  const isConnected =
    integrationsData?.data?.some(
      (i) => i.provider === 'MICROSOFT_365' && i.connected,
    ) ?? false;

  const [viewMode, setViewMode] = useState<CalendarViewMode>('month');
  const [currentDate, setCurrentDate] = useState(() => new Date());
  const [selectedDay, setSelectedDay] = useState(() => new Date());

  // Datumsbereich berechnen
  const rangeStart =
    viewMode === 'month'
      ? startOfWeekMonday(
          new Date(currentDate.getFullYear(), currentDate.getMonth(), 1),
        )
      : viewMode === 'week'
      ? startOfWeekMonday(currentDate)
      : currentDate; // agenda: ab currentDate

  const rangeEnd =
    viewMode === 'month'
      ? addDays(rangeStart, 42)
      : viewMode === 'week'
      ? addDays(startOfWeekMonday(currentDate), 5) // Mo–Fr
      : addDays(currentDate, 14); // 14 Tage Agenda

  const { data: eventsData, isLoading, error } = useOffice365CalendarRange(
    toISODate(rangeStart),
    toISODate(rangeEnd),
  );
  const events: M365CalendarEvent[] = eventsData?.data ?? [];

  const navigate = (delta: number) => {
    const d = new Date(currentDate);
    if (viewMode === 'month') {
      d.setMonth(d.getMonth() + delta);
    } else if (viewMode === 'week') {
      d.setDate(d.getDate() + delta * 7);
    } else {
      d.setDate(d.getDate() + delta * 14);
    }
    setCurrentDate(d);
  };

  const goToday = () => {
    const t = new Date();
    setCurrentDate(t);
    setSelectedDay(t);
  };

  // Anzeigebezeichnung
  const rangeLabel = (() => {
    if (viewMode === 'month') {
      return currentDate.toLocaleDateString('de-DE', { month: 'long', year: 'numeric' });
    }
    if (viewMode === 'week') {
      const days = getWorkWeekDays(currentDate);
      const f = days[0];
      const l = days[4];
      const sm = f.getMonth() === l.getMonth();
      return sm
        ? `${f.getDate()}. – ${l.getDate()}. ${l.toLocaleDateString('de-DE', { month: 'long', year: 'numeric' })}`
        : `${f.getDate()}. ${f.toLocaleDateString('de-DE', { month: 'short' })} – ${l.getDate()}. ${l.toLocaleDateString('de-DE', { month: 'short', year: 'numeric' })}`;
    }
    // agenda
    const end = addDays(currentDate, 13);
    const sm = currentDate.getMonth() === end.getMonth();
    return sm
      ? `${currentDate.getDate()}. – ${end.getDate()}. ${end.toLocaleDateString('de-DE', { month: 'long', year: 'numeric' })}`
      : `${currentDate.getDate()}. ${currentDate.toLocaleDateString('de-DE', { month: 'short' })} – ${end.getDate()}. ${end.toLocaleDateString('de-DE', { month: 'short', year: 'numeric' })}`;
  })();

  if (intLoading) {
    return <p className={styles.status}>Verbindung wird geprüft…</p>;
  }

  if (!isConnected) {
    return (
      <div className={styles.notConnected}>
        <span className={styles.notConnectedIcon}>📅</span>
        <p className={styles.notConnectedTitle}>Microsoft 365 nicht verbunden</p>
        <p className={styles.notConnectedSub}>
          Verbinden Sie Ihr Konto unter{' '}
          <a href="/crm/office365" className={styles.notConnectedLink}>
            CRM → Office 365
          </a>
          .
        </p>
      </div>
    );
  }

  return (
    <div className={styles.root}>
      {/* Toolbar */}
      <div className={styles.toolbar}>
        <div className={styles.navGroup}>
          <button
            type="button"
            className={styles.navBtn}
            onClick={() => navigate(-1)}
            aria-label="Zurück"
          >
            ‹
          </button>
          <button type="button" className={styles.todayBtn} onClick={goToday}>
            Heute
          </button>
          <button
            type="button"
            className={styles.navBtn}
            onClick={() => navigate(1)}
            aria-label="Vor"
          >
            ›
          </button>
        </div>

        <h2 className={styles.rangeLabel}>{rangeLabel}</h2>

        <div className={styles.viewToggle}>
          <button
            type="button"
            className={`${styles.viewBtn} ${viewMode === 'month' ? styles.viewBtnActive : ''}`}
            onClick={() => setViewMode('month')}
          >
            Monat
          </button>
          <button
            type="button"
            className={`${styles.viewBtn} ${viewMode === 'week' ? styles.viewBtnActive : ''}`}
            onClick={() => setViewMode('week')}
          >
            Woche
          </button>
          <button
            type="button"
            className={`${styles.viewBtn} ${viewMode === 'agenda' ? styles.viewBtnActive : ''}`}
            onClick={() => setViewMode('agenda')}
          >
            Agenda
          </button>
        </div>
      </div>

      {/* Status */}
      {isLoading && (
        <p className={styles.status}>Termine werden geladen…</p>
      )}
      {error && (
        <p className={styles.errorText}>
          Kalendertermine konnten nicht geladen werden.
        </p>
      )}

      {/* Hauptbereich */}
      {!isLoading && (
        <div className={styles.content}>
          <div className={styles.calendarPanel}>
            {viewMode === 'month' && (
              <MonthView
                currentDate={currentDate}
                selectedDay={selectedDay}
                events={events}
                onDayClick={setSelectedDay}
              />
            )}
            {viewMode === 'week' && (
              <WeekView
                currentDate={currentDate}
                selectedDay={selectedDay}
                events={events}
                onDayClick={setSelectedDay}
              />
            )}
            {viewMode === 'agenda' && (
              <AgendaView
                currentDate={currentDate}
                events={events}
                selectedDay={selectedDay}
                onDayClick={setSelectedDay}
              />
            )}
          </div>

          {/* Tages-Agenda nur bei Monat- und Wochenansicht */}
          {(viewMode === 'month' || viewMode === 'week') && (
            <DayAgenda day={selectedDay} events={events} />
          )}
        </div>
      )}
    </div>
  );
}
