import { useCallback, useEffect, useMemo, useState } from 'react';
import { formatDistanceToNowStrict } from 'date-fns';
import { de } from 'date-fns/locale';
import {
  createColumnHelper,
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getSortedRowModel,
  useReactTable
} from '@tanstack/react-table';
import NotificationPanel from './NotificationPanel';
import MobileConfigList from './MobileConfigList';

const CONFIG_TABLE_STATE_KEY = 'dashboardConfigTableState';
const columnHelper = createColumnHelper();
const formatDateKey = (value) => {
  const date = value instanceof Date ? value : new Date(value);
  if (Number.isNaN(date.getTime())) {
    return '';
  }
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
};

const addDays = (date, days) => {
  const next = new Date(date);
  next.setDate(next.getDate() + days);
  return next;
};

const formatPickupListTime = (value) => {
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return 'Unbekannt';
  }
  const time = date.toLocaleTimeString('de-DE', {
    hour: '2-digit',
    minute: '2-digit'
  });
  const today = new Date();
  const dateKey = formatDateKey(date);
  if (dateKey === formatDateKey(today)) {
    return `Heute ${time}`;
  }
  if (dateKey === formatDateKey(addDays(today, 1))) {
    return `Morgen ${time}`;
  }
  const diffDays = Math.round((new Date(`${dateKey}T00:00:00`).getTime() - new Date(`${formatDateKey(today)}T00:00:00`).getTime()) / (24 * 60 * 60 * 1000));
  if (diffDays > 1 && diffDays < 7) {
    const weekday = date.toLocaleDateString('de-DE', { weekday: 'short' });
    return `${weekday} ${time}`;
  }
  return date.toLocaleString('de-DE', {
    day: '2-digit',
    month: '2-digit',
    hour: '2-digit',
    minute: '2-digit'
  });
};

const compareByDate = (a, b) => {
  const aTime = new Date(a.date).getTime();
  const bTime = new Date(b.date).getTime();
  return (Number.isNaN(aTime) ? 0 : aTime) - (Number.isNaN(bTime) ? 0 : bTime);
};

const ColumnTextFilter = ({ column, placeholder }) => {
  if (!column.getCanFilter()) {
    return null;
  }
  return (
    <input
      type="text"
      value={column.getFilterValue() ?? ''}
      onChange={(event) => column.setFilterValue(event.target.value || undefined)}
      placeholder={placeholder}
      className="mt-1 w-full rounded border px-2 py-1 text-xs focus:outline-none focus:ring-1 focus:ring-blue-500"
    />
  );
};

const ColumnSelectFilter = ({ column, options, placeholder = 'Alle' }) => {
  if (!column.getCanFilter()) {
    return null;
  }
  return (
    <select
      value={column.getFilterValue() ?? ''}
      onChange={(event) => column.setFilterValue(event.target.value || undefined)}
      className="mt-1 w-full rounded border px-2 py-1 text-xs focus:outline-none focus:ring-1 focus:ring-blue-500"
    >
      <option value="">{placeholder}</option>
      {options.map((option) => (
        <option key={option.value} value={option.value}>
          {option.label}
        </option>
      ))}
    </select>
  );
};

const formatLastPickupLabel = (value) => {
  const date = new Date(value);
  if (!value || Number.isNaN(date.getTime()) || date.getTime() <= 0) {
    return null;
  }
  return date.toLocaleDateString('de-DE');
};

const formatLastPickupRelative = (value) => {
  const date = new Date(value);
  if (!value || Number.isNaN(date.getTime()) || date.getTime() <= 0) {
    return null;
  }
  return formatDistanceToNowStrict(date, { addSuffix: true, locale: de });
};

const getLastPickupTimestamp = (value) => {
  if (!value) {
    return -1;
  }
  const date = new Date(value);
  const time = date.getTime();
  return Number.isNaN(time) ? -1 : time;
};

const formatMemberSinceLabel = (value) => {
  const date = new Date(value);
  if (!value || Number.isNaN(date.getTime()) || date.getTime() <= 0) {
    return null;
  }
  return date.toLocaleDateString('de-DE');
};

const getLastPickupDescription = (entry) => {
  const lastPickupLabel = formatLastPickupLabel(entry.lastPickupAt);
  if (lastPickupLabel) {
    return `Letzte Abholung: ${lastPickupLabel}`;
  }
  const memberSinceLabel = formatMemberSinceLabel(entry.memberSinceAt);
  return memberSinceLabel ? `Noch nicht abgeholt. Beitritt: ${memberSinceLabel}` : 'Noch nicht abgeholt';
};

