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

const props = defineProps({
    modelValue: Boolean,
    mode: { type: String, default: 'horario' }, // 'horario' | 'periodo' | 'dia' | 'feriados'
    workRules: { type: Array, default: () => [] },
    settings: { type: Object, default: null },
    ownerId: { type: String, default: '' },
    tenantId: { type: [String, null], default: null }
});

const emit = defineEmits(['update:modelValue', 'saved']);
const toast = useToast();
const saving = ref(false);

// ── Feriados ──────────────────────────────────────────────────────────────
const { proximos, load: loadFeriados, criar: criarFeriado } = useFeriados();

// ── Mode: horario ─────────────────────────────────────────────────────────
const todayDow = new Date().getDay();

const timeSlots = computed(() => {
    const rule = props.workRules.find((r) => Number(r.dia_semana) === todayDow);
    if (!rule) return [];
    const dur = props.settings?.session_duration_min ?? props.settings?.duracao_padrao_minutos ?? 50;
    const [sh, sm] = String(rule.hora_inicio || '08:00')
        .slice(0, 5)
        .split(':')
        .map(Number);
    const [eh, em] = String(rule.hora_fim || '18:00')
        .slice(0, 5)
        .split(':')
        .map(Number);
    const startMin = sh * 60 + sm;
    const endMin = eh * 60 + em;
    const slots = [];
    for (let t = startMin; t + dur <= endMin; t += dur) {
        const h1 = Math.floor(t / 60),
            m1 = t % 60;
        const t2 = t + dur,
            h2 = Math.floor(t2 / 60),
            m2 = t2 % 60;
        const hi = `${String(h1).padStart(2, '0')}:${String(m1).padStart(2, '0')}`;
        const hf = `${String(h2).padStart(2, '0')}:${String(m2).padStart(2, '0')}`;
        slots.push({ label: `${hi} – ${hf}`, hora_inicio: hi, hora_fim: hf });
    }
    return slots;
});

const selectedSlotIndices = ref(new Set());

function toggleSlot(idx) {
    const s = new Set(selectedSlotIndices.value);
    if (s.has(idx)) s.delete(idx);
    else s.add(idx);
    selectedSlotIndices.value = s;
}

// ── Mode: periodo ─────────────────────────────────────────────────────────
const periodos = ref([
    { label: 'Manhã', sub: '06:00 – 12:00', icon: 'pi pi-sun', hora_inicio: '06:00', hora_fim: '12:00', selected: false },
    { label: 'Tarde', sub: '12:00 – 18:00', icon: 'pi pi-cloud-sun', hora_inicio: '12:00', hora_fim: '18:00', selected: false },
    { label: 'Noite', sub: '18:00 – 23:00', icon: 'pi pi-moon', hora_inicio: '18:00', hora_fim: '23:00', selected: false }
]);
const periodoDate = ref(new Date());

// ── Mode: dia ─────────────────────────────────────────────────────────────
const selectedDays = ref([]);

// ── Mode: feriados ────────────────────────────────────────────────────────
const upcomingFeriados = computed(() => proximos(90));
const feriadosDecisao = ref({}); // { [iso]: true (trabalha) | false (não trabalha) }

// Dialog feriado municipal
const fdlgOpen = ref(false);
const fsaving = ref(false);
const fform = ref({ nome: '', data: null, observacao: '' });

// ── Reset ao abrir ────────────────────────────────────────────────────────
watch(
    () => props.modelValue,
    (v) => {
        if (!v) return;
        selectedSlotIndices.value = new Set();
        periodos.value.forEach((p) => {
            p.selected = false;
        });
        periodoDate.value = new Date();
        selectedDays.value = [];
        feriadosDecisao.value = {};
        if (props.mode === 'feriados' && props.tenantId) {
            loadFeriados(props.tenantId);
        }
    }
);

// ── Helpers ───────────────────────────────────────────────────────────────
function toISO(d) {
    if (!d) return null;
    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}

