<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/layout/configuracoes/BloqueiosPage.vue
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
-->
<script setup>
import { ref, computed, onMounted } from 'vue';
import { supabase } from '@/lib/supabase/client';
import { tenantDb } from '@/lib/supabase/tenantClient';
import { useTenantStore } from '@/stores/tenantStore';
import { useToast } from 'primevue/usetoast';
import { useConfirm } from 'primevue/useconfirm';
import { useFeriados } from '@/composables/useFeriados';
import DatePicker from 'primevue/datepicker';

const toast = useToast();
const confirm = useConfirm();
const tenantStore = useTenantStore();

// ── Feriados (nacionais + municipais) ───────────────────────
const { nacionais, municipais, todos, loading: loadingF, load: loadFeriados, criar: criarFeriado, remover: removerFeriado, isDuplicata } = useFeriados();

// ── Estado bloqueios ────────────────────────────────────────
const loadingB = ref(true);
const saving = ref(false);

const ownerId = ref(null);
const tenantId = ref(null);
const ano = ref(new Date().getFullYear());
const bloqueios = ref([]);

// ── Dialog bloqueio ─────────────────────────────────────────
const dlgOpen = ref(false);
const dlgMode = ref('add');
const form = ref(emptyForm());

// ── Dialog feriado municipal ────────────────────────────────
const fdlgOpen = ref(false);
const fsaving = ref(false);
const fform = ref(emptyFForm());

function emptyForm() {
    return {
        id: null,
        titulo: '',
        data_inicio: null,
        data_fim: null,
        hora_inicio: null,
        hora_fim: null,
        recorrente: false,
        dia_semana: null,
        observacao: ''
    };
}

function emptyFForm() {
    return { nome: '', data: null, observacao: '', bloqueia_sessoes: false };
}

// ── Helpers ─────────────────────────────────────────────────
function dateToISO(d) {
    if (!d) return null;
    const dt = d instanceof Date ? d : new Date(d);
    return `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, '0')}-${String(dt.getDate()).padStart(2, '0')}`;
}
function isoToDate(s) {
    if (!s) return null;
    const [y, m, d] = String(s).split('-').map(Number);
    return new Date(y, m - 1, d);
}
function dateToHHMM(d) {
    if (!d || !(d instanceof Date)) return null;
    return String(d.getHours()).padStart(2, '0') + ':' + String(d.getMinutes()).padStart(2, '0');
}
function hhmmToDate(hhmm) {
    if (!hhmm) return null;
    const [h, m] = String(hhmm).split(':').map(Number);
    const d = new Date();
    d.setHours(h, m, 0, 0);
    return d;
}
function fmtDate(iso) {
    if (!iso) return '—';
    const [y, m, d] = String(iso).split('-');
    return `${d}/${m}/${y}`;
}
function fmtDateShort(iso) {
    if (!iso) return '';
    const [, m, d] = String(iso).split('-');
    return `${d}/${m}`;
}
function fmtHora(t) {
    if (!t) return null;
    return String(t).slice(0, 5);
}

// ── Auth + tenant ────────────────────────────────────────────
async function boot() {
    const { data } = await supabase.auth.getUser();
    ownerId.value = data?.user?.id || null;
    tenantId.value = tenantStore.activeTenantId || tenantStore.tenantId || tenantStore.tenant?.id || null;
    if (tenantId.value) await loadFeriados(tenantId.value);
    await loadBloqueios();
}

onMounted(boot);

// ── Load bloqueios ────────────────────────────────────────────
async function loadBloqueios() {
    if (!ownerId.value) return;
    loadingB.value = true;
    try {
        const { data, error } = await tenantDb().from('agenda_bloqueios').select('*').eq('owner_id', ownerId.value).gte('data_inicio', `${ano.value}-01-01`).lte('data_inicio', `${ano.value}-12-31`).order('data_inicio');
        if (error) throw error;
        bloqueios.value = data || [];
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3500 });
    } finally {
        loadingB.value = false;
    }
}

