/**
 * Calendar page - 3-column explorer-style layout.
 *
 * Left: CalendarTree (calendar selection + visibility)
 * Middle: Calendar view (Day / Week / Month / Range) with date controls
 * Right: CalendarDetail (selected entry details + subtasks)
 *
 * Uses PluginToolbar for actions, ResizablePanel for desktop layout.
 */

import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ResizablePanel } from '@/components/ui/ResizablePanel';
import { ConfirmDialog } from '@/components/ui/ConfirmDialog';
import { useToast } from '@/components/ui/Toast';
import { CalendarTree } from '@/components/calendar/CalendarTree';
import { MonthView } from '@/components/calendar/MonthView';
import { WeekView } from '@/components/calendar/WeekView';
import { DayView } from '@/components/calendar/DayView';
import { RangeView } from '@/components/calendar/RangeView';
import { formatDateInput } from '@/utils/date';
import { CalendarDetail } from '@/components/calendar/CalendarDetail';
import { AppointmentModal } from '@/components/calendar/AppointmentModal';
import { IcsControls } from '@/components/calendar/IcsControls';
import { SharingSettings } from '@/components/calendar/SharingSettings';
import { useCalendarStore, type CalendarViewMode } from '@/store/calendarStore';
import { usePluginToolbarStore } from '@/store/pluginToolbarStore';
import { ChevronLeft, ChevronRight, Info, Plus } from 'lucide-react';
import {
  fetchCalendars,
  createCalendar,
  listEntries,
  updateEntry,
  deleteEntry,
  type Calendar,
  type CalendarEntry,
} from '@/api/calendar';

