<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/features/agenda/components/AgendaCalendar.vue
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
-->
<script setup>
import { computed, ref, watch, onMounted } from 'vue';

import FullCalendar from '@fullcalendar/vue3';
import timeGridPlugin from '@fullcalendar/timegrid';
import interactionPlugin from '@fullcalendar/interaction';
import dayGridPlugin from '@fullcalendar/daygrid';

import ProgressSpinner from 'primevue/progressspinner';
import { FC_TOUCH_DEFAULTS } from '@/features/agenda/utils/fcDefaults';

const props = defineProps({
    // UI
    view: { type: String, default: 'day' }, // 'day' | 'week'
    mode: { type: String, default: 'work_hours' }, // 'full_24h' | 'work_hours'

    // calendar behavior
    timezone: { type: String, default: 'America/Sao_Paulo' },
    slotDuration: { type: String, default: '00:30:00' },
    slotMinTime: { type: String, default: '06:00:00' },
    slotMaxTime: { type: String, default: '22:00:00' },
    businessHours: { type: [Array, Object], default: () => [] },

    // data
    events: { type: Array, default: () => [] },
    loading: { type: Boolean, default: false }
});

const emit = defineEmits(['rangeChange', 'selectTime', 'eventClick', 'eventDrop', 'eventResize']);

const fcRef = ref(null);

const initialView = computed(() => (props.view === 'week' ? 'timeGridWeek' : 'timeGridDay'));

function getApi() {
    const inst = fcRef.value;
    return inst?.getApi?.() || null;
}

function emitRange() {
    const api = getApi();
    if (!api) return;
    const v = api.view;
    emit('rangeChange', { start: v.activeStart, end: v.activeEnd });
}

// -----------------------------
// Calendar options
// -----------------------------
const calendarOptions = computed(() => {
    const isWorkHours = props.mode !== 'full_24h';

    // No modo 24h, não recorta — mas mantemos min/max caso você queira ainda controlar
    const minTime = isWorkHours ? props.slotMinTime : '00:00:00';
    // FullCalendar timeGrid costuma aceitar 24:00:00, mas 23:59:59 evita edge-case
    const maxTime = isWorkHours ? props.slotMaxTime : '23:59:59';

    return {
        ...FC_TOUCH_DEFAULTS,
        plugins: [timeGridPlugin, interactionPlugin, dayGridPlugin],
        initialView: initialView.value,

        timeZone: props.timezone,

        // Header desativado (você controla no Toolbar)
        headerToolbar: false,

        // Visão "produto": blocos com linhas suaves
        nowIndicator: true,
        allDaySlot: false,
        expandRows: true,
        height: 'auto',

        // Seleção / DnD / Resize
        selectable: true,
        selectMirror: true,
        editable: true,
        eventStartEditable: true,
        eventDurationEditable: true,

        // Intervalos visuais
        slotDuration: props.slotDuration,
        slotMinTime: minTime,
        slotMaxTime: maxTime,
        slotLabelFormat: {
            hour: '2-digit',
            minute: '2-digit',
            hour12: false
        },

        // Horário "verdadeiro" de funcionamento (se você usar)
        businessHours: props.businessHours,

        // Dados
        events: props.events,

        // Melhor UX
        weekends: true,
        firstDay: 1, // segunda

        // Callbacks
        datesSet: () => {
            // dispara quando muda o intervalo exibido (prev/next/today/view)
            emitRange();
        },

        select: (selection) => {
            // selection: { start, end, allDay, ... }
            emit('selectTime', selection);
        },

        eventClick: (info) => emit('eventClick', info),
        eventDrop: (info) => emit('eventDrop', info),
        eventResize: (info) => emit('eventResize', info)
    };
});

// -----------------------------
// Exposed methods (para Toolbar/Page)
// -----------------------------
function goToday() {
    getApi()?.today?.();
}
function prev() {
    getApi()?.prev?.();
}
function next() {
    getApi()?.next?.();
}

function setView(v) {
    const api = getApi();
    if (!api) return;
    api.changeView(v === 'week' ? 'timeGridWeek' : 'timeGridDay');
}

defineExpose({ goToday, prev, next, setView });

// Se a prop view mudar, sincroniza
watch(
    () => props.view,
    (v) => setView(v)
);

// Emite o range inicial assim que montar
onMounted(() => {
    // garante que o FullCalendar já criou a view
    setTimeout(() => emitRange(), 0);
});
</script>

<template>
    <div class="agenda-calendar-wrap">
        <div v-if="loading" class="agenda-calendar-loading">
            <div class="flex flex-col gap-2 w-full px-2 py-2">
                <Skeleton height="2rem" class="mb-1" />
                <div class="grid grid-cols-7 gap-1">
                    <Skeleton v-for="n in 7" :key="n" height="1.25rem" />
                </div>
                <Skeleton v-for="n in 8" :key="'row' + n" height="3rem" />
            </div>
        </div>

        <FullCalendar ref="fcRef" :options="calendarOptions" />
    </div>
</template>

<style scoped>
.agenda-calendar-wrap {
    position: relative;
    width: 100%;
}

.agenda-calendar-loading {
    position: absolute;
    inset: 0;
    z-index: 20;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(3px);
    background: color-mix(in srgb, var(--surface-card) 85%, transparent);
    border-radius: 16px;
}

/* Deixa o calendário "respirar" dentro de cards/layouts */
:deep(.fc) {
    font-size: 0.95rem;
}

:deep(.fc .fc-timegrid-slot) {
    height: 2.2rem;
}

:deep(.fc .fc-timegrid-now-indicator-line) {
    opacity: 0.75;
}

:deep(.fc .fc-scrollgrid) {
    border-radius: 16px;
    overflow: hidden;
    border: 1px solid var(--surface-border);
}

:deep(.fc .fc-timegrid-axis-cushion),
:deep(.fc .fc-timegrid-slot-label-cushion) {
    color: var(--text-color-secondary);
}
</style>
