import { useState, useMemo, useCallback } from 'react';
import {
  Box,
  Typography,
  IconButton,
  ButtonGroup,
  Button,
  Popover,
  List,
  ListItem,
  ListItemText,
  Chip,
  Tooltip,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogContentText,
  DialogActions,
  Snackbar,
  Alert,
  Skeleton,
  Divider,
  useTheme,
  useMediaQuery,
} from '@mui/material';
import {
  ChevronLeft,
  ChevronRight,
  Today as TodayIcon,
  CalendarViewMonth as CalendarIcon,
  ViewList as ListViewIcon,
  Star as StarIcon,
  ContentCopy as CopyIcon,
  CheckCircle as CheckIcon,
  Cancel as CancelIcon,
  HelpOutline as UnknownIcon,
} from '@mui/icons-material';
import { useNavigate } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import DashboardLayout from '../components/dashboard/DashboardLayout';
import { trainingApi } from '../services/training';
import type { UebungListItem, UebungTyp, TeilnahmeStatus } from '../types/training.types';

// ---------------------------------------------------------------------------
// Constants & helpers
// ---------------------------------------------------------------------------

const WEEKDAY_LABELS = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
const MONTH_LABELS = [
  'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
  'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember',
];

const TYP_DOT_COLOR: Record<UebungTyp, string> = {
  'Übungsabend':      '#1976d2', // blue
  'Lehrgang':         '#7b1fa2', // purple
  'Sonderdienst':     '#e65100', // orange
  'Versammlung':      '#616161', // gray
  'Gemeinschaftsübung': '#00796b', // teal
  'Sonstiges':        '#9e9e9e', // light gray
};

const TYP_CHIP_COLOR: Record<
  UebungTyp,
  'primary' | 'secondary' | 'warning' | 'default' | 'error' | 'info' | 'success'
> = {
  'Übungsabend':      'primary',
  'Lehrgang':         'secondary',
  'Sonderdienst':     'warning',
  'Versammlung':      'default',
  'Gemeinschaftsübung': 'info',
  'Sonstiges':        'default',
};

function startOfDay(d: Date): Date {
  const c = new Date(d);
  c.setHours(0, 0, 0, 0);
  return c;
}

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

/** Returns calendar grid cells for the month view — always 6×7 (42 cells) */
function buildMonthGrid(year: number, month: number): Date[] {
  // month is 0-indexed
  const firstDay = new Date(year, month, 1);
  // ISO week starts Monday; getDay() returns 0=Sun → convert to Mon=0
  const dayOfWeek = (firstDay.getDay() + 6) % 7;
  const start = new Date(firstDay);
  start.setDate(start.getDate() - dayOfWeek);

  const cells: Date[] = [];
  for (let i = 0; i < 42; i++) {
    const d = new Date(start);
    d.setDate(start.getDate() + i);
    cells.push(d);
  }
  return cells;
}

function formatTime(isoString: string): string {
  const d = new Date(isoString);
  const h = String(d.getHours()).padStart(2, '0');
  const m = String(d.getMinutes()).padStart(2, '0');
  return `${h}:${m}`;
}

function formatDateLong(isoString: string): string {
  const d = new Date(isoString);
  const days = ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'];
  return `${days[d.getDay()]}, ${d.getDate()}. ${MONTH_LABELS[d.getMonth()]} ${d.getFullYear()}`;
}

// ---------------------------------------------------------------------------
// RSVP indicator
// ---------------------------------------------------------------------------

function RsvpDot({ status }: { status: TeilnahmeStatus | undefined }) {
  if (!status || status === 'unbekannt') return <UnknownIcon sx={{ fontSize: 14, color: 'text.disabled' }} />;
  if (status === 'zugesagt' || status === 'erschienen') return <CheckIcon sx={{ fontSize: 14, color: 'success.main' }} />;
  return <CancelIcon sx={{ fontSize: 14, color: 'error.main' }} />;
}

// ---------------------------------------------------------------------------
// iCal Subscribe Dialog
// ---------------------------------------------------------------------------

interface IcalDialogProps {
  open: boolean;
  onClose: () => void;
}

