<script setup>
    import { computed, ref } from 'vue';
    import { useI18n } from 'vue-i18n';
    import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
    import { useWorkspaceStore } from '@/features/workspaces/stores/workspaceStore.js';
    import { useCampaignsStore } from '@/features/campaigns/stores/campaignsStore.js';
    import { useContentItemsStore } from '@/features/content/stores/contentItemsStore.js';

    const { t, locale } = useI18n();
    const workspaceStore = useWorkspaceStore();
    const campaignsStore = useCampaignsStore();
    const contentItemsStore = useContentItemsStore();

    const today = startOfDay(new Date());
    const viewMode = ref('month');
    const cursorDate = ref(today);

    const contentStatusMeta = {
        Draft: { tone: 'production', readiness: 'building' },
        'In production': { tone: 'production', readiness: 'building' },
        'In approval': { tone: 'approval', readiness: 'approval' },
        Approved: { tone: 'ready', readiness: 'ready' },
        Scheduled: { tone: 'ready', readiness: 'scheduled' },
        Published: { tone: 'published', readiness: 'published' },
    };

    const contentItemsByCampaignId = computed(() => {
        const grouped = new Map();

        for (const item of contentItemsStore.items) {
            const existing = grouped.get(item.campaignId) ?? [];
            existing.push(item);
            grouped.set(item.campaignId, existing);
        }

        return grouped;
    });

    const calendarEntries = computed(() => {
        const campaignEntries = campaignsStore.campaigns
            .filter(campaign => campaign.endDate || campaign.startDate)
            .map(campaign => buildCampaignEntry(campaign));

        const contentEntries = contentItemsStore.items
            .filter(item => item.dueDate)
            .map(item => buildContentEntry(item));

        return [...campaignEntries, ...contentEntries].sort(sortByDate);
    });

    const entriesByDay = computed(() => {
        const grouped = new Map();

        for (const entry of calendarEntries.value) {
            const existing = grouped.get(entry.dayKey) ?? [];
            existing.push(entry);
            grouped.set(entry.dayKey, existing);
        }

        return grouped;
    });

    const visibleDays = computed(() => {
        if (viewMode.value === 'week') {
            const start = startOfWeek(cursorDate.value);
            return Array.from({ length: 7 }, (_, index) => {
                const date = addDays(start, index);

                return buildDay(date, false);
            });
        }

        const start = startOfWeek(startOfMonth(cursorDate.value));
        const end = endOfWeek(endOfMonth(cursorDate.value));
        const days = [];
        let current = start;

        while (current <= end) {
            days.push(buildDay(current, current.getMonth() !== cursorDate.value.getMonth()));
            current = addDays(current, 1);
        }

        return days;
    });

    const weekdayLabels = computed(() => {
        const base = startOfWeek(cursorDate.value);

        return Array.from({ length: 7 }, (_, index) =>
            new Intl.DateTimeFormat(locale.value, { weekday: 'short' }).format(addDays(base, index))
        );
    });

    const periodLabel = computed(() => {
        if (viewMode.value === 'week') {
            const start = startOfWeek(cursorDate.value);
            const end = addDays(start, 6);
            const sameMonth = start.getMonth() === end.getMonth() && start.getFullYear() === end.getFullYear();

            if (sameMonth) {
                return new Intl.DateTimeFormat(locale.value, {
                    month: 'long',
                    day: 'numeric',
                    year: 'numeric',
                }).formatRange(start, end);
            }

            return new Intl.DateTimeFormat(locale.value, {
                month: 'short',
                day: 'numeric',
                year: 'numeric',
            }).formatRange(start, end);
        }

        return new Intl.DateTimeFormat(locale.value, {
            month: 'long',
            year: 'numeric',
        }).format(cursorDate.value);
    });

    const isLoading = computed(() =>
        workspaceStore.isLoading || campaignsStore.isLoading || contentItemsStore.isLoading
    );

    const pageError = computed(() =>
        workspaceStore.error || campaignsStore.error || contentItemsStore.error
    );

    function buildDay(date, isOutsideMonth) {
        const key = dateKey(date);

        return {
            key,
            date,
            entries: entriesByDay.value.get(key) ?? [],
            isOutsideMonth,
            isToday: key === dateKey(today),
        };
    }

    function buildContentEntry(item) {
        const statusMeta = contentStatusMeta[item.status] ?? { tone: 'production', readiness: 'building' };
        const campaign = campaignsStore.campaigns.find(candidate => candidate.id === item.campaignId);

        return {
            id: item.id,
            type: 'content',
            title: item.title,
            subtitle: campaign?.name ?? t('dashboard.labels.unassignedCampaign'),
            scheduledAt: new Date(item.dueDate),
            dayKey: dateKey(item.dueDate),
            timeLabel: formatHour(item.dueDate),
            tone: statusMeta.tone,
            route: { name: 'content-item-detail', params: { id: item.id } },
        };
    }

    function buildCampaignEntry(campaign) {
        const campaignItems = contentItemsByCampaignId.value.get(campaign.id) ?? [];
        const approvedCount = campaignItems.filter(item => ['Approved', 'Scheduled', 'Published'].includes(item.status)).length;

        return {
            id: campaign.id,
            type: 'campaign',
            title: campaign.name,
            subtitle: campaignItems.length
                ? t('dashboard.campaignProgress', { scheduled: campaignItems.length, approved: approvedCount })
                : t('dashboard.readiness.missing'),
            scheduledAt: new Date(campaign.endDate ?? campaign.startDate),
            dayKey: dateKey(campaign.endDate ?? campaign.startDate),
            timeLabel: t('dashboard.campaignDeadline'),
            tone: campaignItems.length ? 'campaign' : 'risk',
            route: { name: 'campaign-detail', params: { campaignId: campaign.id } },
        };
    }

    function setView(mode) {
        viewMode.value = mode;
        cursorDate.value = mode === 'month' ? startOfMonth(cursorDate.value) : startOfWeek(cursorDate.value);
    }

    function shiftPeriod(direction) {
        cursorDate.value = viewMode.value === 'month'
            ? addMonths(cursorDate.value, direction)
            : addDays(cursorDate.value, direction * 7);
    }

    function jumpToToday() {
        cursorDate.value = today;
    }

    function formatDayNumber(date) {
        return new Intl.DateTimeFormat(locale.value, { day: 'numeric' }).format(date);
    }

    function formatHour(value) {
        return new Intl.DateTimeFormat(locale.value, {
            hour: 'numeric',
            minute: '2-digit',
        }).format(new Date(value));
    }

    function startOfDay(value) {
        const date = new Date(value);
        date.setHours(0, 0, 0, 0);
        return date;
    }

    function startOfWeek(value) {
        const date = startOfDay(value);
        const day = date.getDay();
        const diff = day === 0 ? -6 : 1 - day;
        return addDays(date, diff);
    }

    function endOfWeek(value) {
        return addDays(startOfWeek(value), 6);
    }

    function startOfMonth(value) {
        const date = startOfDay(value);
        date.setDate(1);
        return date;
    }

    function endOfMonth(value) {
        const date = startOfMonth(value);
        date.setMonth(date.getMonth() + 1);
        date.setDate(0);
        return date;
    }

    function addDays(value, amount) {
        const date = startOfDay(value);
        date.setDate(date.getDate() + amount);
        return date;
    }

    function addMonths(value, amount) {
        const date = startOfMonth(value);
        date.setMonth(date.getMonth() + amount);
        return date;
    }

    function dateKey(value) {
        const date = new Date(value);
        return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
    }

    function sortByDate(left, right) {
        return left.scheduledAt.getTime() - right.scheduledAt.getTime();
    }