const getLastPickupStyle = (value) => {
  const time = getLastPickupTimestamp(value);
  if (time <= 0) {
    return {};
  }
  const ageDays = (Date.now() - time) / (1000 * 60 * 60 * 24);
  if (ageDays < 90) {
    return {};
  }
  const minDays = 90;
  const maxDays = 180;
  const ratio = Math.min(Math.max((ageDays - minDays) / (maxDays - minDays), 0), 1);
  const start = { r: 220, g: 38, b: 38 };
  const end = { r: 127, g: 29, b: 29 };
  const r = Math.round(start.r + (end.r - start.r) * ratio);
  const g = Math.round(start.g + (end.g - start.g) * ratio);
  const b = Math.round(start.b + (end.b - start.b) * ratio);
  return { color: `rgb(${r}, ${g}, ${b})` };
};

function readConfigTableState() {
  if (typeof window === 'undefined') {
    return { sorting: [], columnFilters: [] };
  }
  try {
    const raw = window.localStorage.getItem(CONFIG_TABLE_STATE_KEY);
    if (!raw) {
      return { sorting: [], columnFilters: [] };
    }
    const parsed = JSON.parse(raw);
    return {
      sorting: Array.isArray(parsed.sorting) ? parsed.sorting : [],
      columnFilters: Array.isArray(parsed.columnFilters) ? parsed.columnFilters : []
    };
  } catch {
    return { sorting: [], columnFilters: [] };
  }
}

function persistConfigTableState(state) {
  if (typeof window === 'undefined') {
    return;
  }
  try {
    window.localStorage.setItem(CONFIG_TABLE_STATE_KEY, JSON.stringify(state));
  } catch {
    /* ignore */
  }
}

