import { useCallback, useEffect, useMemo, useState } from 'react';
import ConfirmationDialog from './ConfirmationDialog';
import './JournalPage.css';
import {
  formatReferenceLabel,
  formatReminderOffset,
  getNextReminderSchedule,
  getReminderOffset,
  getReminderReference,
  referenceEventOptions
} from '../utils/journalReminder';

const intervalLabels = {
  monthly: 'Monatlich',
  quarterly: 'Vierteljährlich',
  yearly: 'Jährlich'
};
const reminderUnitLabels = {
  days: 'Tage',
  weeks: 'Wochen',
  months: 'Monate'
};

const JournalPage = ({ authorizedFetch, stores }) => {
  const [entries, setEntries] = useState([]);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState('');
  const [editingEntryId, setEditingEntryId] = useState(null);
  const [deleteDialog, setDeleteDialog] = useState({ open: false, entry: null });
  const [formOpen, setFormOpen] = useState(false);
  const [closingForm, setClosingForm] = useState(false);
  const [editingStoreLabel, setEditingStoreLabel] = useState('');
  const [filters, setFilters] = useState({
    query: '',
    storeId: '',
    reminderOnly: false,
    withImagesOnly: false,
    dateFrom: '',
    dateTo: ''
  });
  const [sortBy, setSortBy] = useState('pickupDateDesc');
  const [hoverPreview, setHoverPreview] = useState({
    open: false,
    src: '',
    alt: '',
    left: 0,
    top: 0,
    width: 0,
    height: 0
  });
  const [form, setForm] = useState({
    storeId: '',
    pickupDate: '',
    note: '',
    reminderEnabled: true,
    reminderInterval: 'yearly',
    reminderBeforeValue: 6,
    reminderBeforeUnit: 'weeks',
    reminderReferenceMode: 'pickupDate',
    reminderReferenceEventKey: 'easter_sunday',
    reminderReferenceOffsetValue: 0,
    reminderReferenceOffsetUnit: 'weeks'
  });
  const [images, setImages] = useState([]);
  const [existingImages, setExistingImages] = useState([]);

  const sortedStores = useMemo(() => {
    return [...(stores || [])].sort((a, b) => (a.name || '').localeCompare(b.name || ''));
  }, [stores]);

  const storeOptions = useMemo(() => {
    const options = [...sortedStores];
    const hasSelection = form.storeId && options.some((store) => String(store.id) === String(form.storeId));
    if (!hasSelection && form.storeId) {
      options.unshift({
        id: form.storeId,
        name: editingStoreLabel || `Store ${form.storeId}`
      });
    }
    return options;
  }, [sortedStores, form.storeId, editingStoreLabel]);

  const storeLabelMap = useMemo(() => {
    const map = new Map();
    sortedStores.forEach((store) => {
      if (store?.id) {
        map.set(String(store.id), store.name || `Store ${store.id}`);
      }
    });
    entries.forEach((entry) => {
      if (entry?.storeId && entry?.storeName) {
        map.set(String(entry.storeId), entry.storeName);
      }
    });
    return map;
  }, [sortedStores, entries]);

  const parseDateValue = useCallback((value) => {
    if (!value) {
      return null;
    }
    const parsed = new Date(`${value}T00:00:00`);
    if (Number.isNaN(parsed.getTime())) {
      return null;
    }
    return parsed.getTime();
  }, []);

  const formatDateLabel = useCallback((date) => {
    if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
      return 'unbekannt';
    }
    return date.toLocaleDateString('de-DE', {
      weekday: 'long',
      day: '2-digit',
      month: '2-digit',
      year: 'numeric'
    });
  }, []);

  const getNextReminderTimestamp = useCallback(
    (entry) => {
      const schedule = getNextReminderSchedule(entry);
      return schedule?.reminderDate?.getTime() ?? null;
    },
    []
  );

  const reminderPreview = useMemo(() => {
    if (!form.reminderEnabled) {
      return null;
    }
    const previewEntry = {
      pickupDate: form.pickupDate,
      reminder: {
        enabled: true,
        interval: form.reminderReferenceMode === 'event' ? 'yearly' : form.reminderInterval,
        beforeUnit: form.reminderBeforeUnit,
        beforeValue: Number(form.reminderBeforeValue),
        reference: {
          mode: form.reminderReferenceMode,
          eventKey: form.reminderReferenceEventKey,
          occurrenceOffsetValue: Number(form.reminderReferenceOffsetValue),
          occurrenceOffsetUnit: form.reminderReferenceOffsetUnit
        }
      }
    };
    const schedule = getNextReminderSchedule(previewEntry);
    if (!schedule?.occurrence || !schedule?.reminderDate) {
      return null;
    }
    return {
      occurrenceLabel: formatDateLabel(schedule.occurrence),
      reminderLabel: formatDateLabel(schedule.reminderDate)
    };
  }, [
    form.pickupDate,
    form.reminderBeforeUnit,
    form.reminderBeforeValue,
    form.reminderEnabled,
    form.reminderInterval,
    form.reminderReferenceEventKey,
    form.reminderReferenceMode,
    form.reminderReferenceOffsetUnit,
    form.reminderReferenceOffsetValue,
    formatDateLabel
  ]);

  const filteredEntries = useMemo(() => {
    const query = filters.query.trim().toLowerCase();
    const fromValue = parseDateValue(filters.dateFrom);
    const toValue = parseDateValue(filters.dateTo);
    const results = entries.filter((entry) => {
      if (filters.storeId && String(entry.storeId) !== String(filters.storeId)) {
        return false;
      }
      if (filters.reminderOnly && !entry.reminder?.enabled) {
        return false;
      }
      if (filters.withImagesOnly && (!Array.isArray(entry.images) || entry.images.length === 0)) {
        return false;
      }
      if (fromValue || toValue) {
        const entryDate = parseDateValue(entry.pickupDate);
        if (fromValue && (!entryDate || entryDate < fromValue)) {
          return false;
        }
        if (toValue && (!entryDate || entryDate > toValue)) {
          return false;
        }
      }
      if (query) {
        const storeLabel = entry.storeName || storeLabelMap.get(String(entry.storeId)) || '';
        const haystack = `${storeLabel} ${entry.note || ''}`.toLowerCase();
        if (!haystack.includes(query)) {
          return false;
        }
      }
      return true;
    });

    const sorters = {
      pickupDateDesc: (a, b) => (b.pickupDate || '').localeCompare(a.pickupDate || ''),
      pickupDateAsc: (a, b) => (a.pickupDate || '').localeCompare(b.pickupDate || ''),
      createdAtDesc: (a, b) => (b.createdAt || '').localeCompare(a.createdAt || ''),
      createdAtAsc: (a, b) => (a.createdAt || '').localeCompare(b.createdAt || ''),
      storeNameAsc: (a, b) => {
        const aLabel = a.storeName || storeLabelMap.get(String(a.storeId)) || '';
        const bLabel = b.storeName || storeLabelMap.get(String(b.storeId)) || '';
        return aLabel.localeCompare(bLabel);
      },
      storeNameDesc: (a, b) => {
        const aLabel = a.storeName || storeLabelMap.get(String(a.storeId)) || '';
        const bLabel = b.storeName || storeLabelMap.get(String(b.storeId)) || '';
        return bLabel.localeCompare(aLabel);
      },
      nextReminderAsc: (a, b) => {
        const aNext = getNextReminderTimestamp(a);
        const bNext = getNextReminderTimestamp(b);
        if (aNext === null && bNext === null) {
          return 0;
        }
        if (aNext === null) {
          return 1;
        }
        if (bNext === null) {
          return -1;
        }
        return aNext - bNext;
      }
    };
    const sorter = sorters[sortBy] || sorters.pickupDateDesc;
    return [...results].sort(sorter);
  }, [entries, filters, getNextReminderTimestamp, parseDateValue, sortBy, storeLabelMap]);

  const releaseEntryImageUrls = useCallback((entryList) => {
    if (!Array.isArray(entryList)) {
      return;
    }
    entryList.forEach((entry) => {
      if (!Array.isArray(entry.images)) {
        return;
      }
      entry.images.forEach((image) => {
        if (image?.displayUrl) {
          URL.revokeObjectURL(image.displayUrl);
        }
      });
    });
  }, []);

  const hydrateEntryImages = useCallback(
    async (entry) => {
      if (!entry || !Array.isArray(entry.images) || entry.images.length === 0) {
        return entry;
      }
      const hydratedImages = await Promise.all(
        entry.images.map(async (image) => {
          if (!image?.url) {
            return image;
          }
          try {
            const response = await authorizedFetch(image.url);
            if (!response.ok) {
              throw new Error(`HTTP ${response.status}`);
            }
            const blob = await response.blob();
            return { ...image, displayUrl: URL.createObjectURL(blob) };
          } catch (_error) {
            return image;
          }
        })
      );
      return { ...entry, images: hydratedImages };
    },
    [authorizedFetch]
  );

  const loadEntries = useCallback(async () => {
    setLoading(true);
    setError('');
    try {
      const response = await authorizedFetch('/api/journal');
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      const data = await response.json();
      const normalized = Array.isArray(data) ? data : [];
      const hydrated = await Promise.all(normalized.map((entry) => hydrateEntryImages(entry)));
      hydrated.sort((a, b) => (b.pickupDate || '').localeCompare(a.pickupDate || ''));
      setEntries((prev) => {
        releaseEntryImageUrls(prev);
        return hydrated;
      });
    } catch (err) {
      setError(`Journal konnte nicht geladen werden: ${err.message}`);
    } finally {
      setLoading(false);
    }
  }, [authorizedFetch, hydrateEntryImages, releaseEntryImageUrls]);

  const resetFormImmediate = useCallback(() => {
    images.forEach((entry) => URL.revokeObjectURL(entry.previewUrl));
    setImages([]);
    setExistingImages([]);
    setEditingEntryId(null);
    setFormOpen(false);
    setClosingForm(false);
    setEditingStoreLabel('');
      setForm({
        storeId: '',
        pickupDate: '',
        note: '',
        reminderEnabled: true,
        reminderInterval: 'yearly',
        reminderBeforeValue: 6,
        reminderBeforeUnit: 'weeks',
        reminderReferenceMode: 'pickupDate',
        reminderReferenceEventKey: 'easter_sunday',
        reminderReferenceOffsetValue: 0,
        reminderReferenceOffsetUnit: 'weeks'
      });
  }, [images]);

  const resetForm = useCallback(() => {
    if (!formOpen) {
      return;
    }
    setClosingForm(true);
    setTimeout(() => resetFormImmediate(), 160);
  }, [formOpen, resetFormImmediate]);

  useEffect(() => {
    loadEntries();
  }, [loadEntries]);

  useEffect(() => {
    if (!formOpen) {
      return;
    }
    const handleKeyDown = (event) => {
      if (event.key === 'Escape') {
        resetForm();
      }
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [formOpen, resetForm]);


  const handleFormChange = (patch) => {
    setForm((prev) => ({ ...prev, ...patch }));
  };

  const handleImageChange = (event) => {
    const files = Array.from(event.target.files || []);
    const availableSlots = Math.max(0, 5 - existingImages.length - images.length);
    if (availableSlots === 0) {
      event.target.value = '';
      return;
    }
    const nextImages = files.slice(0, availableSlots).map((file) => ({
      file,
      name: file.name,
      previewUrl: URL.createObjectURL(file)
    }));
    setImages((prev) => [...prev, ...nextImages].slice(0, 5));
    event.target.value = '';
  };

  const removeImage = (index) => {
    setImages((prev) => {
      const next = [...prev];
      const removed = next.splice(index, 1);
      removed.forEach((entry) => URL.revokeObjectURL(entry.previewUrl));
      return next;
    });
  };

  const readFileAsDataUrl = (file) =>
    new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result);
      reader.onerror = () => reject(new Error('Bild konnte nicht gelesen werden'));
      reader.readAsDataURL(file);
    });

  const handleSubmit = async (event) => {
    event.preventDefault();
    if (!form.storeId || !form.pickupDate) {
      setError('Bitte Betrieb und Abholdatum ausfüllen.');
      return;
    }
    setSaving(true);
    setError('');
    try {
      const selectedStore = sortedStores.find((store) => String(store.id) === String(form.storeId));
      const imagePayload = await Promise.all(
        images.map(async (entry) => ({
          name: entry.name,
          dataUrl: await readFileAsDataUrl(entry.file)
        }))
      );
      const payload = {
        storeId: form.storeId,
        storeName: selectedStore?.name || '',
        pickupDate: form.pickupDate,
        note: form.note.trim(),
        reminder: {
          enabled: form.reminderEnabled,
          interval: form.reminderReferenceMode === 'event' ? 'yearly' : form.reminderInterval,
          beforeUnit: form.reminderBeforeUnit,
          beforeValue: Number(form.reminderBeforeValue),
          reference: {
            mode: form.reminderReferenceMode,
            eventKey: form.reminderReferenceEventKey,
            occurrenceOffsetValue: Number(form.reminderReferenceOffsetValue),
            occurrenceOffsetUnit: form.reminderReferenceOffsetUnit
          }
        },
        images: imagePayload,
        keepImageIds: existingImages.map((image) => image.id)
      };
      const response = await authorizedFetch(editingEntryId ? `/api/journal/${editingEntryId}` : '/api/journal', {
        method: editingEntryId ? 'PUT' : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
      });
      if (!response.ok) {
        const body = await response.json().catch(() => ({}));
        throw new Error(body.error || `HTTP ${response.status}`);
      }
      const created = await response.json();
      const hydrated = await hydrateEntryImages(created);
      setEntries((prev) => {
        const next = editingEntryId
          ? prev.map((entry) => (entry.id === editingEntryId ? hydrated : entry))
          : [hydrated, ...prev];
        next.sort((a, b) => (b.pickupDate || '').localeCompare(a.pickupDate || ''));
        return next;
      });
      resetForm();
    } catch (err) {
      setError(`Eintrag konnte nicht gespeichert werden: ${err.message}`);
    } finally {
      setSaving(false);
    }
  };

  const handleDeleteRequest = (entry) => {
    setDeleteDialog({ open: true, entry });
  };

  const handleDeleteConfirm = async () => {
    const entry = deleteDialog.entry;
    if (!entry?.id) {
      setDeleteDialog({ open: false, entry: null });
      return;
    }
    setError('');
    try {
      const response = await authorizedFetch(`/api/journal/${entry.id}`, { method: 'DELETE' });
      if (!response.ok) {
        const body = await response.json().catch(() => ({}));
        throw new Error(body.error || `HTTP ${response.status}`);
      }
      setEntries((prev) => {
        const target = prev.find((item) => item.id === entry.id);
        if (target) {
          releaseEntryImageUrls([target]);
        }
        return prev.filter((item) => item.id !== entry.id);
      });
      if (editingEntryId === entry.id) {
        resetForm();
      }
    } catch (err) {
      setError(`Eintrag konnte nicht gelöscht werden: ${err.message}`);
    } finally {
      setDeleteDialog({ open: false, entry: null });
    }
  };

  const handleEdit = (entry) => {
    setError('');
    images.forEach((image) => URL.revokeObjectURL(image.previewUrl));
    setImages([]);
    setEditingEntryId(entry.id);
    setEditingStoreLabel(entry.storeName || storeLabelMap.get(String(entry.storeId)) || '');
    setExistingImages(Array.isArray(entry.images) ? entry.images.map((image) => ({ ...image })) : []);
    setForm({
      storeId: entry.storeId ? String(entry.storeId) : '',
      pickupDate: entry.pickupDate || '',
      note: entry.note || '',
      reminderEnabled: entry.reminder?.enabled ?? true,
      reminderInterval: entry.reminder?.interval || 'yearly',
      reminderBeforeValue: getReminderOffset(entry.reminder).value,
      reminderBeforeUnit: getReminderOffset(entry.reminder).unit,
      reminderReferenceMode: getReminderReference(entry.reminder).mode,
      reminderReferenceEventKey: getReminderReference(entry.reminder).eventKey,
      reminderReferenceOffsetValue: getReminderReference(entry.reminder).occurrenceOffsetValue,
      reminderReferenceOffsetUnit: getReminderReference(entry.reminder).occurrenceOffsetUnit
    });
    setFormOpen(true);
  };

  const handleCreate = () => {
    setError('');
    setEditingStoreLabel('');
    resetForm();
    setFormOpen(true);
  };

  const showHoverPreview = useCallback((event, image, size) => {
    if (!image) {
      return;
    }
    const src = image.displayUrl || image.url;
    if (!src) {
      return;
    }
    const rect = event.currentTarget.getBoundingClientRect();
    const width = size?.width || 600;
    const height = size?.height || 450;
    const padding = 16;
    let left = rect.right + 12;
    let top = rect.top + rect.height / 2 - height / 2;

    if (left + width > window.innerWidth - padding) {
      left = rect.left - width - 12;
    }
    if (left < padding) {
      left = padding;
    }
    if (top < padding) {
      top = padding;
    }
    if (top + height > window.innerHeight - padding) {
      top = window.innerHeight - height - padding;
    }

    setHoverPreview({
      open: true,
      src,
      alt: image.originalName || 'Journalbild',
      left,
      top,
      width,
      height
    });
  }, []);

  const hideHoverPreview = useCallback(() => {
    setHoverPreview((prev) => (prev.open ? { ...prev, open: false } : prev));
  }, []);

  const removeExistingImage = (imageId) => {
    setExistingImages((prev) => prev.filter((image) => image.id !== imageId));
  };

  return (
    <div className="space-y-6">
      <div className={formOpen ? 'journal-content journal-content--blur' : 'journal-content'}>
        <div className="bg-white rounded-lg shadow p-6">
        <div className="flex flex-wrap items-center justify-between gap-3 mb-4">
          <h2 className="text-xl font-semibold text-gray-800">Journal-Einträge</h2>
          <div className="flex items-center gap-2">
            <button
              type="button"
              onClick={loadEntries}
              className="inline-flex items-center justify-center h-9 w-9 rounded-md border border-gray-200 text-gray-700 hover:bg-gray-50"
              disabled={loading}
              aria-label="Aktualisieren"
              title="Aktualisieren"
            >
              <svg viewBox="0 0 24 24" className="h-4 w-4" aria-hidden="true">
                <path
                  d="M12 5.25A6.75 6.75 0 1 1 6.07 8.5a.75.75 0 1 1 1.286.77A5.25 5.25 0 1 0 12 6.75h-1.94a.75.75 0 0 1 0-1.5H12z"
                  fill="currentColor"
                />
                <path
                  d="M12 3a.75.75 0 0 1 .75.75v2.69l1.72-1.72a.75.75 0 1 1 1.06 1.06l-3 3a.75.75 0 0 1-1.06 0l-3-3a.75.75 0 1 1 1.06-1.06l1.72 1.72V3.75A.75.75 0 0 1 12 3z"
                  fill="currentColor"
                />
              </svg>
            </button>
            <button
              type="button"
              onClick={handleCreate}
              className="inline-flex items-center justify-center h-9 w-9 rounded-md border border-blue-600 bg-blue-600 text-white hover:bg-blue-700"
              aria-label="Neuer Eintrag"
              title="Neuer Eintrag"
            >
              <svg viewBox="0 0 24 24" className="h-4 w-4" aria-hidden="true">
                <path
                  d="M12 5.25a.75.75 0 0 1 .75.75v5.25H18a.75.75 0 1 1 0 1.5h-5.25V18a.75.75 0 1 1-1.5 0v-5.25H6a.75.75 0 1 1 0-1.5h5.25V6a.75.75 0 0 1 .75-.75z"
                  fill="currentColor"
                />
              </svg>
            </button>
          </div>
        </div>
          {error ? (
            <div className="status-banner error mb-4">
              <p>{error}</p>
            </div>
          ) : null}
          {loading ? <p className="text-gray-500">Lade Einträge...</p> : null}
          {!loading && entries.length === 0 ? (
            <p className="text-gray-500">Noch keine Einträge vorhanden.</p>
          ) : null}
          <div className="mt-3 flex flex-wrap items-center gap-2 border border-gray-200 bg-gray-50 rounded-md px-3 py-2">
            <input
              type="text"
              value={filters.query}
              onChange={(event) => setFilters((prev) => ({ ...prev, query: event.target.value }))}
              placeholder="Suche..."
              className="min-w-[140px] flex-1 border border-gray-300 rounded-md px-3 py-2 text-sm"
            />
            <input
              type="date"
              value={filters.dateFrom}
              onChange={(event) => setFilters((prev) => ({ ...prev, dateFrom: event.target.value }))}
              className="min-w-[140px]"
            />
            <input
              type="date"
              value={filters.dateTo}
              onChange={(event) => setFilters((prev) => ({ ...prev, dateTo: event.target.value }))}
              className="min-w-[140px]"
            />
            <button
              type="button"
              onClick={() =>
                setFilters({
                  query: '',
                  storeId: '',
                  reminderOnly: false,
                  withImagesOnly: false,
                  dateFrom: '',
                  dateTo: ''
                })
              }
              className="text-sm px-3 py-2 border rounded-md hover:border-blue-400"
            >
              Reset
            </button>
            <select
              value={sortBy}
              onChange={(event) => setSortBy(event.target.value)}
              className="min-w-[160px] ml-auto"
            >
              <option value="pickupDateDesc">Abhol-Datum ↓</option>
              <option value="pickupDateAsc">Abhol-Datum ↑</option>
              <option value="createdAtDesc">Erstellt ↓</option>
              <option value="createdAtAsc">Erstellt ↑</option>
              <option value="storeNameAsc">Betrieb A–Z</option>
              <option value="storeNameDesc">Betrieb Z–A</option>
              <option value="nextReminderAsc">Nächste Erinnerung</option>
            </select>
          </div>
          <div className="space-y-4">
            {filteredEntries.map((entry) => {
              const reminder = entry.reminder || {};
              const reminderLabel = reminder.enabled
                ? `${intervalLabels[reminder.interval] || 'Jährlich'}, ${formatReminderOffset(reminder)} vorher, ${formatReferenceLabel(reminder)}`
                : 'Keine Erinnerung';
              const storeLabel =
                entry.storeName ||
                storeLabelMap.get(String(entry.storeId)) ||
                `Store ${entry.storeId}`;
              const mainImage = Array.isArray(entry.images) && entry.images.length > 0 ? entry.images[0] : null;
              return (
              <div key={entry.id} className="journal-entry-row border rounded-md">
                <div className="flex">
                  <div className="w-24 sm:w-28 md:w-32 bg-gray-100 flex-shrink-0">
                    {mainImage ? (
                      <div className="journal-image-hover">
                        <div className="h-full w-full overflow-hidden">
                          <img
                            src={mainImage.displayUrl || mainImage.url}
                            alt={mainImage.originalName || 'Journalbild'}
                            className="h-full w-full object-cover"
                            onMouseEnter={(event) =>
                              showHoverPreview(event, mainImage, { width: 720, height: 540 })
                            }
                            onMouseLeave={hideHoverPreview}
                          />
                        </div>
                      </div>
                    ) : (
                      <div className="h-full w-full flex items-center justify-center text-xs text-gray-400">
                        Kein Bild
                      </div>
                    )}
                    </div>
                    <div className="flex-1 p-4">
                      <div className="flex items-start justify-between gap-4">
                        <div>
                        <p className="text-sm text-gray-500">{entry.pickupDate}</p>
                        <h3 className="text-lg font-semibold text-gray-800">
                          {storeLabel}
                        </h3>
                        </div>
                      <div className="flex items-center gap-2">
                        <button
                          type="button"
                          onClick={() => handleEdit(entry)}
                          className="inline-flex items-center justify-center h-9 w-9 rounded-md border border-blue-200 text-blue-600 hover:bg-blue-50"
                          aria-label="Bearbeiten"
                          title="Bearbeiten"
                        >
                          <svg viewBox="0 0 24 24" className="h-4 w-4" aria-hidden="true">
                            <path
                              d="M16.862 3.487a1.75 1.75 0 0 1 2.475 2.475l-9.9 9.9a2.25 2.25 0 0 1-.878.537l-3.292 1.097a.75.75 0 0 1-.948-.948l1.097-3.292a2.25 2.25 0 0 1 .537-.878l9.9-9.9z"
                              fill="currentColor"
                            />
                            <path
                              d="M5 19.25c0-.414.336-.75.75-.75h12.5a.75.75 0 1 1 0 1.5H5.75a.75.75 0 0 1-.75-.75z"
                              fill="currentColor"
                            />
                          </svg>
                        </button>
                        <button
                          type="button"
                          onClick={() => handleDeleteRequest(entry)}
                          className="inline-flex items-center justify-center h-9 w-9 rounded-md border border-red-200 text-red-600 hover:bg-red-50"
                          aria-label="Löschen"
                          title="Löschen"
                        >
                          <svg viewBox="0 0 24 24" className="h-4 w-4" aria-hidden="true">
                            <path
                              d="M9 3.75A1.75 1.75 0 0 1 10.75 2h2.5A1.75 1.75 0 0 1 15 3.75V5h4a.75.75 0 0 1 0 1.5h-1.037l-1.05 12.1A2.25 2.25 0 0 1 14.67 20.75H9.33a2.25 2.25 0 0 1-2.243-2.15L6.037 6.5H5a.75.75 0 0 1 0-1.5h4V3.75zm1.5 1.25h3V3.75a.25.25 0 0 0-.25-.25h-2.5a.25.25 0 0 0-.25.25V5z"
                              fill="currentColor"
                            />
                            <path
                              d="M10 9.25a.75.75 0 0 1 .75.75v6a.75.75 0 1 1-1.5 0v-6a.75.75 0 0 1 .75-.75zm4 0a.75.75 0 0 1 .75.75v6a.75.75 0 1 1-1.5 0v-6a.75.75 0 0 1 .75-.75z"
                              fill="currentColor"
                            />
                          </svg>
                        </button>
                      </div>
                      </div>
                      {entry.note ? <p className="mt-2 text-sm text-gray-700">{entry.note}</p> : null}
                      <p className="mt-2 text-xs text-gray-500">{reminderLabel}</p>
                      {Array.isArray(entry.images) && entry.images.length > 1 ? (
                        <div className="mt-3 grid grid-cols-3 gap-2">
                          {entry.images.slice(1).map((image) => (
                            <div
                              key={image.id}
                              className="journal-image-hover journal-image-hover--grid border rounded-md"
                            >
                              <div className="overflow-hidden rounded-md">
                                <img
                                  src={image.displayUrl || image.url}
                                  alt={image.originalName || 'Journalbild'}
                                  className="h-24 w-full object-cover"
                              onMouseEnter={(event) =>
                                showHoverPreview(event, image, { width: 600, height: 450 })
                              }
                              onMouseLeave={hideHoverPreview}
                            />
                              </div>
                            </div>
                          ))}
                        </div>
                      ) : null}
                    </div>
                  </div>
                </div>
              );
            })}
            {!loading && entries.length > 0 && filteredEntries.length === 0 ? (
              <div className="text-sm text-gray-500">Keine Einträge für die aktuellen Filter.</div>
            ) : null}
          </div>
        </div>
      </div>
      {formOpen ? (
        <>
          <div
            className="fixed inset-0 z-40 bg-slate-900/60 backdrop-blur-sm"
            onMouseDown={resetForm}
          />
          <div
            className={`fixed inset-0 z-50 flex items-center justify-center p-4 ${closingForm ? 'journal-modal-wrap--closing' : 'journal-modal-wrap--open'}`}
            onMouseDown={(event) => {
              if (event.target === event.currentTarget) {
                resetForm();
              }
            }}
          >
            <div
              className={`journal-modal ${closingForm ? 'journal-modal--closing' : 'journal-modal--open'}`}
              onMouseDown={(event) => event.stopPropagation()}
            >
              <div className="flex items-center justify-between border-b px-6 py-4">
                <div>
                  <h2 className="text-lg font-semibold text-gray-800">
                    {editingEntryId ? 'Eintrag bearbeiten' : 'Neuer Eintrag'}
                  </h2>
                  <p className="text-sm text-gray-500">Abholung dokumentieren</p>
                </div>
                <button
                  type="button"
                  onClick={resetForm}
                  className="inline-flex items-center justify-center h-9 w-9 rounded-md border border-gray-200 text-gray-700 hover:bg-gray-50"
                  aria-label="Schließen"
                  title="Schließen"
                >
                  <svg viewBox="0 0 24 24" className="h-4 w-4" aria-hidden="true">
                    <path
                      d="M6.47 6.47a.75.75 0 0 1 1.06 0L12 10.94l4.47-4.47a.75.75 0 1 1 1.06 1.06L13.06 12l4.47 4.47a.75.75 0 1 1-1.06 1.06L12 13.06l-4.47 4.47a.75.75 0 1 1-1.06-1.06L10.94 12 6.47 7.53a.75.75 0 0 1 0-1.06z"
                      fill="currentColor"
                    />
                  </svg>
                </button>
              </div>
              <div className="px-6 py-6">
                {error ? (
                  <div className="status-banner error mb-4">
                    <p>{error}</p>
                  </div>
                ) : null}
                <form className="space-y-4" onSubmit={handleSubmit}>
                  <div className="space-y-2">
                    <label className="block text-sm font-medium text-gray-700" htmlFor="journal-store">
                      Betrieb auswählen
                    </label>
                    <select
                      id="journal-store"
                      value={form.storeId}
                      onChange={(event) => handleFormChange({ storeId: event.target.value })}
                      className="w-full"
                    >
                      <option value="">Bitte wählen</option>
                      {storeOptions.map((store) => (
                        <option key={store.id} value={store.id}>
                          {store.name || `Store ${store.id}`}
                        </option>
                      ))}
                    </select>
                  </div>
                  <div className="space-y-2">
                    <label className="block text-sm font-medium text-gray-700" htmlFor="journal-date">
                      Abholdatum
                    </label>
                    <input
                      id="journal-date"
                      type="date"
                      value={form.pickupDate}
                      onChange={(event) => handleFormChange({ pickupDate: event.target.value })}
                      className="w-full"
                    />
                  </div>
                  <div className="space-y-2">
                    <label className="block text-sm font-medium text-gray-700" htmlFor="journal-note">
                      Kommentar
                    </label>
                    <textarea
                      id="journal-note"
                      value={form.note}
                      onChange={(event) => handleFormChange({ note: event.target.value })}
                      className="w-full border border-gray-300 rounded-md p-3 text-sm"
                      rows={4}
                      placeholder="Freitext zur Abholung..."
                    />
                  </div>
                  <div className="space-y-2">
                    <label className="block text-sm font-medium text-gray-700" htmlFor="journal-images">
                      Bilder hochladen
                    </label>
                    <div className="flex flex-wrap items-center gap-3">
                      <label
                        htmlFor="journal-images"
                        className="inline-flex items-center px-3 py-2 border border-gray-300 rounded-md text-sm font-medium text-gray-700 bg-white hover:border-blue-400 cursor-pointer"
                      >
                        Dateien auswählen
                      </label>
                      <span className="text-xs text-gray-500">
                        {images.length > 0 ? `${images.length} Bild(er) ausgewählt` : 'Maximal 5 Bilder'}
                      </span>
                      <input
                        id="journal-images"
                        type="file"
                        accept="image/*"
                        multiple
                        onChange={handleImageChange}
                        className="hidden"
                      />
                    </div>
                    {existingImages.length > 0 ? (
                      <div className="grid grid-cols-3 gap-2">
                        {existingImages.map((image) => (
                          <div
                            key={image.id}
                            className="journal-image-hover journal-image-hover--grid border rounded-md p-1"
                          >
                            <div className="overflow-hidden rounded">
                              <img
                                src={image.displayUrl || image.url}
                                alt={image.originalName || 'Journalbild'}
                                className="h-20 w-full object-cover"
                                onMouseEnter={(event) =>
                                  showHoverPreview(event, image, { width: 720, height: 540 })
                                }
                                onMouseLeave={hideHoverPreview}
                              />
                            </div>
                            <button
                              type="button"
                              onClick={() => removeExistingImage(image.id)}
                              className="absolute top-1 right-1 bg-white/90 text-xs px-2 py-1 rounded shadow"
                            >
                              Entfernen
                            </button>
                          </div>
                        ))}
                      </div>
                    ) : null}
                    {images.length > 0 ? (
                      <div className="grid grid-cols-3 gap-2">
                        {images.map((image, index) => (
                          <div
                            key={`${image.name}-${index}`}
                            className="journal-image-hover journal-image-hover--grid border rounded-md p-1"
                          >
                            <div className="overflow-hidden rounded">
                              <img
                                src={image.previewUrl}
                                alt={image.name}
                                className="h-20 w-full object-cover"
                                onMouseEnter={(event) =>
                                  showHoverPreview(event, image, { width: 720, height: 540 })
                                }
                                onMouseLeave={hideHoverPreview}
                              />
                            </div>
                            <button
                              type="button"
                              onClick={() => removeImage(index)}
                              className="absolute top-1 right-1 bg-white/90 text-xs px-2 py-1 rounded shadow"
                            >
                              Entfernen
                            </button>
                          </div>
                        ))}
                      </div>
                    ) : null}
                  </div>
                  <div className="border rounded-md p-4 space-y-3 bg-gray-50">
                    <label className="flex items-center gap-2 text-sm font-medium text-gray-700">
                      <input
                        type="checkbox"
                        checked={form.reminderEnabled}
                        onChange={(event) => handleFormChange({ reminderEnabled: event.target.checked })}
                      />
                      Telegram-Erinnerung aktivieren
                    </label>
                    {form.reminderEnabled ? (
                      <>
                        <div className="grid gap-3 md:grid-cols-2">
                          <div className="space-y-1">
                            <label className="block text-sm text-gray-600">Intervall</label>
                            <select
                              value={form.reminderReferenceMode === 'event' ? 'yearly' : form.reminderInterval}
                              onChange={(event) => handleFormChange({ reminderInterval: event.target.value })}
                              disabled={form.reminderReferenceMode === 'event'}
                              className="w-full"
                            >
                              {Object.entries(intervalLabels).map(([value, label]) => (
                                <option key={value} value={value}>
                                  {label}
                                </option>
                              ))}
                            </select>
                          </div>
                          <div className="space-y-1">
                            <label className="block text-sm text-gray-600">Vorher</label>
                            <div className="flex gap-2">
                              <input
                                type="number"
                                min="0"
                                value={form.reminderBeforeValue}
                                onChange={(event) =>
                                  handleFormChange({ reminderBeforeValue: event.target.value })
                                }
                                className="w-24 border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-200"
                              />
                              <select
                                value={form.reminderBeforeUnit}
                                onChange={(event) =>
                                  handleFormChange({ reminderBeforeUnit: event.target.value })
                                }
                                className="flex-1"
                              >
                                {Object.entries(reminderUnitLabels).map(([value, label]) => (
                                  <option key={value} value={value}>
                                    {label}
                                  </option>
                                ))}
                              </select>
                            </div>
                          </div>
                        </div>
                        <div className="grid gap-3 md:grid-cols-2">
                          <div className="space-y-1">
                            <label className="block text-sm text-gray-600">Erinnerung basiert auf</label>
                            <select
                              value={form.reminderReferenceMode}
                              onChange={(event) =>
                                handleFormChange({
                                  reminderReferenceMode: event.target.value,
                                  reminderInterval: event.target.value === 'event' ? 'yearly' : form.reminderInterval
                                })
                              }
                              className="w-full"
                            >
                              <option value="pickupDate">Gespeichertem Abholdatum</option>
                              <option value="event">Referenz-Event</option>
                            </select>
                          </div>
                          {form.reminderReferenceMode === 'event' ? (
                            <div className="space-y-1">
                              <label className="block text-sm text-gray-600">Referenz-Event</label>
                              <select
                                value={form.reminderReferenceEventKey}
                                onChange={(event) => handleFormChange({ reminderReferenceEventKey: event.target.value })}
                                className="w-full"
                              >
                                {referenceEventOptions.map((option) => (
                                  <option key={option.value} value={option.value}>
                                    {option.label}
                                  </option>
                                ))}
                              </select>
                            </div>
                          ) : null}
                        </div>
                        {form.reminderReferenceMode === 'event' ? (
                          <div className="space-y-1">
                            <label className="block text-sm text-gray-600">Abholung relativ zum Event</label>
                            <div className="flex gap-2">
                              <input
                                type="number"
                                value={form.reminderReferenceOffsetValue}
                                onChange={(event) =>
                                  handleFormChange({ reminderReferenceOffsetValue: event.target.value })
                                }
                                className="w-24 border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-200"
                              />
                              <select
                                value={form.reminderReferenceOffsetUnit}
                                onChange={(event) =>
                                  handleFormChange({ reminderReferenceOffsetUnit: event.target.value })
                                }
                                className="flex-1"
                              >
                                {Object.entries(reminderUnitLabels).map(([value, label]) => (
                                  <option key={value} value={value}>
                                    {label}
                                  </option>
                                ))}
                              </select>
                            </div>
                            <p className="text-xs text-gray-500">
                              Positive Werte liegen nach dem Event, negative davor. Beispiel: 2 Wochen nach Ostern oder -4 Wochen vor Ostern.
                            </p>
                          </div>
                        ) : null}
                        <p className="text-xs text-gray-500">
                          Bei Referenz-Events wird die Erinnerung immer jährlich berechnet.
                        </p>
                        {reminderPreview ? (
                          <div className="rounded-md border border-blue-200 bg-blue-50 px-3 py-3 text-sm text-blue-900">
                            <p>
                              Geplante Abholung: <strong>{reminderPreview.occurrenceLabel}</strong>
                            </p>
                            <p>
                              Erinnerung kommt am: <strong>{reminderPreview.reminderLabel}</strong>
                            </p>
                          </div>
                        ) : null}
                      </>
                    ) : null}
                  </div>
                  <div className="grid gap-3 md:grid-cols-2">
                    <button
                      type="submit"
                      className="w-full bg-blue-600 text-white py-2 rounded-md hover:bg-blue-700 disabled:opacity-60"
                      disabled={saving}
                    >
                      {saving ? 'Speichere...' : editingEntryId ? 'Änderungen speichern' : 'Eintrag speichern'}
                    </button>
                    <button
                      type="button"
                      className="w-full border border-gray-300 text-gray-700 py-2 rounded-md hover:border-blue-400"
                      onClick={resetForm}
                    >
                      Abbrechen
                    </button>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </>
      ) : null}
      <ConfirmationDialog
        open={deleteDialog.open}
        title="Eintrag löschen"
        message={`Soll der Eintrag${deleteDialog.entry?.storeName ? ` für "${deleteDialog.entry.storeName}"` : ''} wirklich gelöscht werden?`}
        confirmLabel="Löschen"
        cancelLabel="Abbrechen"
        confirmTone="danger"
        onConfirm={handleDeleteConfirm}
        onCancel={() => setDeleteDialog({ open: false, entry: null })}
      />
      {hoverPreview.open ? (
        <div
          className="journal-hover-preview journal-hover-preview--open"
          style={{
            left: `${hoverPreview.left}px`,
            top: `${hoverPreview.top}px`,
            width: `${hoverPreview.width}px`,
            height: `${hoverPreview.height}px`
          }}
        >
          <img src={hoverPreview.src} alt={hoverPreview.alt} />
        </div>
      ) : null}
    </div>
  );
};

export default JournalPage;
