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

const toast = useToast();
const confirm = useConfirm();
const router = useRouter();
const route = useRoute();
const tenantStore = useTenantStore();

// Preserva o layout em que a pagina esta aberta (Melissa vs /configuracoes).
const inMelissa = computed(() => String(route.path || '').startsWith('/melissa'));

// ── Contexto ──────────────────────────────────────────────────
const userId = ref(null);
const tenantId = ref(null);
const loading = ref(true);

// ── Saldo de créditos ─────────────────────────────────────────
const credits = ref(null);
const hasCredits = computed(() => credits.value !== null);
const balance = computed(() => credits.value?.balance ?? 0);
const totalPurchased = computed(() => credits.value?.total_purchased ?? 0);
const totalConsumed = computed(() => credits.value?.total_consumed ?? 0);

const balanceSeverity = computed(() => {
    if (!hasCredits.value || balance.value <= 0) return 'danger';
    if (balance.value <= (credits.value?.low_balance_threshold || 10)) return 'warn';
    return 'success';
});

const balanceIcon = computed(() => {
    if (balance.value <= 0) return 'pi pi-times-circle';
    if (balance.value <= (credits.value?.low_balance_threshold || 10)) return 'pi pi-exclamation-triangle';
    return 'pi pi-check-circle';
});

// ── Transações recentes ───────────────────────────────────────
const transactions = ref([]);
const txLoading = ref(false);

// ── Logs de envio ─────────────────────────────────────────────
const recentLogs = ref([]);
const logsLoading = ref(false);

// ══════════════════════════════════════════════════════════════
// Templates SMS
// ══════════════════════════════════════════════════════════════

const templates = ref([]);
const templatesLoading = ref(false);
const templateSaving = ref({});

// Labels para exibição
const EVENT_TYPE_LABELS = {
    lembrete_sessao: 'Lembrete',
    confirmacao_sessao: 'Confirmação',
    cancelamento_sessao: 'Cancelamento',
    reagendamento: 'Reagendamento',
    cobranca_pendente: 'Financeiro',
    boas_vindas_paciente: 'Boas-vindas',
    intake_recebido: 'Triagem',
    intake_aprovado: 'Triagem',
    intake_rejeitado: 'Triagem'
};
const EVENT_SEVERITY = {
    lembrete_sessao: 'info',
    confirmacao_sessao: 'success',
    cancelamento_sessao: 'danger',
    reagendamento: 'warn',
    cobranca_pendente: 'warn',
    boas_vindas_paciente: 'success',
    intake_recebido: 'info',
    intake_aprovado: 'success',
    intake_rejeitado: 'danger'
};

// Referências dos textareas por template key
const textareaRefs = ref({});

function setTextareaRef(key, el) {
    if (el) textareaRefs.value[key] = el;
}

async function loadTemplates() {
    if (!tenantId.value) return;
    templatesLoading.value = true;
    try {
        // 1. Busca templates default semeados no schema do tenant
        const { data: globals, error: gErr } = await tenantDb().from('notification_templates')
            .select('*')
            .eq('channel', 'sms')
            .eq('is_default', true)
            .eq('is_active', true)
            .is('deleted_at', null)
            .order('domain')
            .order('event_type');
        if (gErr) throw gErr;

        // 2. Busca customizações do tenant
        const { data: customs, error: cErr } = await tenantDb().from('notification_templates').select('*').eq('channel', 'sms').is('deleted_at', null);
        if (cErr) throw cErr;

        const customMap = {};
        for (const c of customs || []) customMap[c.key] = c;

        // 3. Mescla: para cada global, verifica se o tenant tem customização
        templates.value = (globals || []).map((g) => {
            const custom = customMap[g.key];
            return {
                key: g.key,
                domain: g.domain,
                event_type: g.event_type,
                label: EVENT_TYPE_LABELS[g.event_type] || g.event_type,
                type: EVENT_TYPE_LABELS[g.event_type] || g.event_type,
                type_severity: EVENT_SEVERITY[g.event_type] || 'secondary',
                variables: g.variables || [],
                default_body: g.body_text,
                // Se tenant customizou, usa o texto dele; senão usa o global
                id: custom?.id || null,
                body_text: custom?.body_text || g.body_text,
                is_custom: !!custom
            };
        });
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro ao carregar templates', detail: e.message, life: 4000 });
    } finally {
        templatesLoading.value = false;
    }
}