function IcalDialog({ open, onClose }: IcalDialogProps) {
  const [snackOpen, setSnackOpen] = useState(false);
  const [subscribeUrl, setSubscribeUrl] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  const handleOpen = async () => {
    if (subscribeUrl) return;
    setLoading(true);
    try {
      const { subscribeUrl: url } = await trainingApi.getCalendarToken();
      setSubscribeUrl(url);
    } catch (_) {
      setSubscribeUrl(null);
    } finally {
      setLoading(false);
    }
  };

  const handleCopy = async () => {
    if (!subscribeUrl) return;
    await navigator.clipboard.writeText(subscribeUrl);
    setSnackOpen(true);
  };

  return (
    <>
      <Dialog
        open={open}
        onClose={onClose}
        TransitionProps={{ onEnter: handleOpen }}
        maxWidth="sm"
        fullWidth
      >
        <DialogTitle>Kalender abonnieren</DialogTitle>
        <DialogContent>
          <DialogContentText sx={{ mb: 2 }}>
            Kopiere die URL und füge sie in deiner Kalender-App unter
            "Kalender abonnieren" ein. Der Kalender wird automatisch
            aktualisiert, sobald neue Dienste eingetragen werden.
          </DialogContentText>

          {loading && <Skeleton variant="rectangular" height={48} sx={{ borderRadius: 1 }} />}

          {!loading && subscribeUrl && (
            <Box
              sx={{
                display: 'flex',
                alignItems: 'center',
                gap: 1,
                p: 1.5,
                borderRadius: 1,
                bgcolor: 'action.hover',
                fontFamily: 'monospace',
                fontSize: '0.75rem',
                wordBreak: 'break-all',
              }}
            >
              <Box sx={{ flexGrow: 1, userSelect: 'all' }}>{subscribeUrl}</Box>
              <Tooltip title="URL kopieren">
                <IconButton size="small" onClick={handleCopy}>
                  <CopyIcon fontSize="small" />
                </IconButton>
              </Tooltip>
            </Box>
          )}

          <Typography variant="body2" color="text.secondary" sx={{ mt: 2 }}>
            <strong>Apple Kalender:</strong> Ablage → Neues Kalenderabonnement<br />
            <strong>Google Kalender:</strong> Andere Kalender → Per URL<br />
            <strong>Thunderbird:</strong> Neu → Kalender → Im Netzwerk
          </Typography>
        </DialogContent>
        <DialogActions>
          <Button onClick={onClose}>Schließen</Button>
          {subscribeUrl && (
            <Button variant="contained" onClick={handleCopy} startIcon={<CopyIcon />}>
              URL kopieren
            </Button>
          )}
        </DialogActions>
      </Dialog>

      <Snackbar
        open={snackOpen}
        autoHideDuration={3000}
        onClose={() => setSnackOpen(false)}
        anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
      >
        <Alert severity="success" onClose={() => setSnackOpen(false)}>
          URL kopiert!
        </Alert>
      </Snackbar>
    </>
  );
}

// ---------------------------------------------------------------------------
// Month Calendar Grid
// ---------------------------------------------------------------------------

interface MonthCalendarProps {
  year: number;
  month: number;
  events: UebungListItem[];
  onDayClick: (day: Date, anchor: Element) => void;
}