// ── Navegação de ano ─────────────────────────────────────────
async function anoAnterior() {
    ano.value--;
    await loadFeriados(tenantId.value, ano.value);
    await loadBloqueios();
}
async function anoProximo() {
    ano.value++;
    await loadFeriados(tenantId.value, ano.value);
    await loadBloqueios();
}

// ── Feriado municipal CRUD ────────────────────────────────────
function abrirFeriadoMunicipal() {
    fform.value = emptyFForm();
    fdlgOpen.value = true;
}

const fformValid = computed(() => !!fform.value.nome.trim() && !!fform.value.data);

async function salvarFeriado() {
    if (!fformValid.value) return;
    const iso = dateToISO(fform.value.data);
    if (isDuplicata(iso, fform.value.nome)) {
        toast.add({ severity: 'warn', summary: 'Duplicado', detail: 'Já existe um feriado com esse nome nessa data.', life: 3000 });
        return;
    }
    fsaving.value = true;
    try {
        await criarFeriado({
            tenant_id: tenantId.value,
            owner_id: ownerId.value,
            tipo: 'municipal',
            nome: fform.value.nome.trim(),
            data: iso,
            observacao: fform.value.observacao || null,
            bloqueia_sessoes: fform.value.bloqueia_sessoes
        });
        toast.add({ severity: 'success', summary: 'Feriado cadastrado', life: 1800 });
        fdlgOpen.value = false;
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3500 });
    } finally {
        fsaving.value = false;
    }
}

function excluirFeriado(id) {
    confirm.require({
        message: 'Deseja remover este feriado municipal?',
        header: 'Confirmar remoção',
        icon: 'pi pi-exclamation-triangle',
        rejectLabel: 'Cancelar',
        acceptLabel: 'Remover',
        acceptClass: 'p-button-danger',
        accept: async () => {
            try {
                await removerFeriado(id);
                toast.add({ severity: 'success', summary: 'Removido', life: 1500 });
            } catch (e) {
                toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3000 });
            }
        }
    });
}

// ── Bloqueio CRUD ─────────────────────────────────────────────
function abrirAddBloqueio() {
    form.value = emptyForm();
    dlgMode.value = 'add';
    dlgOpen.value = true;
}

function abrirEditBloqueio(b) {
    form.value = {
        id: b.id,
        titulo: b.titulo,
        data_inicio: isoToDate(b.data_inicio),
        data_fim: isoToDate(b.data_fim),
        hora_inicio: hhmmToDate(fmtHora(b.hora_inicio)),
        hora_fim: hhmmToDate(fmtHora(b.hora_fim)),
        recorrente: !!b.recorrente,
        dia_semana: b.dia_semana ?? null,
        observacao: b.observacao || ''
    };
    dlgMode.value = 'edit';
    dlgOpen.value = true;
}

const formValid = computed(() => !!form.value.titulo.trim() && !!form.value.data_inicio);

async function salvarBloqueio() {
    if (!formValid.value) return;
    saving.value = true;
    try {
        const payload = {
            owner_id: ownerId.value,
            tenant_id: tenantId.value,
            tipo: 'bloqueio',
            titulo: form.value.titulo.trim(),
            data_inicio: dateToISO(form.value.data_inicio),
            data_fim: dateToISO(form.value.data_fim) || null,
            hora_inicio: dateToHHMM(form.value.hora_inicio) || null,
            hora_fim: dateToHHMM(form.value.hora_fim) || null,
            recorrente: form.value.recorrente,
            dia_semana: form.value.dia_semana ?? null,
            observacao: form.value.observacao || null,
            origem: 'manual'
        };

        if (dlgMode.value === 'edit') {
            const { error } = await tenantDb().from('agenda_bloqueios').update(payload).eq('id', form.value.id);
            if (error) throw error;
            toast.add({ severity: 'success', summary: 'Salvo', detail: 'Bloqueio atualizado.', life: 1800 });
        } else {
            const { error } = await tenantDb().from('agenda_bloqueios').insert(payload);
            if (error) throw error;
            toast.add({ severity: 'success', summary: 'Criado', detail: 'Bloqueio adicionado.', life: 1800 });
        }

        dlgOpen.value = false;
        await loadBloqueios();
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3500 });
    } finally {
        saving.value = false;
    }
}