</script>

<template>
    <section class="calendar-shell">
        <div
            v-if="isLoading"
            class="page-message"
        >
            {{ t('dashboard.loading') }}
        </div>

        <div
            v-else-if="pageError"
            class="page-message error"
        >
            {{ pageError }}
        </div>

        <article
            v-else
            class="calendar-card"
        >
            <div class="calendar-toolbar">
                <div class="calendar-nav">
                    <button
                        class="icon-button"
                        type="button"
                        @click="shiftPeriod(-1)"
                    >
                        <v-icon :icon="mdiChevronLeft" />
                    </button>

                    <div class="calendar-period">{{ periodLabel }}</div>

                    <button
                        class="icon-button"
                        type="button"
                        @click="shiftPeriod(1)"
                    >
                        <v-icon :icon="mdiChevronRight" />
                    </button>
                </div>

                <div class="calendar-controls">
                    <button
                        class="text-button"
                        type="button"
                        @click="jumpToToday"
                    >
                        {{ t('today') }}
                    </button>

                    <div class="view-toggle">
                        <button
                            class="toggle-button"
                            :class="{ 'toggle-button-active': viewMode === 'month' }"
                            type="button"
                            @click="setView('month')"
                        >
                            {{ t('dashboard.month') }}
                        </button>
                        <button
                            class="toggle-button"
                            :class="{ 'toggle-button-active': viewMode === 'week' }"
                            type="button"
                            @click="setView('week')"
                        >
                            {{ t('dashboard.week') }}
                        </button>
                    </div>
                </div>
            </div>

            <div class="calendar-grid calendar-grid-head">
                <div
                    v-for="label in weekdayLabels"
                    :key="label"
                    class="weekday-label"
                >
                    {{ label }}
                </div>
            </div>

            <div
                class="calendar-grid"
                :class="viewMode === 'week' ? 'calendar-grid-week' : 'calendar-grid-month'"
            >
                <div
                    v-for="day in visibleDays"
                    :key="day.key"
                    class="calendar-day"
                    :class="{
                        'calendar-day-outside': day.isOutsideMonth,
                        'calendar-day-today': day.isToday,
                        'calendar-day-week': viewMode === 'week',
                    }"
                >
                    <div class="day-number">
                        {{ formatDayNumber(day.date) }}
                    </div>

                    <div
                        v-if="day.entries.length"
                        class="day-entries"
                    >
                        <router-link
                            v-for="entry in viewMode === 'month' ? day.entries.slice(0, 3) : day.entries"
                            :key="`${entry.type}-${entry.id}`"
                            :to="entry.route"
                            class="calendar-entry"
                            :class="entry.tone"
                        >
                            <span class="entry-time">{{ entry.timeLabel }}</span>
                            <strong>{{ entry.title }}</strong>
                            <span>{{ entry.subtitle }}</span>
                        </router-link>

                        <div
                            v-if="viewMode === 'month' && day.entries.length > 3"
                            class="entry-more"
                        >
                            {{ t('dashboard.moreItems', { count: day.entries.length - 3 }) }}
                        </div>
                    </div>

                    <div
                        v-else-if="viewMode === 'week'"
                        class="day-empty"
                    >
                        {{ t('dashboard.emptyPeriod') }}
                    </div>
                </div>
            </div>
        </article>
    </section>