function MonthCalendar({ year, month, events, onDayClick }: MonthCalendarProps) {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
  const today = startOfDay(new Date());
  const cells = useMemo(() => buildMonthGrid(year, month), [year, month]);

  // Build a map: "YYYY-MM-DD" → events
  const eventsByDay = useMemo(() => {
    const map = new Map<string, UebungListItem[]>();
    for (const ev of events) {
      const d = startOfDay(new Date(ev.datum_von));
      const key = d.toISOString().slice(0, 10);
      const arr = map.get(key) ?? [];
      arr.push(ev);
      map.set(key, arr);
    }
    return map;
  }, [events]);

  return (
    <Box>
      {/* Weekday headers */}
      <Box
        sx={{
          display: 'grid',
          gridTemplateColumns: 'repeat(7, 1fr)',
          mb: 0.5,
        }}
      >
        {WEEKDAY_LABELS.map((wd) => (
          <Typography
            key={wd}
            variant="caption"
            sx={{
              textAlign: 'center',
              fontWeight: 600,
              color: wd === 'Sa' || wd === 'So' ? 'error.main' : 'text.secondary',
              py: 0.5,
            }}
          >
            {wd}
          </Typography>
        ))}
      </Box>

      {/* Day cells — 6 rows × 7 cols */}
      <Box
        sx={{
          display: 'grid',
          gridTemplateColumns: 'repeat(7, 1fr)',
          gap: '2px',
        }}
      >
        {cells.map((cell, idx) => {
          const isCurrentMonth = cell.getMonth() === month;
          const isToday = sameDay(cell, today);
          const key = cell.toISOString().slice(0, 10);
          const dayEvents = eventsByDay.get(key) ?? [];
          const hasEvents = dayEvents.length > 0;

          return (
            <Box
              key={idx}
              onClick={(e) => hasEvents && onDayClick(cell, e.currentTarget)}
              sx={{
                minHeight: isMobile ? 44 : 72,
                borderRadius: 1,
                p: '4px',
                cursor: hasEvents ? 'pointer' : 'default',
                bgcolor: isToday
                  ? 'primary.main'
                  : isCurrentMonth
                    ? 'background.paper'
                    : 'action.disabledBackground',
                border: '1px solid',
                borderColor: isToday ? 'primary.dark' : 'divider',
                transition: 'background 0.1s',
                '&:hover': hasEvents
                  ? { bgcolor: isToday ? 'primary.dark' : 'action.hover' }
                  : {},
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                overflow: 'hidden',
              }}
            >
              <Typography
                variant="caption"
                sx={{
                  fontWeight: isToday ? 700 : 400,
                  color: isToday
                    ? 'primary.contrastText'
                    : isCurrentMonth
                      ? 'text.primary'
                      : 'text.disabled',
                  lineHeight: 1.4,
                  fontSize: isMobile ? '0.7rem' : '0.75rem',
                }}
              >
                {cell.getDate()}
              </Typography>

              {/* Event dots — max 3 visible on mobile */}
              {hasEvents && (
                <Box
                  sx={{
                    display: 'flex',
                    flexWrap: 'wrap',
                    gap: '2px',
                    justifyContent: 'center',
                    mt: 0.25,
                  }}
                >
                  {dayEvents.slice(0, isMobile ? 3 : 5).map((ev, i) => (
                    <Box
                      key={i}
                      sx={{
                        width: isMobile ? 5 : 7,
                        height: isMobile ? 5 : 7,
                        borderRadius: '50%',
                        bgcolor: ev.abgesagt
                          ? 'text.disabled'
                          : TYP_DOT_COLOR[ev.typ],
                        border: ev.pflichtveranstaltung
                          ? '1.5px solid'
                          : 'none',
                        borderColor: 'warning.main',
                        flexShrink: 0,
                      }}
                    />
                  ))}
                  {dayEvents.length > (isMobile ? 3 : 5) && (
                    <Typography
                      sx={{
                        fontSize: '0.55rem',
                        color: isToday ? 'primary.contrastText' : 'text.secondary',
                        lineHeight: 1,
                      }}
                    >
                      +{dayEvents.length - (isMobile ? 3 : 5)}
                    </Typography>
                  )}
                </Box>
              )}

              {/* On desktop: show short event titles */}
              {!isMobile && hasEvents && (
                <Box sx={{ width: '100%', mt: 0.25 }}>
                  {dayEvents.slice(0, 2).map((ev, i) => (
                    <Typography
                      key={i}
                      variant="caption"
                      noWrap
                      sx={{
                        display: 'block',
                        fontSize: '0.6rem',
                        lineHeight: 1.3,
                        color: ev.abgesagt ? 'text.disabled' : TYP_DOT_COLOR[ev.typ],
                        textDecoration: ev.abgesagt ? 'line-through' : 'none',
                        px: 0.25,
                      }}
                    >
                      {ev.pflichtveranstaltung && '* '}{ev.titel}
                    </Typography>
                  ))}
                </Box>
              )}
            </Box>
          );
        })}
      </Box>

      {/* Legend */}
      <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1.5, mt: 2 }}>
        {Object.entries(TYP_DOT_COLOR).map(([typ, color]) => (
          <Box key={typ} sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
            <Box sx={{ width: 8, height: 8, borderRadius: '50%', bgcolor: color }} />
            <Typography variant="caption" color="text.secondary">{typ}</Typography>
          </Box>
        ))}
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
          <Box sx={{ width: 8, height: 8, borderRadius: '50%', bgcolor: 'warning.main', border: '1.5px solid', borderColor: 'warning.dark' }} />
          <Typography variant="caption" color="text.secondary">Pflichtveranstaltung</Typography>
        </Box>
      </Box>
    </Box>
  );
}