const DashboardView = ({
  session,
  onRefresh,
  onLogout,
  notificationPanelOpen,
  onToggleNotificationPanel,
  notificationProps,
  stores,
  availableCollapsed,
  onToggleStores,
  onStoreSelect,
  configMap,
  regularPickupMap,
  error,
  onDismissError,
  status,
  visibleConfig,
  config,
  registeredPickups,
  onToggleActive,
  onToggleAutoDeactivate,
  onToggleProfileCheck,
  onToggleOnlyNotify,
  onToggleDormantSkip,
  onWeekdayChange,
  weekdays,
  onRangePickerRequest,
  formatRangeLabel,
  onSaveConfig,
  onResetConfig,
  onHideEntry,
  onDeleteEntry,
  canDelete,
  isDirty,
  focusedStoreId,
  onClearFocus,
  userLocation,
  locationLoading,
  locationError
}) => {
  useEffect(() => {
    if (!focusedStoreId) {
      return;
    }
    const row = document.querySelector(`[data-store-row="${focusedStoreId}"]`);
    if (!row) {
      onClearFocus();
      return;
    }
    row.scrollIntoView({ behavior: 'smooth', block: 'center' });
    row.classList.add('dashboard-row-highlight', 'ring-4', 'ring-blue-400');
    const timeout = setTimeout(() => {
      row.classList.remove('dashboard-row-highlight', 'ring-4', 'ring-blue-400');
      onClearFocus();
    }, 2500);
    return () => {
      clearTimeout(timeout);
      row.classList.remove('dashboard-row-highlight', 'ring-4', 'ring-blue-400');
    };
  }, [focusedStoreId, onClearFocus]);
  const initialTableState = useMemo(() => readConfigTableState(), []);
  const [tableSorting, setTableSorting] = useState(initialTableState.sorting);
  const [tableFilters, setTableFilters] = useState(initialTableState.columnFilters);

  useEffect(() => {
    persistConfigTableState({ sorting: tableSorting, columnFilters: tableFilters });
  }, [tableSorting, tableFilters]);

  const configTableData = useMemo(
    () =>
      Array.isArray(visibleConfig)
        ? visibleConfig.map((item) => ({
            ...item,
            normalizedLabel: (item.label || '').toLowerCase()
          }))
        : [],
    [visibleConfig]
  );

  const upcomingRegisteredPickups = useMemo(
    () =>
      (Array.isArray(registeredPickups) ? registeredPickups : [])
        .filter((pickup) => pickup?.date)
        .slice()
        .sort(compareByDate),
    [registeredPickups]
  );

  const plannedPickupEntries = useMemo(
    () =>
      (Array.isArray(visibleConfig) ? visibleConfig : [])
        .filter((entry) => entry?.active)
        .map((entry) => {
          const range = entry.desiredDateRange || (entry.desiredDate ? { start: entry.desiredDate, end: entry.desiredDate } : null);
          let schedule = 'Aktiv ohne Zeitfenster';
          if (range?.start || range?.end) {
            schedule = formatRangeLabel(range.start || range.end || '', range.end || range.start || '');
          } else if (entry.desiredWeekday) {
            schedule = entry.desiredWeekday;
          }
          return {
            id: entry.id,
            label: entry.label || `Store ${entry.id}`,
            schedule,
            onlyNotify: !!entry.onlyNotify
          };
        })
        .sort((a, b) => a.label.localeCompare(b.label, 'de-DE')),
    [formatRangeLabel, visibleConfig]
  );

  const weekdaysOptions = useMemo(
    () =>
      weekdays.map((day) => ({
        value: day,
        label: day
      })),
    [weekdays]
  );

  const formatRegularPickup = useCallback((rules) => {
    if (!Array.isArray(rules) || rules.length === 0) {
      return null;
    }
    const weekdayLabels = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'];
    const normalizeWeekday = (value) => {
      const num = Number(value);
      if (!Number.isFinite(num)) {
        return null;
      }
      if (num === 0) {
        return 0;
      }
      if (num >= 1 && num <= 7) {
        return num % 7;
      }
      return null;
    };
    const byTime = new Map();
    rules.forEach((rule) => {
      const day = normalizeWeekday(rule.weekday);
      const time = typeof rule.startTimeOfPickup === 'string' ? rule.startTimeOfPickup.slice(0, 5) : '';
      if (day === null || !time) {
        return;
      }
      if (!byTime.has(time)) {
        byTime.set(time, new Set());
      }
      byTime.get(time).add(day);
    });
    if (byTime.size === 0) {
      return null;
    }
    const buildRanges = (days) => {
      if (days.length === 0) {
        return [];
      }
      const ranges = [];
      let start = days[0];
      let last = days[0];
      for (let i = 1; i < days.length; i += 1) {
        const current = days[i];
        if (current === last + 1) {
          last = current;
        } else {
          ranges.push([start, last]);
          start = current;
          last = current;
        }
      }
      ranges.push([start, last]);
      return ranges;
    };
    const formatRange = ([start, end]) => {
      if (start === end) {
        return weekdayLabels[start];
      }
      return `${weekdayLabels[start]}-${weekdayLabels[end]}`;
    };
    const parts = Array.from(byTime.entries())
      .sort(([timeA], [timeB]) => timeA.localeCompare(timeB))
      .map(([time, daysSet]) => {
        const days = Array.from(daysSet).sort((a, b) => a - b);
        const ranges = buildRanges(days).map(formatRange).join(',');
        return `${ranges} ${time}`;
      })
      .filter(Boolean);
    return parts.length > 0 ? parts.join(' | ') : null;
  }, []);

  const configColumns = useMemo(
    () => [
      columnHelper.display({
        id: 'active',
        header: () => <span>Aktiv</span>,
        cell: ({ row }) => (
          <div className="text-center">
            <input
              type="checkbox"
              className="h-5 w-5"
              checked={row.original.active}
              onChange={() => onToggleActive(row.original.id)}
            />
          </div>
        ),
        enableSorting: false,
        enableColumnFilter: false
      }),
      columnHelper.accessor((row) => row.autoDeactivate !== false, {
        id: 'autoDeactivate',
        header: ({ column }) => (
          <div>
            <span className="font-semibold text-sm">Automatisch deaktivieren</span>
            <ColumnSelectFilter
              column={column}
              options={[
                { value: 'true', label: 'Ja' },
                { value: 'false', label: 'Nein' }
              ]}
            />
          </div>
        ),
        cell: ({ row }) => (
          <div className="text-center">
            <input
              type="checkbox"
              className="h-5 w-5"
              checked={row.original.autoDeactivate !== false}
              onChange={() => onToggleAutoDeactivate(row.original.id)}
              title="Nach erfolgreicher Slot-Aktion automatisch deaktivieren"
            />
          </div>
        ),
        filterFn: (row, columnId, value) => {
          if (value === undefined) {
            return true;
          }
          const boolValue = value === 'true';
          return row.getValue(columnId) === boolValue;
        },
        sortingFn: (rowA, rowB, columnId) => {
          const a = rowA.getValue(columnId);
          const b = rowB.getValue(columnId);
          return Number(b) - Number(a);
        }
      }),
      columnHelper.accessor('label', {
        header: ({ column }) => (
          <div>
            <button
              type="button"
              className="flex w-full items-center justify-between text-left font-semibold"
              onClick={column.getToggleSortingHandler()}
            >
              <span>Betrieb</span>
              {column.getIsSorted() ? (
                <span className="text-xs text-gray-500">{column.getIsSorted() === 'asc' ? '▲' : '▼'}</span>
              ) : (
                <span className="text-xs text-gray-400">⇅</span>
              )}
            </button>
            <ColumnTextFilter column={column} placeholder="Name / ID" />
          </div>
        ),
        cell: ({ row }) => {
          const scheduleLabel = formatRegularPickup(regularPickupMap?.[row.original.id]);
          return (
          <div className="flex items-start justify-between gap-3">
            <div>
              <span className="font-medium">{row.original.label}</span>
              {row.original.hidden && <span className="ml-2 text-xs text-gray-400">(ausgeblendet)</span>}
              <p className="text-xs text-gray-500">#{row.original.id}</p>
              {scheduleLabel && (
                <p className="text-xs text-gray-500 mt-1">Slots: {scheduleLabel}</p>
              )}
            </div>
            <a
              href={`https://foodsharing.de/store/${row.original.id}`}
              target="_blank"
              rel="noopener noreferrer"
              className="text-gray-400 hover:text-blue-600"
              title="Store öffnen"
            >
              <svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
                <path d="M12.293 2.293a1 1 0 011.414 0L18 6.586V7a1 1 0 01-1 1h-.586l-3.707-3.707a1 1 0 010-1.414z" />
                <path d="M3 5a2 2 0 012-2h5a1 1 0 010 2H5v10h10v-5a1 1 0 112 0v5a2 2 0 01-2 2H5a2 2 0 01-2-2V5z" />
                <path d="M11 3a1 1 0 100 2h2v2a1 1 0 102 0V4a1 1 0 00-1-1h-3z" />
              </svg>
            </a>
          </div>
          );
        },
        sortingFn: 'alphanumeric',
        filterFn: 'includesString'
      }),
      columnHelper.accessor('lastPickupAt', {
        header: ({ column }) => (
          <button
            type="button"
            className="flex w-full items-center justify-between text-left font-semibold"
            onClick={column.getToggleSortingHandler()}
          >
            <span>Letzte Abholung</span>
            {column.getIsSorted() ? (
              <span className="text-xs text-gray-500">{column.getIsSorted() === 'asc' ? '▲' : '▼'}</span>
            ) : (
              <span className="text-xs text-gray-400">⇅</span>
            )}
          </button>
        ),
        cell: ({ row }) => {
          const lastPickupAt = row.original.lastPickupAt;
          const style = getLastPickupStyle(lastPickupAt);
          const relative = formatLastPickupRelative(lastPickupAt);
          const memberSince = formatMemberSinceLabel(row.original.memberSinceAt);
          return (
            <span
              className="text-sm text-gray-700"
              style={style}
              title={getLastPickupDescription(row.original)}
            >
              {relative || 'Noch nicht abgeholt'}
              {!relative && memberSince && <span className="block text-xs">Beitritt: {memberSince}</span>}
            </span>
          );
        },
        sortingFn: (rowA, rowB, columnId) => {
          const a = getLastPickupTimestamp(rowA.getValue(columnId));
          const b = getLastPickupTimestamp(rowB.getValue(columnId));
          return a - b;
        },
        enableColumnFilter: false
      }),
      columnHelper.display({
        id: 'checkProfileId',
        header: () => <span>Profil prüfen</span>,
        cell: ({ row }) => (
          <div
            className="text-center"
            title={
              getLastPickupDescription(row.original)
            }
          >
            <input
              type="checkbox"
              className="h-5 w-5"
              checked={row.original.checkProfileId}
              onChange={() => onToggleProfileCheck(row.original.id)}
            />
          </div>
        ),
        enableSorting: false,
        enableColumnFilter: false
      }),
      columnHelper.display({
        id: 'skipDormantCheck',
        header: () => <span>Inaktivitätswarnung</span>,
        cell: ({ row }) => (
          <div
            className="text-center"
            title={
              getLastPickupDescription(row.original)
            }
          >
            <input
              type="checkbox"
              className="h-5 w-5"
              checked={!row.original.skipDormantCheck}
              onChange={() => onToggleDormantSkip(row.original.id)}
              title="Warnung bei ausbleibenden Abholungen/Hygiene für diesen Betrieb aktivieren"
            />
          </div>
        ),
        enableSorting: false,
        enableColumnFilter: false
      }),
      columnHelper.accessor((row) => row.onlyNotify, {
        id: 'onlyNotify',
        header: ({ column }) => (
          <div>
            <span className="font-semibold text-sm">Nur benachrichtigen</span>
            <ColumnSelectFilter
              column={column}
              options={[
                { value: 'true', label: 'Ja' },
                { value: 'false', label: 'Nein' }
              ]}
            />
          </div>
        ),
        cell: ({ row }) => (
          <div className="text-center">
            <input
              type="checkbox"
              className="h-5 w-5"
              checked={row.original.onlyNotify}
              onChange={() => onToggleOnlyNotify(row.original.id)}
            />
          </div>
        ),
        filterFn: (row, columnId, value) => {
          if (value === undefined) {
            return true;
          }
          const boolValue = value === 'true';
          return row.getValue(columnId) === boolValue;
        },
        sortingFn: (rowA, rowB, columnId) => {
          const a = rowA.getValue(columnId);
          const b = rowB.getValue(columnId);
          return Number(b) - Number(a);
        }
      }),
      columnHelper.accessor('desiredWeekday', {
        header: ({ column }) => (
          <div>
            <span className="font-semibold text-sm">Wochentag</span>
            <ColumnSelectFilter column={column} options={weekdaysOptions} placeholder="Alle Tage" />
          </div>
        ),
        cell: ({ row }) => (
          <select
            value={row.original.desiredWeekday || ''}
            onChange={(event) => onWeekdayChange(row.original.id, event.target.value)}
            className="border rounded p-1 w-full"
          >
            <option value="">Kein Wochentag</option>
            {weekdays.map((day) => (
              <option key={day} value={day}>
                {day}
              </option>
            ))}
          </select>
        ),
        filterFn: (row, columnId, value) => {
          if (!value) {
            return true;
          }
          return (row.getValue(columnId) || '') === value;
        },
        sortingFn: 'alphanumeric'
      }),
      columnHelper.display({
        id: 'dateRange',
        header: () => <span>Datum / Zeitraum</span>,
        cell: ({ row }) => {
          const normalizedRange = row.original.desiredDateRange
            ? { ...row.original.desiredDateRange }
            : row.original.desiredDate
            ? { start: row.original.desiredDate, end: row.original.desiredDate }
            : null;
          const rangeStart = normalizedRange?.start || '';
          const rangeEnd = normalizedRange?.end || '';
          return (
            <button
              type="button"
              onClick={() => onRangePickerRequest(row.original.id)}
              className="w-full border rounded p-2 text-left transition focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white hover:border-blue-400"
            >
              <span className="block text-sm text-gray-700">{formatRangeLabel(rangeStart, rangeEnd)}</span>
              <span className="block text-xs text-gray-500">Klicke zum Auswählen</span>
            </button>
          );
        },
        enableSorting: false,
        enableColumnFilter: false
      }),
      columnHelper.display({
        id: 'actions',
        header: () => <span className="sr-only">Aktionen</span>,
        cell: ({ row }) => (
          <div className="inline-flex items-center justify-end gap-3 whitespace-nowrap w-full">
            <button
              type="button"
              onClick={() => onHideEntry(row.original.id)}
              className="text-gray-600 hover:text-gray-900"
              title="Ausblenden"
            >
              <svg xmlns="http://www.w3.org/2000/svg" className="inline h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 19c7 0 9-7 9-7s-2-7-9-7-9 7-9 7 2 7 9 7z" />
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15a3 3 0 100-6 3 3 0 000 6z" />
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 3l18 18" />
              </svg>
            </button>
            {canDelete && (
              <button
                type="button"
                onClick={() => onDeleteEntry(row.original.id)}
                className="text-red-600 hover:text-red-800"
                title="Löschen"
              >
                <svg xmlns="http://www.w3.org/2000/svg" className="inline h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                </svg>
              </button>
            )}
          </div>
        ),
        enableSorting: false,
        enableColumnFilter: false
      })
    ],
    [
      onDeleteEntry,
      onHideEntry,
      onRangePickerRequest,
      onToggleAutoDeactivate,
      onToggleActive,
      onToggleDormantSkip,
      onToggleOnlyNotify,
      onToggleProfileCheck,
      onWeekdayChange,
      formatRangeLabel,
      canDelete,
      formatRegularPickup,
      regularPickupMap,
      weekdays,
      weekdaysOptions
    ]
  );

  const configTable = useReactTable({
    data: configTableData,
    columns: configColumns,
    state: {
      sorting: tableSorting,
      columnFilters: tableFilters
    },
    onSortingChange: setTableSorting,
    onColumnFiltersChange: setTableFilters,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel()
  });

  const {
    error: notificationError,
    message: notificationMessage,
    settings: notificationSettings,
    capabilities: notificationCapabilities,
    loading: notificationLoading,
    dirty: notificationDirty,
    saving: notificationSaving,
    onReset: onNotificationReset,
    onSave: onNotificationSave,
    onFieldChange: onNotificationFieldChange,
    onSendTest: onNotificationTest,
    onCopyLink: onNotificationCopy,
    copyFeedback,
    ntfyPreviewUrl
  } = notificationProps;

  const sortedStores = useMemo(() => {
    const list = Array.isArray(stores) ? [...stores] : [];
    return list.sort((a, b) => {
      const aId = a?.id != null ? String(a.id) : '';
      const bId = b?.id != null ? String(b.id) : '';
      const aInConfig = configMap?.has(aId);
      const bInConfig = configMap?.has(bId);
      if (aInConfig !== bInConfig) {
        return aInConfig ? 1 : -1;
      }
      const nameA = (a?.name || '').toLocaleLowerCase('de-DE');
      const nameB = (b?.name || '').toLocaleLowerCase('de-DE');
      if (nameA < nameB) {
        return -1;
      }
      if (nameA > nameB) {
        return 1;
      }
      return 0;
    });
  }, [stores, configMap]);

  return (
    <div className="p-4 max-w-6xl mx-auto bg-white shadow-lg rounded-lg mt-4">
      <h1 className="dashboard-page-title text-2xl font-bold mb-4 text-center text-gray-800">Foodsharing Manager</h1>
      <div className="dashboard-summary-card dashboard-session bg-blue-50 border border-blue-100 rounded-lg p-4 mb-4 shadow">
        <div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
          <div className="dashboard-session__identity">
            <p className="dashboard-session__label text-sm uppercase text-blue-600 font-semibold">Angemeldet</p>
            <p className="dashboard-session__name text-lg font-medium text-gray-800">{session.profile.name}</p>
          </div>
        <div className="dashboard-session__actions flex flex-wrap gap-2 items-center">
            <button
              onClick={() => onRefresh({ block: false })}
              className="dashboard-session__refresh bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors"
            >
              Betriebe aktualisieren
            </button>
            <button
              onClick={onLogout}
              className="dashboard-session__logout bg-gray-200 hover:bg-gray-300 text-gray-800 py-2 px-4 rounded focus:outline-none focus:ring-2 focus:ring-gray-400 transition-colors"
            >
              Logout
            </button>
            <button
              type="button"
              onClick={onToggleNotificationPanel}
              className={`dashboard-session__notifications flex items-center justify-center w-11 h-11 rounded-full border ${
                notificationPanelOpen ? 'border-blue-500 text-blue-600' : 'border-gray-300 text-gray-600'
              } hover:text-blue-700 hover:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-400 transition`}
              title="Benachrichtigungen konfigurieren"
            >
              <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.89 3.31.877 2.42 2.42a1.724 1.724 0 0 0 1.065 2.572c1.757.426 1.757 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.89 1.543-.877 3.31-2.42 2.42a1.724 1.724 0 0 0-2.572 1.065c-.426 1.757-2.924 1.757-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.89-3.31-.877-2.42-2.42a1.724 1.724 0 0 0-1.065-2.572c-1.757-.426-1.757-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.89-1.543.877-3.31 2.42-2.42.996.575 2.273.155 2.573-1.065z"
                />
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0z" />
              </svg>
            </button>
            {notificationLoading && <span className="text-sm text-gray-500 ml-1">Lade…</span>}
          </div>
        </div>
      </div>

      {notificationPanelOpen && (
        <NotificationPanel
          error={notificationError}
          message={notificationMessage}
          settings={notificationSettings}
          capabilities={notificationCapabilities}
          loading={notificationLoading}
          dirty={notificationDirty}
          saving={notificationSaving}
          onReset={onNotificationReset}
          onSave={onNotificationSave}
          onFieldChange={onNotificationFieldChange}
          onSendTest={onNotificationTest}
          onCopyLink={onNotificationCopy}
          copyFeedback={copyFeedback}
          ntfyPreviewUrl={ntfyPreviewUrl}
          location={userLocation}
          locationLoading={locationLoading}
          locationError={locationError}
        />
      )}

      <div className="mb-6 border border-gray-200 rounded-lg overflow-hidden">
        <button
          onClick={onToggleStores}
          className="w-full flex items-center justify-between px-4 py-3 bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-300"
        >
          <span className="font-semibold text-gray-800">Verfügbare Betriebe ({stores.length})</span>
          <svg
            xmlns="http://www.w3.org/2000/svg"
            className={`h-5 w-5 text-gray-600 transition-transform ${availableCollapsed ? '' : 'rotate-180'}`}
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
          </svg>
        </button>
        {!availableCollapsed && (
          <div className="max-h-72 overflow-y-auto divide-y divide-gray-100">
            {sortedStores.map((store) => {
              const storeId = String(store.id);
              const entry = configMap.get(storeId);
              const isVisible = entry && !entry.hidden;
              const blockedByNoPickups = store.hasPickupSlots === false;
              let statusLabel = 'Hinzufügen';
              let statusClass = 'text-blue-600';
              if (isVisible) {
                statusLabel = 'Bereits in Konfiguration';
                statusClass = 'text-gray-500';
              } else if (entry) {
                statusLabel = 'Ausgeblendet – erneut hinzufügen';
                statusClass = 'text-amber-600';
              } else if (blockedByNoPickups) {
                statusLabel = 'Keine Pickups – automatisch verborgen';
                statusClass = 'text-red-600';
              }
              return (
                <div
                  key={storeId}
                  className="flex items-center justify-between px-4 py-3 hover:bg-gray-50 transition cursor-default"
                >
                  <div>
                    <p className="font-semibold text-gray-800">{store.name}</p>
                    <p className="text-sm text-gray-500">
                      {store.zip} {store.city}
                    </p>
                    <p className={`text-xs mt-2 ${statusClass}`}>{statusLabel}</p>
                  </div>
              <div className="flex items-center gap-2">
                <label className="flex items-center gap-1 text-sm text-gray-700">
                  <input
                    type="checkbox"
                    className="h-4 w-4"
                    checked={!entry?.skipDormantCheck}
                    onChange={() => onToggleDormantSkip(storeId)}
                    title="Warnung bei ausbleibenden Abholungen/Hygiene für diesen Betrieb aktivieren"
                  />
                  <span>Inaktivitätswarnung</span>
                </label>
                <button
                  onClick={() => onStoreSelect(store)}
                  title={blockedByNoPickups ? 'Keine Pickups – automatisch verborgen' : undefined}
                  className="bg-blue-50 hover:bg-blue-100 text-blue-600 border border-blue-200 px-3 py-1.5 rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-300"
                >
                  {isVisible ? 'Zur Liste springen' : 'Hinzufügen'}
                </button>
              </div>
            </div>
          );
        })}
      </div>
    )}
      </div>

      {error && (
        <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4 relative">
          <span className="block sm:inline">{error}</span>
          <button className="absolute top-0 bottom-0 right-0 px-4 py-3" onClick={onDismissError}>
            <span className="text-xl">&times;</span>
          </button>
        </div>
      )}

      {status && (
        <div className="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4 relative">
          <span className="block sm:inline">{status}</span>
      </div>
    )}

      <div className="mb-4 grid gap-3 lg:grid-cols-2">
        <section className="border border-gray-200 rounded-lg bg-gray-50 p-3">
          <div className="flex items-center justify-between gap-3 mb-2">
            <h2 className="text-sm font-semibold text-gray-800">Foodsharing-Slots</h2>
            <span className="text-xs text-gray-500">{upcomingRegisteredPickups.length}</span>
          </div>
          {upcomingRegisteredPickups.length === 0 ? (
            <p className="text-sm text-gray-500">Keine eingetragenen künftigen Slots gefunden.</p>
          ) : (
            <ul className="space-y-1.5 max-h-40 overflow-y-auto">
              {upcomingRegisteredPickups.slice(0, 8).map((pickup) => (
                <li
                  key={`${pickup.storeId || 'store'}-${pickup.date}-${pickup.description || ''}`}
                  className="flex items-start justify-between gap-3 rounded bg-white px-2 py-1.5 text-sm"
                >
                  <div className="min-w-0">
                    <p className="truncate font-medium text-gray-800">{pickup.storeName}</p>
                    <p className="truncate text-xs text-gray-500">{pickup.description || 'Abholslot'}</p>
                  </div>
                  <div className="shrink-0 text-right">
                    <p className="text-xs font-medium text-blue-700">{formatPickupListTime(pickup.date)}</p>
                    <p className="text-xs text-gray-500">{pickup.isConfirmed ? 'bestätigt' : 'offen'}</p>
                  </div>
                </li>
              ))}
            </ul>
          )}
        </section>

        <section className="border border-gray-200 rounded-lg bg-gray-50 p-3">
          <div className="flex items-center justify-between gap-3 mb-2">
            <h2 className="text-sm font-semibold text-gray-800">Pickup-Manager geplant</h2>
            <span className="text-xs text-gray-500">{plannedPickupEntries.length}</span>
          </div>
          {plannedPickupEntries.length === 0 ? (
            <p className="text-sm text-gray-500">Keine aktiven Planungen im Foodsharing Manager.</p>
          ) : (
            <ul className="space-y-1.5 max-h-40 overflow-y-auto">
              {plannedPickupEntries.slice(0, 8).map((entry) => (
                <li
                  key={entry.id}
                  className="flex items-center justify-between gap-3 rounded bg-white px-2 py-1.5 text-sm"
                >
                  <p className="min-w-0 truncate font-medium text-gray-800">{entry.label}</p>
                  <div className="shrink-0 text-right">
                    <p className="text-xs font-medium text-emerald-700">{entry.schedule}</p>
                    {entry.onlyNotify && <p className="text-xs text-gray-500">nur Hinweis</p>}
                  </div>
                </li>
              ))}
            </ul>
          )}
        </section>
      </div>

      <MobileConfigList
        entries={visibleConfig}
        regularPickupMap={regularPickupMap}
        weekdays={weekdays}
        formatRangeLabel={formatRangeLabel}
        formatRegularPickup={formatRegularPickup}
        onToggleActive={onToggleActive}
        onToggleAutoDeactivate={onToggleAutoDeactivate}
        onToggleProfileCheck={onToggleProfileCheck}
        onToggleOnlyNotify={onToggleOnlyNotify}
        onToggleDormantSkip={onToggleDormantSkip}
        onWeekdayChange={onWeekdayChange}
        onRangePickerRequest={onRangePickerRequest}
        onHideEntry={onHideEntry}
        onDeleteEntry={onDeleteEntry}
        canDelete={canDelete}
        isDirty={isDirty}
        onSaveConfig={onSaveConfig}
        onResetConfig={onResetConfig}
      />

      <div className="desktop-config-table overflow-x-auto">
        <table className="min-w-full bg-white border border-gray-200">
          <thead className="bg-gray-100">
            {configTable.getHeaderGroups().map((headerGroup) => (
              <tr key={headerGroup.id}>
                {headerGroup.headers.map((header) => (
                  <th key={header.id} className="px-4 py-2 text-left align-top text-sm font-semibold">
                    {flexRender(header.column.columnDef.header, header.getContext())}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody>
            {configTable.getRowModel().rows.map((row, idx) => (
              <tr
                key={row.id}
                data-store-row={row.original.id}
                className={idx % 2 === 0 ? 'bg-gray-50' : 'bg-white'}
              >
                {row.getVisibleCells().map((cell) => (
                  <td key={cell.id} className="px-4 py-2 align-middle">
                    {flexRender(cell.column.columnDef.cell, cell.getContext())}
                  </td>
                ))}
              </tr>
            ))}
            {configTable.getRowModel().rows.length === 0 && (
              <tr>
                <td
                  className="px-4 py-6 text-center text-sm text-gray-500"
                  colSpan={configTable.getHeaderGroups()?.[0]?.headers.length || 1}
                >
                  Keine Einträge gefunden. Filter zurücksetzen oder Suchbegriff anpassen.
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>

      <div className="desktop-config-actions mt-6 flex justify-between">
        <button onClick={onResetConfig} className="bg-gray-500 hover:bg-gray-600 text-white py-2 px-4 rounded">
          Zurücksetzen
        </button>
        <button onClick={onSaveConfig} className="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded">
          Konfiguration speichern
        </button>
      </div>

    </div>
  );
};

export default DashboardView;