</template>

<style scoped>
@reference "@/assets/main.css";
    .calendar-shell {
        @apply mx-auto w-full max-w-7xl px-5 py-8 md:px-8;
    }

    .page-message {
        @apply rounded-[1.25rem] border p-4 text-sm font-medium;
        background: rgba(255, 255, 255, 0.88);
        border-color: rgba(23, 32, 51, 0.08);
        color: #526178;
    }

    .page-message.error {
        color: #b91c1c;
    }

    .calendar-card {
        @apply rounded-[1.75rem] border p-4 md:p-5;
        background: rgba(255, 255, 255, 0.94);
        border-color: rgba(23, 32, 51, 0.08);
        box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06);
    }

    .calendar-toolbar {
        @apply mb-4 flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between;
    }

    .calendar-nav,
    .calendar-controls {
        @apply flex items-center gap-2;
    }

    .calendar-controls {
        @apply flex-wrap justify-end;
    }

    .calendar-period {
        @apply min-w-0 px-2 text-base font-bold md:text-lg;
        color: #172033;
    }

    .icon-button,
    .text-button,
    .toggle-button {
        @apply inline-flex items-center justify-center rounded-full border px-3 py-2 text-sm font-semibold transition;
        background: #f8fafc;
        border-color: rgba(23, 32, 51, 0.1);
        color: #172033;
    }

    .icon-button {
        @apply h-10 w-10 px-0 py-0;
    }

    .icon-button:hover,
    .text-button:hover,
    .toggle-button:hover {
        background: #eef4ff;
    }

    .view-toggle {
        @apply inline-flex rounded-full border p-1;
        background: #f8fafc;
        border-color: rgba(23, 32, 51, 0.1);
    }

    .toggle-button {
        @apply border-0 bg-transparent;
    }

    .toggle-button-active {
        background: #172033;
        color: #ffffff;
    }

    .calendar-grid {
        @apply grid gap-3;
        grid-template-columns: repeat(7, minmax(0, 1fr));
    }

    .calendar-grid-head {
        @apply mb-3;
    }

    .weekday-label {
        @apply px-2 text-xs font-bold uppercase tracking-[0.16em];
        color: #526178;
    }

    .calendar-day {
        @apply min-h-[8.5rem] rounded-[1.25rem] border p-3;
        background: linear-gradient(180deg, rgba(255, 253, 248, 0.8) 0%, rgba(255, 255, 255, 0.96) 100%);
        border-color: rgba(23, 32, 51, 0.08);
    }

    .calendar-day-week {
        @apply min-h-[22rem];
    }

    .calendar-day-outside {
        opacity: 0.48;
    }

    .calendar-day-today {
        border-color: rgba(15, 118, 110, 0.22);
        box-shadow: inset 0 0 0 1px rgba(15, 118, 110, 0.18);
    }

    .day-number {
        @apply mb-3 text-sm font-bold;
        color: #172033;
    }

    .day-entries {
        @apply flex flex-col gap-2;
    }

    .calendar-entry {
        @apply flex flex-col gap-0.5 rounded-[1rem] border px-3 py-2 no-underline transition;
    }

    .calendar-entry:hover {
        transform: translateY(-1px);
    }

    .calendar-entry strong {
        @apply text-sm font-bold;
        color: #172033;
    }

    .calendar-entry span {
        @apply text-xs leading-5;
        color: #526178;
    }

    .entry-time {
        @apply text-[0.7rem] font-bold uppercase tracking-[0.12em];
        color: #0f766e;
    }

    .entry-more,
    .day-empty {
        @apply px-1 text-xs font-semibold;
        color: #526178;
    }

    .calendar-entry.production {
        background: #fff7ed;
        border-color: rgba(249, 115, 22, 0.18);
    }

    .calendar-entry.approval {
        background: #eff6ff;
        border-color: rgba(37, 99, 235, 0.16);
    }

    .calendar-entry.ready {
        background: #ecfdf5;
        border-color: rgba(5, 150, 105, 0.16);
    }

    .calendar-entry.risk {
        background: #fef2f2;
        border-color: rgba(220, 38, 38, 0.16);
    }

    .calendar-entry.campaign {
        background: #f8fafc;
        border-color: rgba(71, 85, 105, 0.18);
        border-style: dashed;
    }

    .calendar-entry.published,
    .calendar-entry.muted {
        background: #f8fafc;
        border-color: rgba(148, 163, 184, 0.18);
    }

    @media (max-width: 960px) {
        .calendar-shell {
            @apply px-4 py-6;
        }

        .calendar-grid {
            gap: 0.5rem;
        }

        .weekday-label {
            @apply text-[0.65rem];
        }

        .calendar-day {
            @apply min-h-[7rem] p-2;
        }

        .calendar-day-week {
            @apply min-h-[18rem];
        }

        .calendar-entry {
            @apply px-2 py-2;
        }
    }

    @media (max-width: 720px) {
        .calendar-toolbar {
            @apply items-stretch;
        }

        .calendar-nav,
        .calendar-controls {
            @apply justify-between;
        }

        .calendar-grid-head,
        .calendar-grid {
            min-width: 46rem;
        }

        .calendar-card {
            overflow-x: auto;
        }
    }
</style>