// ---------------------------------------------------------------------------
// List View
// ---------------------------------------------------------------------------

function ListView({
  events,
  onEventClick,
}: {
  events: UebungListItem[];
  onEventClick: (id: string) => void;
}) {
  return (
    <List disablePadding>
      {events.map((ev, idx) => (
        <Box key={ev.id}>
          {idx > 0 && <Divider />}
          <ListItem
            onClick={() => onEventClick(ev.id)}
            sx={{
              cursor: 'pointer',
              px: 1,
              py: 1,
              borderRadius: 1,
              opacity: ev.abgesagt ? 0.55 : 1,
              '&:hover': { bgcolor: 'action.hover' },
            }}
          >
            {/* Date badge */}
            <Box
              sx={{
                minWidth: 52,
                textAlign: 'center',
                mr: 2,
                flexShrink: 0,
              }}
            >
              <Typography variant="caption" sx={{ display: 'block', color: 'text.disabled', fontSize: '0.65rem' }}>
                {new Date(ev.datum_von).getDate()}.
                {new Date(ev.datum_von).getMonth() + 1}.
              </Typography>
              <Typography variant="caption" sx={{ display: 'block', color: 'text.secondary', fontSize: '0.7rem' }}>
                {formatTime(ev.datum_von)}
              </Typography>
            </Box>

            <ListItemText
              primary={
                <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, flexWrap: 'wrap' }}>
                  {ev.pflichtveranstaltung && (
                    <StarIcon sx={{ fontSize: 14, color: 'warning.main' }} />
                  )}
                  <Typography
                    variant="body2"
                    sx={{
                      fontWeight: ev.pflichtveranstaltung ? 700 : 400,
                      textDecoration: ev.abgesagt ? 'line-through' : 'none',
                    }}
                  >
                    {ev.titel}
                  </Typography>
                  {ev.abgesagt && (
                    <Chip label="Abgesagt" size="small" color="error" variant="outlined" sx={{ fontSize: '0.6rem', height: 16 }} />
                  )}
                </Box>
              }
              secondary={
                <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.75, mt: 0.25, flexWrap: 'wrap' }}>
                  <Chip
                    label={ev.typ}
                    size="small"
                    color={TYP_CHIP_COLOR[ev.typ]}
                    variant="outlined"
                    sx={{ fontSize: '0.6rem', height: 16 }}
                  />
                  {ev.ort && (
                    <Typography variant="caption" color="text.disabled" noWrap>
                      {ev.ort}
                    </Typography>
                  )}
                </Box>
              }
              sx={{ my: 0 }}
            />

            {/* RSVP badge */}
            <Box sx={{ ml: 1 }}>
              <RsvpDot status={ev.eigener_status} />
            </Box>
          </ListItem>
        </Box>
      ))}
      {events.length === 0 && (
        <Typography
          variant="body2"
          color="text.secondary"
          sx={{ textAlign: 'center', py: 4 }}
        >
          Keine Veranstaltungen in diesem Monat.
        </Typography>
      )}
    </List>
  );
}

// ---------------------------------------------------------------------------
// Day Popover
// ---------------------------------------------------------------------------

interface DayPopoverProps {
  anchorEl: Element | null;
  day: Date | null;
  events: UebungListItem[];
  onClose: () => void;
  onEventClick: (id: string) => void;
}