function fmtDateLong(iso) {
    if (!iso) return '';
    const [y, m, d] = iso.split('-').map(Number);
    return new Date(y, m - 1, d).toLocaleDateString('pt-BR', { weekday: 'long', day: '2-digit', month: 'long' });
}

function setFeriadoDecisao(data, rawVal) {
    const val = rawVal === 'sim' ? true : rawVal === 'nao' ? false : undefined;
    const copy = { ...feriadosDecisao.value };
    if (val === undefined) delete copy[data];
    else copy[data] = val;
    feriadosDecisao.value = copy;
}

// ── UI ────────────────────────────────────────────────────────────────────
const dialogTitle = computed(
    () =>
        ({
            horario: 'Bloquear por Horário',
            periodo: 'Bloquear por Período',
            dia: 'Bloquear por Dia',
            feriados: 'Bloqueio por Feriados'
        })[props.mode] || 'Bloquear'
);

const canConfirm = computed(() => {
    if (props.mode === 'horario') return selectedSlotIndices.value.size > 0;
    if (props.mode === 'periodo') return periodos.value.some((p) => p.selected);
    if (props.mode === 'dia') return selectedDays.value.length > 0;
    if (props.mode === 'feriados') return Object.values(feriadosDecisao.value).some((v) => v === false);
    return false;
});

function close() {
    emit('update:modelValue', false);
}

// ── Confirmar bloqueio ────────────────────────────────────────────────────
async function confirmar() {
    if (!props.ownerId || !props.tenantId) {
        toast.add({ severity: 'warn', summary: 'Atenção', detail: 'Configurações da agenda não carregadas.', life: 3000 });
        return;
    }
    saving.value = true;
    try {
        const base = {
            owner_id: props.ownerId,
            tipo: 'bloqueio',
            recorrente: false
        };
        const rows = [];

        if (props.mode === 'horario') {
            const iso = toISO(new Date());
            timeSlots.value.forEach((slot, idx) => {
                if (!selectedSlotIndices.value.has(idx)) return;
                rows.push({ ...base, titulo: `Bloqueio ${slot.hora_inicio}–${slot.hora_fim}`, data_inicio: iso, data_fim: iso, hora_inicio: slot.hora_inicio, hora_fim: slot.hora_fim, origem: 'agenda_horario' });
            });
        } else if (props.mode === 'periodo') {
            const iso = toISO(periodoDate.value);
            periodos.value
                .filter((p) => p.selected)
                .forEach((p) => {
                    rows.push({ ...base, titulo: `Bloqueio ${p.label}`, data_inicio: iso, data_fim: iso, hora_inicio: p.hora_inicio, hora_fim: p.hora_fim, origem: 'agenda_periodo' });
                });
        } else if (props.mode === 'dia') {
            selectedDays.value.forEach((d) => {
                rows.push({ ...base, titulo: 'Dia bloqueado', data_inicio: toISO(d), data_fim: toISO(d), hora_inicio: null, hora_fim: null, origem: 'agenda_dia' });
            });
        } else if (props.mode === 'feriados') {
            for (const [data, trabalha] of Object.entries(feriadosDecisao.value)) {
                if (trabalha !== false) continue;
                const f = upcomingFeriados.value.find((f) => f.data === data);
                rows.push({ ...base, titulo: f ? `Feriado: ${f.nome}` : 'Feriado bloqueado', data_inicio: data, data_fim: data, hora_inicio: null, hora_fim: null, origem: 'agenda_feriado' });
            }
        }

        if (!rows.length) {
            toast.add({ severity: 'warn', summary: 'Seleção vazia', detail: 'Selecione ao menos um item para bloquear.', life: 2500 });
            return;
        }

        const { error } = await tenantDb().from('agenda_bloqueios').insert(rows);
        if (error) throw error;

        // Marcar sessões existentes como "remarcado"
        await marcarSessoesParaRemarcar(rows);

        toast.add({
            severity: 'success',
            summary: 'Bloqueio criado',
            detail: `${rows.length} bloqueio(s) registrado(s). Sessões existentes marcadas para reagendamento.`,
            life: 4500
        });
        emit('saved');
        close();
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao criar bloqueio.', life: 4000 });
    } finally {
        saving.value = false;
    }
}

