<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/layout/configuracoes/ConfiguracoesExcecoesFinanceirasPage.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 { useTenantStore } from '@/stores/tenantStore';
import { useToast } from 'primevue/usetoast';
import { useFinancialExceptions } from '@/features/agenda/composables/useFinancialExceptions';

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

const { exceptions, loading, error: exceptionsError, load, save } = useFinancialExceptions();

const ownerId = ref(null);
const tenantId = ref(null);
const pageLoading = ref(true);

// ── Tipos de exceção fixos ────────────────────────────────────────────
const exceptionTypes = [
    { value: 'patient_no_show', label: 'Paciente não compareceu' },
    { value: 'patient_cancellation', label: 'Cancelamento pelo paciente' },
    { value: 'professional_cancellation', label: 'Cancelamento pelo profissional' }
];

// ── Opções de modo de cobrança ────────────────────────────────────────
const chargeModeOptions = [
    { value: 'none', label: 'Não cobrar' },
    { value: 'full', label: 'Sessão completa' },
    { value: 'fixed_fee', label: 'Taxa fixa' },
    { value: 'percentage', label: 'Percentual da sessão' }
];

// ── Severidade do badge por charge_mode ──────────────────────────────
const chargeModeSeverity = {
    none: 'secondary',
    full: 'danger',
    fixed_fee: 'warn',
    percentage: 'info'
};

// ── Lookup: para cada exception_type, o registro ativo (owner > clínica) ──
// Prioridade: registro próprio do owner > registro global (owner_id IS NULL)
function recordFor(type) {
    const own = exceptions.value.find((e) => e.exception_type === type && e.owner_id !== null);
    const global = exceptions.value.find((e) => e.exception_type === type && e.owner_id === null);
    return own ?? global ?? null;
}

function isGlobalRecord(rec) {
    return rec?.owner_id === null;
}

// ── Texto descritivo do charge_mode ──────────────────────────────────
function chargeModeLabel(mode) {
    return chargeModeOptions.find((o) => o.value === mode)?.label ?? mode ?? '—';
}

function fmtBRL(v) {
    if (v == null || v === '') return '—';
    return Number(v).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' });
}

function summaryFor(rec) {
    if (!rec) return 'Não configurado (padrão: não cobrar)';
    switch (rec.charge_mode) {
        case 'none':
            return 'Não cobrar';
        case 'full':
            return 'Cobrar sessão completa';
        case 'fixed_fee':
            return `Taxa fixa: ${fmtBRL(rec.charge_value)}`;
        case 'percentage':
            return `${rec.charge_pct ?? 0}% da sessão`;
        default:
            return '—';
    }
}

// ── Edição inline ─────────────────────────────────────────────────────
const editingType = ref(null);
const editForm = ref({});
const savingEdit = ref(false);

function startEdit(type) {
    const rec = recordFor(type);
    editingType.value = type;
    editForm.value = {
        id: rec?.id ?? null,
        exception_type: type,
        charge_mode: rec?.charge_mode ?? 'none',
        charge_value: rec?.charge_value != null ? Number(rec.charge_value) : null,
        charge_pct: rec?.charge_pct != null ? Number(rec.charge_pct) : null,
        min_hours_notice: rec?.min_hours_notice != null ? Number(rec.min_hours_notice) : null,
        default_consume_on_miss: !!rec?.default_consume_on_miss
    };
}

function cancelEdit() {
    editingType.value = null;
    editForm.value = {};
}

async function saveEdit() {
    savingEdit.value = true;
    try {
        await save({
            id: editForm.value.id,
            owner_id: ownerId.value,
            tenant_id: tenantId.value,
            exception_type: editForm.value.exception_type,
            charge_mode: editForm.value.charge_mode,
            charge_value: editForm.value.charge_mode === 'fixed_fee' ? (editForm.value.charge_value ?? null) : null,
            charge_pct: editForm.value.charge_mode === 'percentage' ? (editForm.value.charge_pct ?? null) : null,
            min_hours_notice: editForm.value.exception_type === 'patient_cancellation' ? (editForm.value.min_hours_notice ?? null) : null,
            default_consume_on_miss: !!editForm.value.default_consume_on_miss
        });
        await load(ownerId.value);
        cancelEdit();
        toast.add({ severity: 'success', summary: 'Salvo', detail: 'Configuração atualizada.', life: 3000 });
    } catch {
        toast.add({ severity: 'error', summary: 'Erro', detail: exceptionsError.value || 'Falha ao salvar.', life: 4000 });
    } finally {
        savingEdit.value = false;
    }
}