function DayPopover({ anchorEl, day, events, onClose, onEventClick }: DayPopoverProps) {
  if (!day) return null;

  return (
    <Popover
      open={Boolean(anchorEl)}
      anchorEl={anchorEl}
      onClose={onClose}
      anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
      transformOrigin={{ vertical: 'top', horizontal: 'center' }}
      PaperProps={{ sx: { p: 1, maxWidth: 300, width: '90vw' } }}
    >
      <Typography variant="subtitle2" sx={{ mb: 1, px: 0.5 }}>
        {formatDateLong(day.toISOString())}
      </Typography>
      <List dense disablePadding>
        {events.map((ev) => (
          <ListItem
            key={ev.id}
            onClick={() => { onEventClick(ev.id); onClose(); }}
            sx={{
              cursor: 'pointer',
              borderRadius: 1,
              px: 0.75,
              '&:hover': { bgcolor: 'action.hover' },
              opacity: ev.abgesagt ? 0.6 : 1,
            }}
          >
            <Box
              sx={{
                width: 8,
                height: 8,
                borderRadius: '50%',
                bgcolor: TYP_DOT_COLOR[ev.typ],
                mr: 1,
                flexShrink: 0,
              }}
            />
            <ListItemText
              primary={
                <Typography
                  variant="body2"
                  sx={{
                    fontWeight: ev.pflichtveranstaltung ? 700 : 400,
                    textDecoration: ev.abgesagt ? 'line-through' : 'none',
                    display: 'flex',
                    alignItems: 'center',
                    gap: 0.5,
                  }}
                >
                  {ev.pflichtveranstaltung && <StarIcon sx={{ fontSize: 12, color: 'warning.main' }} />}
                  {ev.titel}
                </Typography>
              }
              secondary={`${formatTime(ev.datum_von)} – ${formatTime(ev.datum_bis)} Uhr`}
            />
            <RsvpDot status={ev.eigener_status} />
          </ListItem>
        ))}
      </List>
    </Popover>
  );
}

// ---------------------------------------------------------------------------
// Main Page
// ---------------------------------------------------------------------------