export function CalendarPage() {
  const { t } = useTranslation();
  const toast = useToast();

  const {
    viewMode,
    setViewMode,
    visibleMonth,
    visibleWeek,
    visibleDay,
    rangeStart,
    rangeEnd,
    setRangeStart,
    setRangeEnd,
    goToNextMonth,
    goToPrevMonth,
    goToNextWeek,
    goToPrevWeek,
    goToNextDay,
    goToPrevDay,
    goToToday,
    activeCalendarId,
    setActiveCalendarId,
    calendars,
    setCalendars,
    selectedEntry,
    setSelectedEntry,
    visibleCalendarIds,
    toggleCalendarVisibility,
  } = useCalendarStore();

  const [entries, setEntries] = useState<CalendarEntry[]>([]);
  const [loading, setLoading] = useState(false);
  const [loadingCalendars, setLoadingCalendars] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [modalOpen, setModalOpen] = useState(false);
  const [modalEntry, setModalEntry] = useState<CalendarEntry | null>(null);
  const [prefillDate, setPrefillDate] = useState<Date | null>(null);

  const [showSharing, setShowSharing] = useState(false);
  const [showIcs, setShowIcs] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<CalendarEntry | null>(null);
  const [showDetails, setShowDetails] = useState(true);

  // Mobile view state
  const [activeView, setActiveView] = useState<'tree' | 'calendar' | 'details'>('tree');

  // Load calendars once
  useEffect(() => {
    let cancelled = false;
    setLoadingCalendars(true);
    fetchCalendars()
      .then((list) => {
        if (cancelled) return;
        setCalendars(list);
        if (!activeCalendarId && list.length > 0) {
          setActiveCalendarId(list[0].id);
        }
      })
      .catch((e: Error) => {
        if (!cancelled) setError(e.message);
      })
      .finally(() => {
        if (!cancelled) setLoadingCalendars(false);
      });
    return () => {
      cancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Compute date range based on viewMode
  const range = useMemo(() => {
    if (viewMode === 'month') {
      const first = new Date(visibleMonth.getFullYear(), visibleMonth.getMonth(), 1);
      const dayOfWeek = (first.getDay() + 6) % 7;
      const start = new Date(first);
      start.setDate(first.getDate() - dayOfWeek);
      start.setHours(0, 0, 0, 0);
      const end = new Date(start);
      end.setDate(start.getDate() + 42);
      return { start, end };
    }
    if (viewMode === 'week') {
      const start = new Date(visibleWeek);
      start.setHours(0, 0, 0, 0);
      const end = new Date(start);
      end.setDate(start.getDate() + 7);
      return { start, end };
    }
    if (viewMode === 'day') {
      const start = new Date(visibleDay);
      start.setHours(0, 0, 0, 0);
      const end = new Date(start);
      end.setDate(start.getDate() + 1);
      return { start, end };
    }
    // range
    const start = rangeStart ? new Date(rangeStart) : new Date();
    start.setHours(0, 0, 0, 0);
    const end = rangeEnd ? new Date(rangeEnd) : new Date(start);
    end.setHours(23, 59, 59, 999);
    end.setDate(end.getDate() + 1);
    return { start, end };
  }, [viewMode, visibleMonth, visibleWeek, visibleDay, rangeStart, rangeEnd]);

  const loadEntries = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const list = await listEntries({
        start: range.start.toISOString(),
        end: range.end.toISOString(),
      });
      setEntries(list);
    } catch (e) {
      setError((e as Error).message ?? t('calendar.errorLoad'));
    } finally {
      setLoading(false);
    }
  }, [range.start, range.end, t]);

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

  // Filter entries by visible calendars
  const filteredEntries = useMemo(() => {
    if (visibleCalendarIds.size === 0) return entries;
    return entries.filter((e) => visibleCalendarIds.has(e.calendar_id));
  }, [entries, visibleCalendarIds]);

  const activeCalendar = calendars.find((c) => c.id === activeCalendarId) ?? null;
  const selectedCalendar = selectedEntry
    ? calendars.find((c) => c.id === selectedEntry.calendar_id) ?? null
    : null;

  // ??? Handlers ???????????????????????????????????????????????????????????

  const handleCreateAt = useCallback((date: Date) => {
    setModalEntry(null);
    setPrefillDate(date);
    setModalOpen(true);
  }, []);

  const handleEditEntry = useCallback(
    (entry: CalendarEntry) => {
      setSelectedEntry(entry);
      if (showDetails) {
        setActiveView('details');
      }
    },
    [setSelectedEntry, showDetails],
  );

  const handleOpenEditModal = useCallback(() => {
    if (!selectedEntry) return;
    setModalEntry(selectedEntry);
    setPrefillDate(null);
    setModalOpen(true);
  }, [selectedEntry]);

  const handleMoveEntry = useCallback(
    async (entry: CalendarEntry, newStart: Date) => {
      try {
        const oldEnd = entry.end_at ? new Date(entry.end_at) : null;
        const oldStart = entry.start_at ? new Date(entry.start_at) : null;
        const durationMs =
          oldStart && oldEnd ? oldEnd.getTime() - oldStart.getTime() : 60 * 60 * 1000;
        const newEnd = new Date(newStart.getTime() + durationMs);
        const updated = await updateEntry(entry.id, {
          start_at: newStart.toISOString(),
          end_at: newEnd.toISOString(),
        });
        setEntries((cur) => cur.map((e) => (e.id === updated.id ? updated : e)));
        if (selectedEntry?.id === updated.id) {
          setSelectedEntry(updated);
        }
      } catch (e) {
        setError((e as Error).message ?? t('calendar.errorSave'));
        await loadEntries();
      }
    },
    [t, loadEntries, selectedEntry, setSelectedEntry],
  );

  const handleSaved = useCallback(
    (saved: CalendarEntry) => {
      setEntries((cur) => {
        const exists = cur.some((e) => e.id === saved.id);
        return exists ? cur.map((e) => (e.id === saved.id ? saved : e)) : [...cur, saved];
      });
      if (selectedEntry?.id === saved.id) {
        setSelectedEntry(saved);
      }
    },
    [selectedEntry, setSelectedEntry],
  );

  const handleDeleted = useCallback(
    (entryId: string) => {
      setEntries((cur) => cur.filter((e) => e.id !== entryId));
      if (selectedEntry?.id === entryId) {
        setSelectedEntry(null);
      }
    },
    [selectedEntry, setSelectedEntry],
  );

  const handleConfirmDelete = useCallback(async () => {
    if (!deleteTarget) return;
    try {
      await deleteEntry(deleteTarget.id);
      toast.success(t('calendar.detail.delete'));
      handleDeleted(deleteTarget.id);
      setDeleteTarget(null);
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      toast.error(msg);
    }
  }, [deleteTarget, handleDeleted, toast, t]);

  const handleDeleteFromDetail = useCallback(() => {
    if (!selectedEntry) return;
    setDeleteTarget(selectedEntry);
  }, [selectedEntry]);

  const handleEntryChanged = useCallback(
    (updated: CalendarEntry) => {
      setEntries((cur) => cur.map((e) => (e.id === updated.id ? updated : e)));
      if (selectedEntry?.id === updated.id) {
        setSelectedEntry(updated);
      }
    },
    [selectedEntry, setSelectedEntry],
  );

  const handleCreateCalendar = useCallback(async () => {
    const name = window.prompt(t('calendar.tree.newCalendar'));
    if (!name?.trim()) return;
    try {
      const created = await createCalendar({ name: name.trim() });
      setCalendars([...calendars, created]);
      setActiveCalendarId(created.id);
      toast.success(t('calendar.tree.newCalendar'));
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      toast.error(msg);
    }
  }, [t, toast, setCalendars, setActiveCalendarId, calendars]);

  const handleSelectCalendar = useCallback(
    (id: string) => {
      setActiveCalendarId(id);
      setActiveView('calendar');
    },
    [setActiveCalendarId],
  );

  // ??? Toolbar registration ???????????????????????????????????????????????

  const registerItems = usePluginToolbarStore((s) => s.registerItems);
  const unregisterPlugin = usePluginToolbarStore((s) => s.unregisterPlugin);

  useEffect(() => {
    const items = [
      // Navigation group
      {
        id: 'nav-prev',
        plugin: 'calendar',
        label: t('calendar.navigation.prev'),
        group: 'navigation',
        onClick:
          viewMode === 'month'
            ? goToPrevMonth
            : viewMode === 'week'             ? goToPrevWeek
              : viewMode === 'day'               ? goToPrevDay
                : () => {},
        icon: (
          <ChevronLeft className="w-3.5 h-3.5" strokeWidth={2} />
        ),
      },
      {
        id: 'nav-today',
        plugin: 'calendar',
        label: t('calendar.navigation.today'),
        group: 'navigation',
        onClick: goToToday,
      },
      {
        id: 'nav-next',
        plugin: 'calendar',
        label: t('calendar.navigation.next'),
        group: 'navigation',
        onClick:
          viewMode === 'month'
            ? goToNextMonth
            : viewMode === 'week'
              ? goToNextWeek
              : viewMode === 'day'
                ? goToNextDay
                : () => {},
        icon: (
          <ChevronRight className="w-3.5 h-3.5" strokeWidth={2} />
        ),
      },
      // View mode group
      {
        id: 'view-mode',
        plugin: 'calendar',
        label: t('calendar.viewMonth'),
        group: 'view-mode',
        type: 'select' as const,
        selectValue: viewMode,
        selectOptions: [
          { value: 'day', label: t('calendar.viewDay') },
          { value: 'week', label: t('calendar.viewWeek') },
          { value: 'month', label: t('calendar.viewMonth') },
          { value: 'range', label: t('calendar.viewRange') },
        ],
        onSelect: (value: string) => setViewMode(value as CalendarViewMode),
        onClick: () => {},
      },
      // Actions group
      {
        id: 'new-appointment',
        plugin: 'calendar',
        label: t('calendar.newAppointment'),
        group: 'actions',
        onClick: () => {
          setModalEntry(null);
          setPrefillDate(null);
          setModalOpen(true);
        },
        icon: (
          <Plus className="w-3.5 h-3.5" strokeWidth={2} />
        ),
      },
      {
        id: 'ics-import',
        plugin: 'calendar',
        label: t('calendar.ics.import'),
        group: 'actions',
        onClick: () => setShowIcs((v) => !v),
      },
      {
        id: 'ics-export',
        plugin: 'calendar',
        label: t('calendar.ics.export'),
        group: 'actions',
        onClick: () => setShowIcs((v) => !v),
      },
      // Details toggle group
      {
        id: 'toggle-details',
        plugin: 'calendar',
        label: t('calendar.detail.title'),
        group: 'details',
        active: showDetails,
        onClick: () => setShowDetails((v) => !v),
        icon: (
          <Info className="w-3.5 h-3.5" strokeWidth={2} />
        ),
      },
    ];

    registerItems('calendar', items);
    return () => unregisterPlugin('calendar');
  }, [
    viewMode,
    showDetails,
    goToPrevMonth,
    goToNextMonth,
    goToPrevWeek,
    goToNextWeek,
    goToPrevDay,
    goToNextDay,
    goToToday,
    setViewMode,
    registerItems,
    unregisterPlugin,
    t,
  ]);

  // ??? Render ?????????????????????????????????????????????????????????????

  const renderCalendarView = () => {
    if (calendars.length === 0 && !loading) {
      return (
        <div className="flex items-center justify-center h-full p-6" data-testid="calendar-empty">
          <div className="text-center">
            <p className="text-sm font-medium text-secondary-600">{t('calendar.noCalendars')}</p>
            <p className="mt-1 text-xs text-secondary-400">{t('calendar.noEntries')}</p>
          </div>
        </div>
      );
    }

    switch (viewMode) {
      case 'day':
        return (
          <DayView
            visibleDay={visibleDay}
            entries={filteredEntries}
            loading={loading}
            onCreateAt={handleCreateAt}
            onEditEntry={handleEditEntry}
            onMoveEntry={handleMoveEntry}
          />
        );
      case 'week':
        return (
          <WeekView
            visibleWeek={visibleWeek}
            entries={filteredEntries}
            loading={loading}
            onCreateAt={handleCreateAt}
            onEditEntry={handleEditEntry}
            onMoveEntry={handleMoveEntry}
          />
        );
      case 'range':
        return (
          <RangeView
            rangeStart={rangeStart ?? new Date()}
            rangeEnd={rangeEnd ?? new Date()}
            entries={filteredEntries}
            loading={loading}
            onEditEntry={handleEditEntry}
          />
        );
      default:
        return (
          <MonthView
            visibleMonth={visibleMonth}
            entries={filteredEntries}
            loading={loading}
            onCreateAt={handleCreateAt}
            onEditEntry={handleEditEntry}
            onMoveEntry={handleMoveEntry}
          />
        );
    }
  };

  const renderRangeControls = () => {
    if (viewMode !== 'range') return null;
    return (
      <div className="flex items-center gap-2 px-4 py-2 border-b border-secondary-200 bg-secondary-50">
        <label className="text-xs text-secondary-600">{t('calendar.range.start')}</label>
        <input
          type="date"
          value={rangeStart ? formatDateInput(rangeStart) : ''}
          onChange={(e) => setRangeStart(e.target.value ? new Date(e.target.value) : null)}
          className="text-sm rounded-md border border-secondary-300 px-2 py-1"
          data-testid="calendar-range-start"
        />
        <label className="text-xs text-secondary-600">{t('calendar.range.end')}</label>
        <input
          type="date"
          value={rangeEnd ? formatDateInput(rangeEnd) : ''}
          onChange={(e) => setRangeEnd(e.target.value ? new Date(e.target.value) : null)}
          className="text-sm rounded-md border border-secondary-300 px-2 py-1"
          data-testid="calendar-range-end"
        />
      </div>
    );
  };

  return (
    <div className="flex flex-col h-full" data-testid="calendar-page">
      {error && (
        <div className="mb-2 p-3 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="calendar-error">
          <p className="text-sm text-danger-700">{error}</p>
        </div>
      )}

      {/* ICS controls panel */}
      {showIcs && (
        <div className="mb-2 p-3 bg-secondary-50 border-b border-secondary-200" data-testid="calendar-ics-panel">
          <IcsControls calendar={activeCalendar} onImported={() => void loadEntries()} />
        </div>
      )}

      {/* Sharing settings panel */}
      {showSharing && activeCalendar && (
        <div className="mb-2 p-3 bg-secondary-50 border-b border-secondary-200" data-testid="calendar-sharing-panel">
          <SharingSettings calendar={activeCalendar} />
        </div>
      )}

      {/* Desktop: three-pane layout with resizable panels */}
      <div className="hidden md:flex flex-1 overflow-hidden">
        {/* Left: CalendarTree */}
        <ResizablePanel
          initialWidth={240}
          minWidth={180}
          maxWidth={400}
          className="border-r border-secondary-200 bg-white"
          data-testid="calendar-tree-pane"
        >
          <CalendarTree
            calendars={calendars}
            activeCalendarId={activeCalendarId}
            visibleCalendarIds={visibleCalendarIds}
            onSelect={handleSelectCalendar}
            onToggleVisibility={toggleCalendarVisibility}
            onCreate={handleCreateCalendar}
            loading={loadingCalendars}
          />
        </ResizablePanel>

        {/* Middle: Calendar view */}
        <ResizablePanel
          resizable={false}
          className="bg-white"
          data-testid="calendar-view-pane"
        >
          <div className="flex flex-col h-full">
            {renderRangeControls()}
            <div className="flex-1 overflow-hidden">{renderCalendarView()}</div>
          </div>
        </ResizablePanel>

        {/* Right: CalendarDetail (only when toggled on) */}
        {showDetails && (
          <ResizablePanel
            initialWidth={300}
            minWidth={200}
            maxWidth={450}
            handleSide="left"
            className="border-l border-secondary-200 bg-white"
            data-testid="calendar-detail-pane"
          >
            <CalendarDetail
              entry={selectedEntry}
              calendar={selectedCalendar}
              onEdit={handleOpenEditModal}
              onDelete={handleDeleteFromDetail}
              onClose={() => {
                setSelectedEntry(null);
                setShowDetails(false);
              }}
              onEntryChanged={handleEntryChanged}
            />
          </ResizablePanel>
        )}
      </div>

      {/* Mobile: single-pane view switching */}
      <div className="flex md:hidden flex-1 overflow-hidden flex-col">
        {/* View 1: CalendarTree */}
        {activeView === 'tree' && (
          <div className="flex-1 overflow-y-auto bg-white" data-testid="mobile-calendar-tree-pane">
            <div className="flex items-center gap-2 px-3 py-2 border-b border-secondary-200 sticky top-0 bg-white z-10">
              <h2 className="text-sm font-semibold text-secondary-900">{t('calendar.tree.title')}</h2>
              <button
                onClick={() => setActiveView('calendar')}
                className="ml-auto inline-flex items-center gap-1 px-2 py-1 rounded text-sm text-secondary-700 hover:bg-secondary-100 min-h-touch"
                aria-label={t('calendar.title')}
                data-testid="mobile-go-to-calendar"
              >
                <span className="text-sm font-medium">{t('calendar.title')}</span>
                <ChevronRight className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
              </button>
            </div>
            <CalendarTree
              calendars={calendars}
              activeCalendarId={activeCalendarId}
              visibleCalendarIds={visibleCalendarIds}
              onSelect={handleSelectCalendar}
              onToggleVisibility={toggleCalendarVisibility}
              onCreate={handleCreateCalendar}
              loading={loadingCalendars}
            />
          </div>
        )}

        {/* View 2: Calendar */}
        {activeView === 'calendar' && (
          <div className="flex-1 overflow-hidden bg-white flex flex-col" data-testid="mobile-calendar-view-pane">
            <div className="flex items-center gap-2 px-3 py-2 border-b border-secondary-200 sticky top-0 bg-white z-10">
              <button
                onClick={() => setActiveView('tree')}
                className="inline-flex items-center gap-1 px-2 py-1 rounded text-sm text-secondary-700 hover:bg-secondary-100 min-h-touch"
                aria-label={t('common.back')}
                data-testid="mobile-back-to-tree"
              >
                <ChevronLeft className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
                <span className="text-sm font-medium">{t('calendar.tree.title')}</span>
              </button>
              {showDetails && (
                <button
                  onClick={() => setActiveView('details')}
                  className="ml-auto inline-flex items-center gap-1 px-2 py-1 rounded text-sm text-secondary-700 hover:bg-secondary-100 min-h-touch"
                  aria-label={t('calendar.detail.title')}
                  data-testid="mobile-go-to-details"
                >
                  <span className="text-sm font-medium">{t('calendar.detail.title')}</span>
                  <ChevronRight className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
                </button>
              )}
            </div>
            {renderRangeControls()}
            <div className="flex-1 overflow-hidden">{renderCalendarView()}</div>
          </div>
        )}

        {/* View 3: CalendarDetail */}
        {activeView === 'details' && showDetails && (
          <div className="flex-1 overflow-y-auto bg-white" data-testid="mobile-calendar-detail-pane">
            <div className="flex items-center gap-2 px-3 py-2 border-b border-secondary-200 sticky top-0 bg-white z-10">
              <button
                onClick={() => setActiveView('calendar')}
                className="inline-flex items-center gap-1 px-2 py-1 rounded text-sm text-secondary-700 hover:bg-secondary-100 min-h-touch"
                aria-label={t('common.back')}
                data-testid="mobile-back-to-calendar"
              >
                <ChevronLeft className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
                <span className="text-sm font-medium">{t('calendar.title')}</span>
              </button>
            </div>
            <CalendarDetail
              entry={selectedEntry}
              calendar={selectedCalendar}
              onEdit={handleOpenEditModal}
              onDelete={handleDeleteFromDetail}
              onClose={() => {
                setSelectedEntry(null);
                setActiveView('calendar');
              }}
              onEntryChanged={handleEntryChanged}
            />
          </div>
        )}
      </div>

      {/* Delete confirmation */}
      <ConfirmDialog
        open={!!deleteTarget}
        title={t('calendar.detail.delete')}
        message={t('calendar.confirmDelete')}
        confirmLabel={t('common.delete')}
        variant="danger"
        onConfirm={handleConfirmDelete}
        onCancel={() => setDeleteTarget(null)}
      />

      {/* Appointment modal */}
      <AppointmentModal
        open={modalOpen}
        onClose={() => setModalOpen(false)}
        entry={modalEntry}
        prefillDate={prefillDate}
        calendars={calendars}
        defaultCalendarId={activeCalendarId}
        onSaved={handleSaved}
        onDeleted={handleDeleted}
      />
    </div>
  );
}

export default CalendarPage;