// ── Computed auxiliares usados no template ────────────────────────────
const showChargeValue = computed(() => editForm.value.charge_mode === 'fixed_fee');
const showChargePct = computed(() => editForm.value.charge_mode === 'percentage');
const showMinHours = computed(() => editForm.value.exception_type === 'patient_cancellation');

// ── Mount ─────────────────────────────────────────────────────────────
onMounted(async () => {
    try {
        const uid = tenantStore.user?.id || (await supabase.auth.getUser()).data?.user?.id;
        if (!uid) return;

        ownerId.value = uid;
        tenantId.value = tenantStore.activeTenantId || null;

        await load(uid);
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao carregar.', life: 4000 });
    } finally {
        pageLoading.value = false;
    }
});
</script>

<template>
    <div class="flex flex-col gap-3">
        <!-- ══ SKELETON ══════════════════════════════════════════════ -->
        <template v-if="pageLoading || loading">
            <div v-for="n in 3" :key="n" class="cfg-wrap">
                <div class="cfg-wrap__head">
                    <Skeleton width="1.75rem" height="1.75rem" border-radius="6px" />
                    <Skeleton :width="n === 1 ? '13rem' : n === 2 ? '11rem' : '15rem'" height="12px" />
                    <Skeleton width="4rem" height="1.4rem" border-radius="999px" class="ml-auto" />
                </div>
                <div class="px-4 py-3">
                    <Skeleton width="16rem" height="10px" />
                </div>
            </div>
            <AppLoadingPhrases action="Carregando exceções financeiras..." containerClass="py-6" />
        </template>

        <template v-else>
            <!-- Um card por tipo de exceção -->
            <div v-for="et in exceptionTypes" :key="et.value" class="cfg-wrap">
                <!-- Cabeçalho do card -->
                <div class="cfg-wrap__head">
                    <div class="cfg-wrap__icon"><i class="pi pi-exclamation-triangle" /></div>
                    <span class="cfg-wrap__title">{{ et.label }}</span>
                    <div class="ml-auto flex items-center gap-2 shrink-0">
                        <template v-if="recordFor(et.value)">
                            <Tag :value="chargeModeLabel(recordFor(et.value)?.charge_mode)" :severity="chargeModeSeverity[recordFor(et.value)?.charge_mode] ?? 'secondary'" />
                            <Tag v-if="isGlobalRecord(recordFor(et.value))" value="Regra da clínica" severity="secondary" />
                        </template>
                        <Button v-if="editingType !== et.value && !isGlobalRecord(recordFor(et.value))" label="Configurar" icon="pi pi-cog" size="small" severity="secondary" outlined class="rounded-full" @click="startEdit(et.value)" />
                    </div>
                </div>

                <!-- Modo leitura -->
                <div v-if="editingType !== et.value" class="exc-read">
                    <template v-if="recordFor(et.value)">
                        <div class="text-sm text-[var(--text-color-secondary)]">
                            {{ summaryFor(recordFor(et.value)) }}
                            <span v-if="et.value === 'patient_cancellation' && recordFor(et.value)?.min_hours_notice"> — cobrar apenas se cancelado com menos de {{ recordFor(et.value).min_hours_notice }}h de antecedência </span>
                        </div>
                    </template>
                    <div v-else class="text-sm text-[var(--text-color-secondary)] italic">Não configurado — comportamento padrão: não cobrar.</div>
                </div>

                <!-- Modo edição -->
                <div v-else class="exc-edit">
                    <!-- Modo de cobrança -->
                    <div>
                        <label class="exc-label">Modo de cobrança</label>
                        <SelectButton v-model="editForm.charge_mode" :options="chargeModeOptions" optionLabel="label" optionValue="value" class="flex-wrap mt-1" />
                    </div>

                    <div class="grid grid-cols-12 gap-3">
                        <!-- Taxa fixa -->
                        <div v-if="showChargeValue" class="col-span-12 sm:col-span-4">
                            <FloatLabel variant="on">
                                <InputNumber v-model="editForm.charge_value" inputId="edit-charge-value" mode="currency" currency="BRL" locale="pt-BR" :min="0" fluid />
                                <label for="edit-charge-value">Taxa fixa (R$)</label>
                            </FloatLabel>
                        </div>

                        <!-- Percentual -->
                        <div v-if="showChargePct" class="col-span-12 sm:col-span-4">
                            <FloatLabel variant="on">
                                <InputNumber v-model="editForm.charge_pct" inputId="edit-charge-pct" :min="0" :max="100" :minFractionDigits="0" :maxFractionDigits="2" suffix="%" fluid />
                                <label for="edit-charge-pct">Percentual da sessão (%)</label>
                            </FloatLabel>
                        </div>

                        <!-- Antecedência mínima -->
                        <div v-if="showMinHours" class="col-span-12 sm:col-span-6">
                            <FloatLabel variant="on">
                                <InputNumber v-model="editForm.min_hours_notice" inputId="edit-min-hours" :min="0" :max="720" suffix=" h" fluid showButtons />
                                <label for="edit-min-hours">Cobrar se cancelado com menos de X horas (vazio = sempre)</label>
                            </FloatLabel>
                            <small class="text-[var(--text-color-secondary)] opacity-70 mt-1 block text-xs"> Deixe em branco para cobrar independentemente da antecedência. </small>
                        </div>
                    </div>

                    <!-- Default consume_on_miss (2026-05-14): toggle pra padrão do
                         "Descontar do saldo" no dialog de status change. -->
                    <div class="flex items-start gap-2.5 mt-1">
                        <Checkbox v-model="editForm.default_consume_on_miss" inputId="edit-consume-default" binary />
                        <label for="edit-consume-default" class="cursor-pointer flex flex-col gap-0.5">
                            <span class="text-sm font-medium">Descontar do saldo do pacote por padrão</span>
                            <small class="text-[var(--text-color-secondary)] opacity-70 text-xs">
                                Quando esta exceção ocorre em sessão de pacote saldo, o dialog vem com "Descontar" marcado. Terapeuta pode override caso a caso.
                            </small>
                        </label>
                    </div>

                    <!-- Botões na linha separada -->
                    <div class="flex gap-2 justify-end mt-1">
                        <Button label="Cancelar" icon="pi pi-times" size="small" severity="secondary" outlined class="rounded-full" @click="cancelEdit" />
                        <Button label="Salvar" icon="pi pi-check" size="small" :loading="savingEdit" class="rounded-full" @click="saveEdit" />
                    </div>
                </div>
            </div>

            <!-- Dica -->
            <Message severity="info" :closable="false">
                <span class="text-sm"> Estas configurações definem o comportamento padrão de cobrança. Você pode ajustá-las individualmente em cada evento na agenda. </span>
            </Message>

            <LoadedPhraseBlock />
        </template>
    </div>
</template>

<style scoped>
/* ── Card wrap ────────────────────────────────────── */
.cfg-wrap {
    border: 1px solid var(--surface-border);
    border-radius: 6px;
    background: var(--surface-card);
    overflow: hidden;
}
.cfg-wrap__head {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--surface-border);
    background: var(--surface-ground);
    flex-wrap: wrap;
}
.cfg-wrap__icon {
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 6px;
    flex-shrink: 0;
    background: color-mix(in srgb, var(--primary-color, #6366f1) 12%, transparent);
    color: var(--primary-color, #6366f1);
    font-size: 0.8rem;
}
.cfg-wrap__title {
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--text-color);
}

/* ── Leitura ──────────────────────────────────────── */
.exc-read {
    padding: 0.75rem 1rem;
}

/* ── Edição ───────────────────────────────────────── */
.exc-edit {
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    background: color-mix(in srgb, var(--primary-color, #6366f1) 3%, var(--surface-card));
    border-top: 2px solid color-mix(in srgb, var(--primary-color, #6366f1) 40%, transparent);
}

/* ── Label ────────────────────────────────────────── */
.exc-label {
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-color-secondary);
    margin-bottom: 0.375rem;
}
</style>