function excluirBloqueio(id) {
    const b = bloqueios.value.find((x) => x.id === id);
    confirm.require({
        message: b?.titulo ? `Remover o bloqueio "${b.titulo}"?` : 'Deseja remover este bloqueio?',
        header: 'Confirmar remoção',
        icon: 'pi pi-exclamation-triangle',
        rejectLabel: 'Cancelar',
        acceptLabel: 'Remover',
        acceptClass: 'p-button-danger',
        accept: async () => {
            try {
                const { error } = await tenantDb().from('agenda_bloqueios').delete().eq('id', id);
                if (error) throw error;
                bloqueios.value = bloqueios.value.filter((b) => b.id !== id);
                toast.add({ severity: 'success', summary: 'Removido', life: 1500 });
            } catch (e) {
                toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3000 });
            }
        }
    });
}

// ── fmtPeriodo ────────────────────────────────────────────────
function fmtPeriodo(b) {
    if (b.recorrente && b.dia_semana != null) {
        const dias = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'];
        return `Toda ${dias[b.dia_semana]}`;
    }
    const ini = fmtDate(b.data_inicio);
    if (!b.data_fim || b.data_fim === b.data_inicio) {
        const hora = b.hora_inicio ? ` · ${fmtHora(b.hora_inicio)}–${fmtHora(b.hora_fim) || '?'}` : ' · Dia inteiro';
        return ini + hora;
    }
    return `${ini} até ${fmtDate(b.data_fim)}`;
}

const loading = computed(() => loadingF.value || loadingB.value);
</script>