async function marcarSessoesParaRemarcar(bloqueios) {
    // Para cada bloqueio, tenta marcar sessões existentes como 'remarcado'
    for (const b of bloqueios) {
        try {
            let query = tenantDb().from('agenda_eventos').update({ status: 'remarcado' }).eq('owner_id', props.ownerId).eq('tipo', 'sessao').gte('inicio_em', `${b.data_inicio}T00:00:00`).lte('inicio_em', `${b.data_fim}T23:59:59`);

            if (b.hora_inicio && b.hora_fim) {
                // filtra pela hora aproximada — comparação UTC simplificada
                query = query.gte('inicio_em', `${b.data_inicio}T${b.hora_inicio}:00`).lte('inicio_em', `${b.data_inicio}T${b.hora_fim}:00`);
            }

            await query;
        } catch {
            /* ignora erros parciais — o bloqueio já foi criado */
        }
    }
}

// ── Feriado municipal ─────────────────────────────────────────────────────
async function salvarFeriadoMunicipal() {
    if (!fform.value.nome || !fform.value.data) return;
    fsaving.value = true;
    const iso = toISO(fform.value.data);
    try {
        await criarFeriado({
            owner_id: props.ownerId,
            tipo: 'municipal',
            nome: fform.value.nome.trim(),
            data: iso,
            observacao: fform.value.observacao || null,
            bloqueia_sessoes: true
        });
        toast.add({ severity: 'success', summary: 'Feriado cadastrado', life: 1800 });
        // Auto-marca como "não trabalha" para facilitar
        feriadosDecisao.value = { ...feriadosDecisao.value, [iso]: false };
        fdlgOpen.value = false;
        fform.value = { nome: '', data: null, observacao: '' };
        // Recarrega feriados
        if (props.tenantId) loadFeriados(props.tenantId);
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message, life: 3500 });
    } finally {
        fsaving.value = false;
    }
}
</script>

