import React from 'react';
import {
  Box,
  Chip,
  Link,
  Skeleton,
  Typography,
} from '@mui/material';
import { CalendarMonth as CalendarMonthIcon } from '@mui/icons-material';
import { Link as RouterLink } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { trainingApi } from '../../services/training';
import { eventsApi } from '../../services/events';
import type { UebungListItem, UebungTyp } from '../../types/training.types';
import type { VeranstaltungListItem } from '../../types/events.types';
import { ListCard } from '../templates/ListCard';
import { WidgetCard } from '../templates/WidgetCard';

// ---------------------------------------------------------------------------
// Color map — matches TYP_DOT_COLOR in Kalender.tsx
// ---------------------------------------------------------------------------
const TYP_DOT_COLOR: Record<UebungTyp, string> = {
  'Übungsabend':        '#1976d2',
  'Lehrgang':           '#7b1fa2',
  'Sonderdienst':       '#e65100',
  'Versammlung':        '#616161',
  'Gemeinschaftsübung': '#00796b',
  'Sonstiges':          '#9e9e9e',
};

/** Fallback color for Veranstaltung when no kategorie_farbe is present */
const VERANSTALTUNG_DEFAULT_COLOR = '#c62828';

// ---------------------------------------------------------------------------
// Unified entry shape used internally
// ---------------------------------------------------------------------------
interface CalendarEntry {
  id: string;
  date: Date;
  title: string;
  /** Hex color for the type dot */
  color: string;
  /** Human-readable label shown in the chip */
  typeLabel: string;
  /** Whether the event is all-day (no time shown) */
  allDay: boolean;
  /** Source: training or event */
  source: 'training' | 'event';
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

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

function formatDateShort(d: Date): string {
  const weekday = WEEKDAY_SHORT[d.getDay()];
  const day = String(d.getDate()).padStart(2, '0');
  const month = String(d.getMonth() + 1).padStart(2, '0');
  return `${weekday} ${day}.${month}.`;
}

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

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

function mapTraining(item: UebungListItem): CalendarEntry {
  return {
    id: `training-${item.id}`,
    date: new Date(item.datum_von),
    title: item.titel,
    color: TYP_DOT_COLOR[item.typ] ?? TYP_DOT_COLOR['Sonstiges'],
    typeLabel: item.typ,
    allDay: false,
    source: 'training',
  };
}

function mapVeranstaltung(item: VeranstaltungListItem): CalendarEntry {
  return {
    id: `event-${item.id}`,
    date: new Date(item.datum_von),
    title: item.titel,
    color: item.kategorie_farbe ?? VERANSTALTUNG_DEFAULT_COLOR,
    typeLabel: item.kategorie_name ?? 'Veranstaltung',
    allDay: item.ganztaegig,
    source: 'event',
  };
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

const FETCH_LIMIT = 20; // fetch more than 5 so filtering from today leaves enough
const DISPLAY_LIMIT = 5;

const UpcomingEventsWidget: React.FC = () => {
  const { data: trainingItems = [], isLoading: trainingLoading, isError: trainingError } = useQuery<UebungListItem[]>({
    queryKey: ['upcoming-trainings'],
    queryFn: () => trainingApi.getUpcoming(FETCH_LIMIT),
  });

  const { data: eventItems = [], isLoading: eventsLoading, isError: eventsError } = useQuery<VeranstaltungListItem[]>({
    queryKey: ['upcoming-events'],
    queryFn: () => eventsApi.getUpcoming(FETCH_LIMIT),
  });

  const loading = trainingLoading || eventsLoading;
  const error = trainingError || eventsError;

  const entries = React.useMemo(() => {
    if (loading) return [];
    const today = startOfToday();
    return [
      ...trainingItems
        .filter((t) => !t.abgesagt)
        .map(mapTraining),
      ...eventItems
        .filter((e) => !e.abgesagt)
        .map(mapVeranstaltung),
    ]
      .filter((e) => e.date >= today)
      .sort((a, b) => a.date.getTime() - b.date.getTime())
      .slice(0, DISPLAY_LIMIT);
  }, [trainingItems, eventItems, loading]);

  // ── Render ────────────────────────────────────────────────────────────────
  if (error) {
    return (
      <WidgetCard
        title="Nächste Termine"
        icon={<CalendarMonthIcon fontSize="small" />}
        isError
        errorMessage="Termine konnten nicht geladen werden."
      />
    );
  }

  return (
    <ListCard
      title="Nächste Termine"
      icon={<CalendarMonthIcon fontSize="small" />}
      items={entries}
      renderItem={(entry) => (
        <Box
          sx={{
            display: 'flex',
            alignItems: 'flex-start',
            gap: 1.5,
          }}
        >
          {/* Colored type indicator dot */}
          <Box
            sx={{
              mt: '4px',
              flexShrink: 0,
              width: 10,
              height: 10,
              borderRadius: '50%',
              bgcolor: entry.color,
            }}
          />

          {/* Date + title block */}
          <Box sx={{ flex: 1, minWidth: 0 }}>
            <Box
              sx={{
                display: 'flex',
                alignItems: 'center',
                gap: 0.75,
                flexWrap: 'wrap',
                mb: 0.25,
              }}
            >
              <Typography
                variant="caption"
                sx={{
                  color: 'text.secondary',
                  fontVariantNumeric: 'tabular-nums',
                  whiteSpace: 'nowrap',
                }}
              >
                {formatDateShort(entry.date)}
                {!entry.allDay && (
                  <> &middot; {formatTime(entry.date.toISOString())}</>
                )}
              </Typography>

              <Chip
                label={entry.typeLabel}
                size="small"
                sx={{
                  height: 16,
                  fontSize: '0.65rem',
                  bgcolor: `${entry.color}22`,
                  color: entry.color,
                  border: `1px solid ${entry.color}55`,
                  fontWeight: 600,
                  '& .MuiChip-label': { px: '5px' },
                }}
              />
            </Box>

            <Typography
              variant="body2"
              sx={{
                fontWeight: 500,
                overflow: 'hidden',
                textOverflow: 'ellipsis',
                whiteSpace: 'nowrap',
              }}
            >
              {entry.title}
            </Typography>
          </Box>
        </Box>
      )}
      isLoading={loading}
      skeletonCount={5}
      skeletonItem={
        <Box sx={{ display: 'flex', gap: 1.5, alignItems: 'flex-start' }}>
          <Skeleton variant="circular" width={10} height={10} sx={{ mt: '4px' }} animation="wave" />
          <Box sx={{ flex: 1 }}>
            <Skeleton variant="text" width="70%" animation="wave" />
            <Skeleton variant="text" width="40%" animation="wave" />
          </Box>
        </Box>
      }
      emptyMessage="Keine bevorstehenden Termine"
      footer={
        <Box sx={{ textAlign: 'right' }}>
          <Link
            component={RouterLink}
            to="/kalender"
            underline="hover"
            variant="body2"
            sx={{ fontWeight: 500 }}
          >
            Alle Termine
          </Link>
        </Box>
      }
    />
  );
};

export default UpcomingEventsWidget;