<template>
    <ConfirmDialog />

    <div class="flex flex-col gap-3">
        <!-- Stats + ações -->
        <div class="flex flex-wrap items-center gap-2">
            <div class="blk-stat blk-stat--blue">
                <div class="blk-stat__value">{{ nacionais.length }}</div>
                <div class="blk-stat__label">Nacionais</div>
            </div>
            <div class="blk-stat blk-stat--orange">
                <div class="blk-stat__value">{{ municipais.length }}</div>
                <div class="blk-stat__label">Municipais</div>
            </div>
            <div class="blk-stat blk-stat--red">
                <div class="blk-stat__value">{{ bloqueios.length }}</div>
                <div class="blk-stat__label">Bloqueios</div>
            </div>
            <div class="ml-auto flex gap-2">
                <Button icon="pi pi-map-marker" label="Feriado municipal" severity="secondary" outlined class="rounded-full" size="small" @click="abrirFeriadoMunicipal" />
                <Button icon="pi pi-ban" label="Novo bloqueio" class="rounded-full" size="small" @click="abrirAddBloqueio" />
            </div>
        </div>

        <!-- ══ SKELETON ══════════════════════════════════════════════ -->
        <template v-if="loading">
            <!-- Grupo skeleton: Feriados Nacionais — frases aqui -->
            <div class="blk-group">
                <div class="blk-group__head">
                    <Skeleton shape="circle" size="1.6rem" />
                    <Skeleton width="9rem" height="0.85rem" />
                    <Skeleton width="2rem" height="1.2rem" border-radius="999px" />
                </div>
                <AppLoadingPhrases action="Carregando bloqueios e feriados..." containerClass="py-10" />
            </div>

            <!-- Grupo skeleton: Feriados Municipais -->
            <div class="blk-group">
                <div class="blk-group__head">
                    <Skeleton shape="circle" size="1.6rem" />
                    <Skeleton width="10rem" height="0.85rem" />
                    <Skeleton width="2rem" height="1.2rem" border-radius="999px" />
                </div>
                <div class="blk-list">
                    <div v-for="i in 3" :key="i" class="blk-item">
                        <Skeleton width="4rem" height="0.75rem" />
                        <Skeleton :width="`${8 + (i % 2) * 5}rem`" height="0.75rem" />
                    </div>
                </div>
            </div>

            <!-- Grupo skeleton: Bloqueios -->
            <div class="blk-group">
                <div class="blk-group__head">
                    <Skeleton shape="circle" size="1.6rem" />
                    <Skeleton width="5rem" height="0.85rem" />
                    <Skeleton width="2rem" height="1.2rem" border-radius="999px" />
                </div>
                <div class="blk-list">
                    <div v-for="i in 4" :key="i" class="blk-item">
                        <Skeleton width="4rem" height="0.75rem" />
                        <Skeleton :width="`${7 + (i % 3) * 3}rem`" height="0.75rem" />
                    </div>
                </div>
            </div>
        </template>

        <template v-else>
            <!-- Feriados Nacionais -->
            <div class="blk-group">
                <div class="blk-group__head">
                    <div class="blk-group__head-icon" style="background: color-mix(in srgb, #3b82f6 12%, transparent); color: #3b82f6">
                        <i class="pi pi-flag" />
                    </div>
                    <span>Feriados Nacionais</span>
                    <span class="blk-group__count">{{ nacionais.length }}</span>
                    <span class="ml-auto text-xs text-[var(--text-color-secondary)] opacity-60 font-normal">gerado automaticamente</span>
                </div>
                <div class="blk-list">
                    <div v-for="f in nacionais" :key="f.data + f.nome" class="blk-item">
                        <div class="blk-item__date">{{ fmtDateShort(f.data) }}</div>
                        <div class="blk-item__title">{{ f.nome }}</div>
                        <Tag v-if="f.movel" value="Móvel" severity="secondary" class="text-xs shrink-0 ml-auto" />
                    </div>
                </div>
            </div>

            <!-- Feriados Municipais -->
            <div class="blk-group">
                <div class="blk-group__head">
                    <div class="blk-group__head-icon" style="background: color-mix(in srgb, #f97316 12%, transparent); color: #f97316">
                        <i class="pi pi-map-marker" />
                    </div>
                    <span>Feriados Municipais</span>
                    <span class="blk-group__count">{{ municipais.length }}</span>
                </div>
                <div v-if="!municipais.length" class="blk-empty">Nenhum feriado municipal cadastrado para {{ ano }}.</div>
                <div v-else class="blk-list">
                    <div v-for="f in municipais" :key="f.id" class="blk-item">
                        <div class="blk-item__date">{{ fmtDate(f.data) }}</div>
                        <div class="blk-item__title">{{ f.nome }}</div>
                        <div v-if="f.observacao" class="blk-item__obs">{{ f.observacao }}</div>
                        <div class="blk-item__actions">
                            <Button icon="pi pi-trash" text rounded size="small" severity="danger" @click="excluirFeriado(f.id)" />
                        </div>
                    </div>
                </div>
            </div>

            <!-- Bloqueios -->
            <div class="blk-group">
                <div class="blk-group__head">
                    <div class="blk-group__head-icon" style="background: color-mix(in srgb, #ef4444 12%, transparent); color: #ef4444">
                        <i class="pi pi-ban" />
                    </div>
                    <span>Bloqueios</span>
                    <span class="blk-group__count">{{ bloqueios.length }}</span>
                </div>
                <div v-if="!bloqueios.length" class="blk-empty">Nenhum bloqueio cadastrado para {{ ano }}.</div>
                <div v-else class="blk-list">
                    <div v-for="b in bloqueios" :key="b.id" class="blk-item">
                        <div class="blk-item__date">{{ fmtPeriodo(b) }}</div>
                        <div class="blk-item__title">{{ b.titulo }}</div>
                        <Tag v-if="b.recorrente" value="Recorrente" severity="warn" class="text-xs shrink-0" />
                        <div v-if="b.observacao" class="blk-item__obs">{{ b.observacao }}</div>
                        <div class="blk-item__actions">
                            <Button icon="pi pi-pencil" text rounded size="small" severity="secondary" @click="abrirEditBloqueio(b)" />
                            <Button icon="pi pi-trash" text rounded size="small" severity="danger" @click="excluirBloqueio(b.id)" />
                        </div>
                    </div>
                </div>
            </div>

            <!-- Bloco pós-carregamento -->
            <LoadedPhraseBlock />
        </template>
    </div>

    <!-- Dialog feriado municipal -->
    <Dialog v-model:visible="fdlgOpen" modal :draggable="false" pt:mask:class="backdrop-blur-xs" header="Cadastrar feriado municipal" :style="{ width: '420px', maxWidth: '95vw' }">
        <div class="flex flex-col gap-4 pt-1">
            <div>
                <label class="blk-label">Nome do feriado *</label>
                <InputText v-model="fform.nome" class="w-full mt-1" placeholder="Ex.: Aniversário da cidade, Padroeiro…" />
            </div>
            <div>
                <label class="blk-label">Data *</label>
                <DatePicker v-model="fform.data" showIcon fluid iconDisplay="input" dateFormat="dd/mm/yy" :manualInput="false" class="mt-1">
                    <template #inputicon="sp"><i class="pi pi-calendar" @click="sp.clickCallback" /></template>
                </DatePicker>
            </div>
            <div>
                <label class="blk-label">Observação <span class="opacity-60">(opcional)</span></label>
                <Textarea v-model="fform.observacao" class="w-full mt-1" rows="2" autoResize placeholder="Nota interna…" />
            </div>
            <div v-if="fform.data && fform.nome && isDuplicata(dateToISO(fform.data), fform.nome)" class="text-sm text-red-500 flex items-center gap-2"><i class="pi pi-exclamation-triangle" /> Já existe um feriado com esse nome nessa data.</div>
        </div>
        <template #footer>
            <Button label="Cancelar" severity="secondary" outlined class="rounded-full" @click="fdlgOpen = false" />
            <Button label="Cadastrar" icon="pi pi-check" class="rounded-full" :disabled="!fformValid || (fform.data && fform.nome && isDuplicata(dateToISO(fform.data), fform.nome))" :loading="fsaving" @click="salvarFeriado" />
        </template>
    </Dialog>

    <!-- Dialog bloqueio -->
    <Dialog v-model:visible="dlgOpen" modal :draggable="false" pt:mask:class="backdrop-blur-xs" :header="dlgMode === 'edit' ? 'Editar bloqueio' : 'Novo bloqueio'" :style="{ width: '480px', maxWidth: '95vw' }">
        <div class="flex flex-col gap-4 pt-1">
            <div>
                <label class="blk-label">Título *</label>
                <InputText v-model="form.titulo" class="w-full mt-1" placeholder="Ex.: Recesso, Férias, Licença…" />
            </div>
            <div class="flex gap-3">
                <div class="flex-1">
                    <label class="blk-label">Data início *</label>
                    <DatePicker v-model="form.data_inicio" showIcon fluid iconDisplay="input" dateFormat="dd/mm/yy" :manualInput="false" class="mt-1">
                        <template #inputicon="sp"><i class="pi pi-calendar" @click="sp.clickCallback" /></template>
                    </DatePicker>
                </div>
                <div class="flex-1">
                    <label class="blk-label">Data fim <span class="opacity-60">(opcional)</span></label>
                    <DatePicker v-model="form.data_fim" showIcon fluid iconDisplay="input" dateFormat="dd/mm/yy" :manualInput="false" :minDate="form.data_inicio || undefined" class="mt-1">
                        <template #inputicon="sp"><i class="pi pi-calendar" @click="sp.clickCallback" /></template>
                    </DatePicker>
                </div>
            </div>
            <div class="flex gap-3">
                <div class="flex-1">
                    <label class="blk-label">Hora início <span class="opacity-60">(opcional)</span></label>
                    <DatePicker v-model="form.hora_inicio" showIcon fluid iconDisplay="input" timeOnly hourFormat="24" :stepMinute="15" :manualInput="false" class="mt-1">
                        <template #inputicon="sp"><i class="pi pi-clock" @click="sp.clickCallback" /></template>
                    </DatePicker>
                </div>
                <div class="flex-1">
                    <label class="blk-label">Hora fim <span class="opacity-60">(opcional)</span></label>
                    <DatePicker v-model="form.hora_fim" showIcon fluid iconDisplay="input" timeOnly hourFormat="24" :stepMinute="15" :manualInput="false" class="mt-1">
                        <template #inputicon="sp"><i class="pi pi-clock" @click="sp.clickCallback" /></template>
                    </DatePicker>
                </div>
            </div>
            <div>
                <label class="blk-label">Observação <span class="opacity-60">(opcional)</span></label>
                <Textarea v-model="form.observacao" class="w-full mt-1" rows="2" autoResize />
            </div>
        </div>
        <template #footer>
            <Button label="Cancelar" icon="pi pi-times" severity="secondary" outlined class="rounded-full" @click="dlgOpen = false" />
            <Button :label="dlgMode === 'edit' ? 'Salvar' : 'Adicionar'" icon="pi pi-check" class="rounded-full" :disabled="!formValid" :loading="saving" @click="salvarBloqueio" />
        </template>
    </Dialog>