<template>
    <!-- Dialog principal -->
    <Dialog :visible="modelValue" modal :draggable="false" :header="dialogTitle" :style="{ width: '540px', maxWidth: '96vw' }" @update:visible="emit('update:modelValue', $event)">
        <!-- ── Banner de aviso ────────────────────────────────── -->
        <div class="blq-warning mb-4">
            <i class="pi pi-exclamation-triangle blq-warning__icon" />
            <div class="text-sm leading-relaxed">
                <b>Atenção:</b> sessões existentes nos períodos bloqueados serão marcadas como <b>Remarcar</b> e os pacientes receberão aviso por e-mail/SMS para reagendamento.<br />
                <span class="opacity-70 text-xs">O bloqueio prevalece sobre qualquer compromisso já agendado.</span>
            </div>
        </div>

        <!-- ══ Modo: Horário ════════════════════════════════════ -->
        <div v-if="mode === 'horario'" class="flex flex-col gap-3">
            <p class="text-sm text-[var(--text-color-secondary)]">Selecione os horários de <b>hoje</b> que deseja bloquear (baseados na sua jornada). Presencial e online serão bloqueados simultaneamente.</p>

            <div v-if="timeSlots.length === 0" class="blq-empty">
                <i class="pi pi-info-circle" />
                Hoje não é um dia de trabalho configurado na agenda.
            </div>

            <div v-else class="flex flex-wrap gap-2">
                <button v-for="(slot, idx) in timeSlots" :key="idx" class="blq-chip" :class="{ 'blq-chip--on': selectedSlotIndices.has(idx) }" type="button" @click="toggleSlot(idx)">
                    <i class="pi pi-clock text-xs" />
                    {{ slot.label }}
                </button>
            </div>

            <p v-if="selectedSlotIndices.size > 0" class="text-xs text-[var(--text-color-secondary)]">
                <i class="pi pi-lock mr-1" style="color: var(--red-500)" />
                {{ selectedSlotIndices.size }} horário(s) selecionado(s)
            </p>
        </div>

        <!-- ══ Modo: Período ════════════════════════════════════ -->
        <div v-else-if="mode === 'periodo'" class="flex flex-col gap-4">
            <p class="text-sm text-[var(--text-color-secondary)]">Selecione o dia e os períodos que deseja bloquear.</p>

            <div>
                <label class="blq-label">Data *</label>
                <DatePicker v-model="periodoDate" 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="grid grid-cols-3 gap-3">
                <button v-for="p in periodos" :key="p.label" class="blq-period-card" :class="{ 'blq-period-card--on': p.selected }" type="button" @click="p.selected = !p.selected">
                    <i :class="p.icon" class="text-xl mb-1" />
                    <span class="font-semibold text-sm">{{ p.label }}</span>
                    <span class="text-xs opacity-60">{{ p.sub }}</span>
                </button>
            </div>
        </div>

        <!-- ══ Modo: Dia ════════════════════════════════════════ -->
        <div v-else-if="mode === 'dia'" class="flex flex-col gap-3">
            <p class="text-sm text-[var(--text-color-secondary)]">Clique nos dias que deseja bloquear. O dia inteiro ficará indisponível para agendamentos.</p>

            <Calendar v-model="selectedDays" inline selectionMode="multiple" :minDate="new Date()" class="w-full" />

            <p v-if="selectedDays.length" class="text-xs text-[var(--text-color-secondary)]">
                <i class="pi pi-lock mr-1" style="color: var(--red-500)" />
                {{ selectedDays.length }} dia(s) selecionado(s)
            </p>
        </div>

        <!-- ══ Modo: Feriados ═══════════════════════════════════ -->
        <div v-else-if="mode === 'feriados'" class="flex flex-col gap-3">
            <div class="flex items-center justify-between gap-2 flex-wrap">
                <p class="text-sm text-[var(--text-color-secondary)] m-0">Próximos feriados (90 dias). Indique se vai trabalhar em cada um.</p>
                <Button label="+ Feriado municipal" icon="pi pi-map-marker" size="small" severity="secondary" outlined class="shrink-0 rounded-full" @click="fdlgOpen = true" />
            </div>

            <div v-if="upcomingFeriados.length === 0" class="blq-empty">
                <i class="pi pi-calendar" />
                Nenhum feriado nos próximos 90 dias.
            </div>

            <div v-else class="flex flex-col gap-2 max-h-[320px] overflow-y-auto pr-1">
                <div v-for="f in upcomingFeriados" :key="f.data" class="blq-feriado-row" :class="{ 'blq-feriado-row--blocked': feriadosDecisao[f.data] === false }">
                    <div class="flex-1 min-w-0">
                        <div class="font-medium text-sm truncate">{{ f.nome }}</div>
                        <div class="text-xs text-[var(--text-color-secondary)] capitalize">
                            {{ fmtDateLong(f.data) }}
                        </div>
                    </div>

                    <div class="flex items-center gap-2 shrink-0 flex-wrap justify-end">
                        <span class="text-xs text-[var(--text-color-secondary)] whitespace-nowrap">Vai trabalhar?</span>
                        <SelectButton
                            :modelValue="feriadosDecisao[f.data] === true ? 'sim' : feriadosDecisao[f.data] === false ? 'nao' : null"
                            :options="[
                                { label: 'Sim', value: 'sim' },
                                { label: 'Não', value: 'nao' }
                            ]"
                            optionLabel="label"
                            optionValue="value"
                            :allowEmpty="true"
                            size="small"
                            @update:modelValue="(v) => setFeriadoDecisao(f.data, v)"
                        />
                    </div>
                </div>
            </div>
        </div>

        <!-- ── Footer ─────────────────────────────────────────── -->
        <template #footer>
            <Button label="Cancelar" severity="secondary" outlined @click="close" />
            <Button label="Confirmar Bloqueio" icon="pi pi-lock" severity="danger" :loading="saving" :disabled="!canConfirm" @click="confirmar" />
        </template>
    </Dialog>

    <!-- Dialog feriado municipal -->
    <Dialog v-model:visible="fdlgOpen" modal :draggable="false" header="Cadastrar feriado municipal" :style="{ width: '420px' }">
        <div class="flex flex-col gap-4 pt-1">
            <div>
                <label class="blq-label">Nome *</label>
                <InputText v-model="fform.nome" class="w-full mt-1" placeholder="Ex.: Aniversário da cidade, Padroeiro…" />
            </div>

            <div>
                <label class="blq-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="blq-label">Observação <span class="opacity-60">(opcional)</span></label>
                <Textarea v-model="fform.observacao" class="w-full mt-1" rows="2" autoResize />
            </div>
        </div>

        <template #footer>
            <Button label="Cancelar" severity="secondary" outlined @click="fdlgOpen = false" />
            <Button label="Cadastrar" icon="pi pi-check" :disabled="!fform.nome || !fform.data" :loading="fsaving" @click="salvarFeriadoMunicipal" />
        </template>
    </Dialog>
