import { computed, ref } from 'vue';
import type { Dayjs } from 'dayjs';
import { getLocalizedDayJs } from '../utils/time';
import { getWeekStartDayNumber } from '../utils/settings';

export function useCalendarNavigation(callbacks: {
    onDatesChange: (payload: { start: Dayjs; end: Dayjs }) => void;
    scrollToCurrentTime: () => void;
    initialDate?: Dayjs | null;
}) {
    const activeView = ref('timeGridWeek');
    const currentDate = ref(callbacks.initialDate ?? getLocalizedDayJs());

    function getFirstDay(): number {
        return getWeekStartDayNumber();
    }

    const viewDays = computed<Dayjs[]>(() => {
        const numDays = activeView.value === 'timeGridWeek' ? 7 : 1;

        if (numDays === 1) {
            return [currentDate.value.startOf('day')];
        }

        const firstDay = getFirstDay();
        const today = currentDate.value.startOf('day');
        const offset = (today.day() - firstDay + 7) % 7;
        const weekStart = today.subtract(offset, 'day');

        const days: Dayjs[] = [];
        for (let i = 0; i < numDays; i++) {
            days.push(weekStart.add(i, 'day'));
        }
        return days;
    });

    const viewTitle = computed(() => {
        if (activeView.value === 'timeGridDay') {
            return currentDate.value.format('MMMM YYYY');
        }

        const days = viewDays.value;
        if (days.length === 0) return '';

        const first = days[0]!;
        const last = days[days.length - 1]!;

        if (first.year() !== last.year()) {
            return `${first.format('MMM YYYY')} \u2013 ${last.format('MMM YYYY')}`;
        }
        if (first.month() !== last.month()) {
            return `${first.format('MMM')} \u2013 ${last.format('MMM YYYY')}`;
        }
        return first.format('MMMM YYYY');
    });

    function emitDatesChange() {
        const days = viewDays.value;
        if (days.length === 0) return;

        const start = days[0]!;
        const end = days[days.length - 1]!.add(1, 'day');
        callbacks.onDatesChange({ start, end });
    }

    function handlePrev() {
        if (activeView.value === 'timeGridWeek') {
            currentDate.value = currentDate.value.subtract(7, 'day');
        } else {
            currentDate.value = currentDate.value.subtract(1, 'day');
        }
        emitDatesChange();
        callbacks.scrollToCurrentTime();
    }

    function handleNext() {
        if (activeView.value === 'timeGridWeek') {
            currentDate.value = currentDate.value.add(7, 'day');
        } else {
            currentDate.value = currentDate.value.add(1, 'day');
        }
        emitDatesChange();
        callbacks.scrollToCurrentTime();
    }

    function handleToday() {
        currentDate.value = getLocalizedDayJs();
        emitDatesChange();
        callbacks.scrollToCurrentTime();
    }

    function handleChangeView(view: string) {
        activeView.value = view;
        emitDatesChange();
        callbacks.scrollToCurrentTime();
    }

    return {
        activeView,
        currentDate,
        viewDays,
        viewTitle,
        emitDatesChange,
        handlePrev,
        handleNext,
        handleToday,
        handleChangeView,
    };
}