</template>

<style scoped>
/* ── Stats ────────────────────────────────────────── */
.blk-stat {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: 0.5rem 0.875rem;
    border-radius: 6px;
    border: 1px solid var(--surface-border);
    background: var(--surface-card);
    min-width: 72px;
}
.blk-stat__value {
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1;
}
.blk-stat__label {
    font-size: 0.7rem;
    color: var(--text-color-secondary);
    opacity: 0.75;
}
.blk-stat--blue .blk-stat__value {
    color: #3b82f6;
}
.blk-stat--orange .blk-stat__value {
    color: #f97316;
}
.blk-stat--red .blk-stat__value {
    color: #ef4444;
}

/* ── Grupos ──────────────────────────────────────── */
.blk-group {
    border-radius: 6px;
    border: 1px solid var(--surface-border);
    background: var(--surface-card);
    overflow: hidden;
}
.blk-group__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--surface-border);
    font-weight: 600;
    font-size: 0.88rem;
    background: var(--surface-ground);
}
.blk-group__head-icon {
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 6px;
    flex-shrink: 0;
    font-size: 0.78rem;
}
.blk-group__count {
    font-size: 0.7rem;
    background: var(--surface-card);
    border: 1px solid var(--surface-border);
    border-radius: 999px;
    padding: 1px 8px;
    color: var(--text-color-secondary);
}