function insertVariable(templateKey, variable) {
    const snippet = `{{${variable}}}`;
    const tpl = templates.value.find((t) => t.key === templateKey);
    if (!tpl) return;

    const taWrapper = textareaRefs.value[templateKey];
    const ta = taWrapper?.$el?.querySelector('textarea') ?? taWrapper;
    if (ta?.setSelectionRange) {
        const start = ta.selectionStart ?? ta.value.length;
        const end   = ta.selectionEnd   ?? start;
        tpl.body_text = (tpl.body_text || '').slice(0, start) + snippet + (tpl.body_text || '').slice(end);
        nextTick(() => {
            const pos = start + snippet.length;
            ta.focus();
            ta.setSelectionRange(pos, pos);
        });
    } else {
        tpl.body_text = (tpl.body_text || '') + snippet;
    }
}

async function saveTemplate(tpl) {
    if (!tenantId.value || templateSaving.value[tpl.key]) return;
    templateSaving.value[tpl.key] = true;
    try {
        if (tpl.id) {
            const { error } = await tenantDb().from('notification_templates').update({ body_text: tpl.body_text }).eq('id', tpl.id);
            if (error) throw error;
        } else {
            const { data: existing } = await tenantDb().from('notification_templates').select('id').eq('key', tpl.key).is('deleted_at', null).maybeSingle();

            if (existing?.id) {
                const { error } = await tenantDb().from('notification_templates').update({ body_text: tpl.body_text, is_active: true }).eq('id', existing.id);
                if (error) throw error;
                tpl.id = existing.id;
            } else {
                const { data, error } = await tenantDb().from('notification_templates')
                    .insert({
                        owner_id: userId.value,
                        channel: 'sms',
                        key: tpl.key,
                        domain: tpl.domain,
                        event_type: tpl.event_type,
                        body_text: tpl.body_text,
                        variables: tpl.variables,
                        is_active: true,
                        is_default: false
                    })
                    .select('id')
                    .single();
                if (error) throw error;
                tpl.id = data.id;
            }
            tpl.is_custom = true;
        }
        toast.add({ severity: 'success', summary: 'Template salvo', life: 3000 });
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro ao salvar template', detail: e.message, life: 5000 });
    } finally {
        templateSaving.value[tpl.key] = false;
    }
}

function isTemplateModified(tpl) {
    return tpl.default_body ? tpl.body_text !== tpl.default_body : false;
}

function confirmRestoreTemplate(tpl) {
    if (!tpl.default_body) return;
    confirm.require({
        group: 'headless',
        message: `Restaurar "${tpl.label}" para o texto original definido pelo administrador?`,
        header: 'Restaurar template',
        icon: 'pi-undo',
        accept: () => {
            tpl.body_text = tpl.default_body;
        }
    });
}

// ── Load ──────────────────────────────────────────────────────
async function loadUser() {
    const {
        data: { user }
    } = await supabase.auth.getUser();
    if (!user) return;
    userId.value = user.id;
    tenantId.value = tenantStore.activeTenantId || user.id;
}

async function loadCredits() {
    if (!tenantId.value) return;

    const { data, error } = await supabase.from('addon_credits').select('*').eq('tenant_id', tenantId.value).eq('addon_type', 'sms').eq('is_active', true).maybeSingle();

    if (!error && data) credits.value = data;
}

async function loadTransactions() {
    if (!tenantId.value) return;
    txLoading.value = true;

    const { data } = await supabase
        .from('addon_transactions')
        .select('id, type, amount, balance_after, description, payment_method, created_at')
        .eq('tenant_id', tenantId.value)
        .eq('addon_type', 'sms')
        .order('created_at', { ascending: false })
        .limit(15);

    txLoading.value = false;
    if (data) transactions.value = data;
}

async function loadLogs() {
    if (!tenantId.value) return;
    logsLoading.value = true;

    const { data } = await tenantDb().from('notification_logs')
        .select('id, template_key, recipient_address, status, failure_reason, sent_at, failed_at, created_at')
        
        .eq('channel', 'sms')
        .order('created_at', { ascending: false })
        .limit(10);

    logsLoading.value = false;
    if (data) recentLogs.value = data;
}

// ── Helpers ───────────────────────────────────────────────────
function txTypeLabel(type) {
    const map = { purchase: 'Compra', consume: 'Consumo', adjustment: 'Ajuste', refund: 'Reembolso', expiration: 'Expiração' };
    return map[type] || type;
}

function txTypeSeverity(type) {
    const map = { purchase: 'success', consume: 'secondary', adjustment: 'info', refund: 'warn', expiration: 'danger' };
    return map[type] || 'secondary';
}

function logStatusSeverity(status) {
    if (status === 'sent') return 'success';
    if (status === 'failed') return 'danger';
    return 'secondary';
}

function formatDate(iso) {
    if (!iso) return '—';
    return new Date(iso).toLocaleString('pt-BR', { dateStyle: 'short', timeStyle: 'short' });
}

function goToRecursosExtras() {
    router.push(inMelissa.value ? '/melissa/cfg-recursos-extras' : '/configuracoes/recursos-extras');
}