</template>

<style scoped>
/* ── Aviso ─────────────────────────────────────────────── */
.blq-warning {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 0.75rem 1rem;
    border-radius: 0.875rem;
    background: color-mix(in srgb, var(--red-400, #f87171) 10%, var(--surface-card));
    border: 1px solid color-mix(in srgb, var(--red-400, #f87171) 30%, transparent);
}
.blq-warning__icon {
    color: var(--red-500, #ef4444);
    flex-shrink: 0;
    margin-top: 2px;
}

/* ── Label ─────────────────────────────────────────────── */
.blq-label {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--text-color-secondary);
}

/* ── Empty ─────────────────────────────────────────────── */
.blq-empty {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 1.5rem 1rem;
    border-radius: 0.875rem;
    border: 1px dashed var(--surface-border);
    font-size: 0.875rem;
    color: var(--text-color-secondary);
    justify-content: center;
}

/* ── Chips de horário ──────────────────────────────────── */
.blq-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.4rem 0.875rem;
    border-radius: 999px;
    border: 1.5px solid var(--surface-border);
    background: var(--surface-card);
    font-size: 0.8125rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.14s;
    color: var(--text-color);
}
.blq-chip:hover {
    border-color: var(--red-300, #fca5a5);
    background: color-mix(in srgb, var(--red-400, #f87171) 8%, var(--surface-card));
}
.blq-chip--on {
    border-color: var(--red-500, #ef4444) !important;
    background: color-mix(in srgb, var(--red-500, #ef4444) 15%, var(--surface-card)) !important;
    color: var(--red-700, #b91c1c);
}

/* ── Cards de período ──────────────────────────────────── */
.blq-period-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.2rem;
    padding: 1.25rem 0.5rem;
    border-radius: 1rem;
    border: 1.5px solid var(--surface-border);
    background: var(--surface-card);
    cursor: pointer;
    transition: all 0.14s;
    color: var(--text-color);
}
.blq-period-card:hover {
    border-color: var(--red-300, #fca5a5);
    background: color-mix(in srgb, var(--red-400, #f87171) 8%, var(--surface-card));
}
.blq-period-card--on {
    border-color: var(--red-500, #ef4444) !important;
    background: color-mix(in srgb, var(--red-500, #ef4444) 15%, var(--surface-card)) !important;
    color: var(--red-700, #b91c1c);
}

/* ── Feriados ──────────────────────────────────────────── */
.blq-feriado-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 0.875rem;
    border-radius: 0.875rem;
    border: 1.5px solid var(--surface-border);
    background: var(--surface-card);
    transition: all 0.14s;
}
.blq-feriado-row--blocked {
    border-color: var(--red-500, #ef4444);
    background: color-mix(in srgb, var(--red-500, #ef4444) 10%, var(--surface-card));
}
</style>