export default function Kalender() {
  const navigate = useNavigate();
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));

  const today = new Date();
  const [viewMonth, setViewMonth] = useState({ year: today.getFullYear(), month: today.getMonth() });
  const [viewMode, setViewMode] = useState<'calendar' | 'list'>('calendar');
  const [icalOpen, setIcalOpen] = useState(false);

  // Popover state
  const [popoverAnchor, setPopoverAnchor] = useState<Element | null>(null);
  const [popoverDay, setPopoverDay] = useState<Date | null>(null);
  const [popoverEvents, setPopoverEvents] = useState<UebungListItem[]>([]);

  // Compute fetch range: whole month ± 1 week buffer for grid
  const { from, to } = useMemo(() => {
    const firstCell = new Date(viewMonth.year, viewMonth.month, 1);
    const dayOfWeek = (firstCell.getDay() + 6) % 7;
    const f = new Date(firstCell);
    f.setDate(f.getDate() - dayOfWeek);

    const lastCell = new Date(f);
    lastCell.setDate(lastCell.getDate() + 41);

    return { from: f, to: lastCell };
  }, [viewMonth]);

  const { data, isLoading } = useQuery({
    queryKey: ['training', 'calendar', from.toISOString(), to.toISOString()],
    queryFn: () => trainingApi.getCalendarRange(from, to),
    staleTime: 5 * 60 * 1000,
  });

  const events = useMemo(() => data ?? [], [data]);

  const handlePrev = () => {
    setViewMonth((prev) => {
      const m = prev.month === 0 ? 11 : prev.month - 1;
      const y = prev.month === 0 ? prev.year - 1 : prev.year;
      return { year: y, month: m };
    });
  };

  const handleNext = () => {
    setViewMonth((prev) => {
      const m = prev.month === 11 ? 0 : prev.month + 1;
      const y = prev.month === 11 ? prev.year + 1 : prev.year;
      return { year: y, month: m };
    });
  };

  const handleToday = () => {
    setViewMonth({ year: today.getFullYear(), month: today.getMonth() });
  };

  const handleDayClick = useCallback((day: Date, anchor: Element) => {
    const key = day.toISOString().slice(0, 10);
    const dayEvs = events.filter(
      (ev) => startOfDay(new Date(ev.datum_von)).toISOString().slice(0, 10) === key
    );
    setPopoverDay(day);
    setPopoverAnchor(anchor);
    setPopoverEvents(dayEvs);
  }, [events]);

  return (
    <DashboardLayout>
      <Box sx={{ maxWidth: 900, mx: 'auto' }}>
        {/* Page header */}
        <Box
          sx={{
            display: 'flex',
            alignItems: 'center',
            flexWrap: 'wrap',
            gap: 1,
            mb: 3,
          }}
        >
          <CalendarIcon color="primary" />
          <Typography variant="h5" sx={{ flexGrow: 1, fontWeight: 700 }}>
            Dienstkalender
          </Typography>

          {/* View toggle */}
          <ButtonGroup size="small" variant="outlined">
            <Tooltip title="Monatsansicht">
              <Button
                onClick={() => setViewMode('calendar')}
                variant={viewMode === 'calendar' ? 'contained' : 'outlined'}
              >
                <CalendarIcon fontSize="small" />
                {!isMobile && <Box sx={{ ml: 0.5 }}>Monat</Box>}
              </Button>
            </Tooltip>
            <Tooltip title="Listenansicht">
              <Button
                onClick={() => setViewMode('list')}
                variant={viewMode === 'list' ? 'contained' : 'outlined'}
              >
                <ListViewIcon fontSize="small" />
                {!isMobile && <Box sx={{ ml: 0.5 }}>Liste</Box>}
              </Button>
            </Tooltip>
          </ButtonGroup>

          <Button
            size="small"
            variant="outlined"
            startIcon={<CopyIcon fontSize="small" />}
            onClick={() => setIcalOpen(true)}
            sx={{ whiteSpace: 'nowrap' }}
          >
            {isMobile ? 'iCal' : 'Kalender abonnieren'}
          </Button>
        </Box>

        {/* Month navigation */}
        <Box
          sx={{
            display: 'flex',
            alignItems: 'center',
            mb: 2,
            gap: 1,
          }}
        >
          <IconButton onClick={handlePrev} size="small" aria-label="Vorheriger Monat">
            <ChevronLeft />
          </IconButton>

          <Typography
            variant="h6"
            sx={{ flexGrow: 1, textAlign: 'center', fontWeight: 600 }}
          >
            {MONTH_LABELS[viewMonth.month]} {viewMonth.year}
          </Typography>

          <Button
            size="small"
            startIcon={<TodayIcon fontSize="small" />}
            onClick={handleToday}
            sx={{ minWidth: 'auto' }}
          >
            {!isMobile && 'Heute'}
          </Button>

          <IconButton onClick={handleNext} size="small" aria-label="Nächster Monat">
            <ChevronRight />
          </IconButton>
        </Box>

        {/* Calendar / List body */}
        {isLoading ? (
          <Skeleton variant="rectangular" height={isMobile ? 320 : 480} sx={{ borderRadius: 2 }} />
        ) : viewMode === 'calendar' ? (
          <MonthCalendar
            year={viewMonth.year}
            month={viewMonth.month}
            events={events}
            onDayClick={handleDayClick}
          />
        ) : (
          <ListView
            events={events.filter((ev) => {
              const d = new Date(ev.datum_von);
              return d.getMonth() === viewMonth.month && d.getFullYear() === viewMonth.year;
            })}
            onEventClick={(id) => navigate(`/training/${id}`)}
          />
        )}
      </Box>

      {/* Day Popover */}
      <DayPopover
        anchorEl={popoverAnchor}
        day={popoverDay}
        events={popoverEvents}
        onClose={() => setPopoverAnchor(null)}
        onEventClick={(id) => navigate(`/training/${id}`)}
      />

      {/* iCal Subscribe Dialog */}
      <IcalDialog open={icalOpen} onClose={() => setIcalOpen(false)} />
    </DashboardLayout>
  );
}