/* ── Itens ──────────────────────────────────────── */
.blk-empty {
    padding: 1.25rem;
    font-size: 0.875rem;
    color: var(--text-color-secondary);
}
.blk-list {
    display: flex;
    flex-direction: column;
}
.blk-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 1rem;
    border-bottom: 1px solid var(--surface-border);
    flex-wrap: wrap;
    transition: background 0.1s;
}
.blk-item:last-child {
    border-bottom: none;
}
.blk-item:hover {
    background: var(--surface-hover);
}

.blk-item__date {
    font-size: 0.75rem;
    color: var(--text-color-secondary);
    white-space: nowrap;
    min-width: 5.5rem;
    font-variant-numeric: tabular-nums;
}
.blk-item__title {
    flex: 1;
    font-weight: 500;
    font-size: 0.85rem;
    min-width: 0;
}
.blk-item__obs {
    font-size: 0.72rem;
    color: var(--text-color-secondary);
    width: 100%;
    padding-left: 6.25rem;
    margin-top: -0.25rem;
}
.blk-item__actions {
    display: flex;
    gap: 0.25rem;
    margin-left: auto;
}

/* ── Dialog labels ──────────────────────────────── */
.blk-label {
    font-size: 0.75rem;
    color: var(--text-color-secondary);
    font-weight: 500;
}
</style>