// ── Init ──────────────────────────────────────────────────────
onMounted(async () => {
    await loadUser();
    await Promise.all([loadCredits(), loadTransactions(), loadLogs(), loadTemplates()]);
    loading.value = false;
});
</script>

<template>
    <div class="flex flex-col gap-5">
        <ConfirmDialog group="headless">
            <template #container="{ message, acceptCallback, rejectCallback }">
                <div class="flex flex-col items-center p-8 bg-surface-0 dark:bg-surface-900 rounded-xl shadow-xl">
                    <div class="rounded-full inline-flex justify-center items-center h-24 w-24 -mt-20" :style="{ background: message.color || 'var(--p-primary-color)', color: '#fff' }">
                        <i :class="`pi ${message.icon || 'pi-question'} !text-4xl`"></i>
                    </div>
                    <span class="font-bold text-2xl block mb-2 mt-6">{{ message.header }}</span>
                    <p class="mb-0 text-center text-[var(--text-color-secondary)]">{{ message.message }}</p>
                    <div class="flex items-center gap-2 mt-6">
                        <Button label="Confirmar" class="rounded-full" :style="{ background: message.color || 'var(--p-primary-color)', borderColor: message.color || 'var(--p-primary-color)' }" @click="acceptCallback" />
                        <Button label="Cancelar" variant="outlined" class="rounded-full" @click="rejectCallback" />
                    </div>
                </div>
            </template>
        </ConfirmDialog>

        <!-- Saldo Card -->
        <Card>
            <template #title>
                <div class="flex items-center gap-2">
                    <i class="pi pi-comment text-xl" />
                    Créditos SMS
                </div>
            </template>
            <template #subtitle>Seus créditos para envio de SMS aos pacientes.</template>
            <template #content>
                <div v-if="loading" class="flex items-center gap-2 text-surface-500"><i class="pi pi-spin pi-spinner" /> Carregando...</div>

                <div v-else class="flex flex-col gap-4">
                    <!-- Saldo principal -->
                    <div class="flex items-center gap-4">
                        <div class="flex items-center gap-2">
                            <i :class="balanceIcon" :style="{ color: balanceSeverity === 'success' ? 'var(--p-green-500)' : balanceSeverity === 'warn' ? 'var(--p-yellow-500)' : 'var(--p-red-500)' }" class="text-2xl" />
                            <span class="text-4xl font-bold">{{ balance }}</span>
                            <span class="text-surface-500 text-sm">créditos disponíveis</span>
                        </div>
                    </div>

                    <!-- Estatísticas -->
                    <div v-if="hasCredits" class="flex gap-6 text-sm text-surface-500">
                        <div class="flex flex-col">
                            <span class="font-semibold text-surface-700">{{ totalPurchased }}</span>
                            <span>Total comprado</span>
                        </div>
                        <div class="flex flex-col">
                            <span class="font-semibold text-surface-700">{{ totalConsumed }}</span>
                            <span>Total consumido</span>
                        </div>
                    </div>

                    <!-- Alerta saldo baixo -->
                    <Message v-if="hasCredits && balance <= 0" severity="error" :closable="false"> Sem créditos SMS. Os lembretes por SMS estão pausados. Adquira mais créditos para reativar. </Message>
                    <Message v-else-if="hasCredits && balance <= (credits?.low_balance_threshold || 10)" severity="warn" :closable="false"> Saldo baixo! Restam apenas {{ balance }} créditos SMS. </Message>

                    <!-- Sem créditos ainda -->
                    <Message v-if="!hasCredits" severity="info" :closable="false"> Você ainda não possui créditos SMS. Adquira um pacote em Recursos Extras. </Message>

                    <Button label="Adquirir créditos SMS" icon="pi pi-shopping-cart" @click="goToRecursosExtras" class="w-fit" />
                </div>
            </template>
        </Card>

        <!-- ══════════════════════════════════════════════════════════ -->
        <!-- Templates de mensagem SMS -->
        <!-- ══════════════════════════════════════════════════════════ -->
        <Card>
            <template #title>
                <div class="flex items-center gap-2">
                    <i class="pi pi-file-edit text-xl" />
                    Mensagens SMS
                </div>
            </template>
            <template #subtitle>Personalize as mensagens enviadas por SMS aos seus pacientes. Os textos padrão já funcionam — edite apenas se quiser personalizar.</template>
            <template #content>
                <!-- Skeleton loading -->
                <template v-if="templatesLoading">
                    <div v-for="n in 4" :key="n" class="border border-surface rounded-xl p-4 mb-3">
                        <div class="flex items-center gap-2 mb-3">
                            <Skeleton width="5rem" height="1.4rem" borderRadius="999px" />
                            <Skeleton width="10rem" height="1rem" />
                        </div>
                        <Skeleton width="100%" height="5rem" class="mb-2" />
                        <div class="flex gap-1">
                            <Skeleton v-for="i in 3" :key="i" width="6rem" height="1.6rem" borderRadius="999px" />
                        </div>
                    </div>
                </template>

                <!-- Cards de templates -->
                <div v-else class="flex flex-col gap-4">
                    <div v-for="tpl in templates" :key="tpl.key" class="border border-surface rounded-xl p-4 flex flex-col gap-3">
                        <!-- Header do card -->
                        <div class="flex items-center gap-2 flex-wrap">
                            <span class="font-semibold text-sm">{{ tpl.label }}</span>
                            <Tag :value="tpl.type" :severity="tpl.type_severity" class="text-[0.65rem]" />
                            <Tag v-if="tpl.is_custom" value="Personalizado" severity="success" class="text-[0.65rem]" />
                        </div>

                        <!-- Editor Jodit -->
                        <Textarea :ref="(el) => setTextareaRef(tpl.key, el)" v-model="tpl.body_text" rows="4" auto-resize class="w-full text-sm" />

                        <!-- Variáveis clicáveis -->
                        <div class="flex flex-col gap-1.5">
                            <span class="text-xs text-surface-500">Inserir variável:</span>
                            <div class="flex flex-wrap gap-1.5">
                                <Button v-for="v in tpl.variables" :key="v" size="small" severity="secondary" outlined class="font-mono !text-[0.68rem] !py-1 !px-2" @click="insertVariable(tpl.key, v)">
                                    <span v-text="'{{' + v + '}}'"></span>
                                </Button>
                            </div>
                        </div>

                        <!-- Ações -->
                        <div class="flex items-center gap-2 justify-end">
                            <Button v-if="isTemplateModified(tpl)" label="Restaurar original" icon="pi pi-undo" size="small" severity="secondary" outlined @click="confirmRestoreTemplate(tpl)" />
                            <Button label="Salvar" icon="pi pi-check" size="small" :loading="templateSaving[tpl.key]" :disabled="templateSaving[tpl.key]" @click="saveTemplate(tpl)" />
                        </div>
                    </div>
                </div>
            </template>
        </Card>

        <!-- Histórico de transações -->
        <Card>
            <template #title>
                <div class="flex items-center justify-between">
                    <span>Histórico de créditos</span>
                    <Button icon="pi pi-refresh" text rounded size="small" @click="loadTransactions" :loading="txLoading" />
                </div>
            </template>
            <template #content>
                <DataTable :value="transactions" :loading="txLoading" size="small" stripedRows emptyMessage="Nenhuma transação encontrada.">
                    <Column field="created_at" header="Data" style="width: 140px">
                        <template #body="{ data }">{{ formatDate(data.created_at) }}</template>
                    </Column>
                    <Column field="type" header="Tipo" style="width: 110px">
                        <template #body="{ data }">
                            <Tag :value="txTypeLabel(data.type)" :severity="txTypeSeverity(data.type)" />
                        </template>
                    </Column>
                    <Column field="amount" header="Qtd" style="width: 80px">
                        <template #body="{ data }">
                            <span :class="data.amount > 0 ? 'text-green-500 font-semibold' : 'text-red-500'"> {{ data.amount > 0 ? '+' : '' }}{{ data.amount }} </span>
                        </template>
                    </Column>
                    <Column field="balance_after" header="Saldo" style="width: 80px" />
                    <Column field="description" header="Descrição" />
                </DataTable>
            </template>
        </Card>

        <!-- Últimos envios -->
        <Card>
            <template #title>
                <div class="flex items-center justify-between">
                    <span>Últimos envios SMS</span>
                    <Button icon="pi pi-refresh" text rounded size="small" @click="loadLogs" :loading="logsLoading" />
                </div>
            </template>
            <template #content>
                <DataTable :value="recentLogs" :loading="logsLoading" size="small" stripedRows emptyMessage="Nenhum registro de SMS encontrado.">
                    <Column field="created_at" header="Data" style="width: 140px">
                        <template #body="{ data }">{{ formatDate(data.sent_at || data.failed_at || data.created_at) }}</template>
                    </Column>
                    <Column field="template_key" header="Template" />
                    <Column field="recipient_address" header="Destinatário" />
                    <Column field="status" header="Status" style="width: 100px">
                        <template #body="{ data }">
                            <Tag :value="data.status" :severity="logStatusSeverity(data.status)" />
                        </template>
                    </Column>
                    <Column field="failure_reason" header="Erro" style="max-width: 200px">
                        <template #body="{ data }">
                            <span class="text-sm text-red-500 truncate block" :title="data.failure_reason">{{ data.failure_reason || '—' }}</span>
                        </template>
                    </Column>
                </DataTable>
            </template>
        </Card>
    </div>
</template>
