<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/views/pages/saas/SaasTenantFeaturesPage.vue
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
-->
<script setup>
import { ref, computed, onMounted, watch } from 'vue';
// Audit alta (2026-05-20): supabase direto extraído pra service module.
import {
    listTenants as svcListTenants,
    listFeatureCatalog as svcListFeatures,
    loadTenantFeatureState as svcLoadTenantState,
    setFeatureException as svcSetFeatureException
} from '@/services/tenantFeatureAdminService';

import Select from 'primevue/select';
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';
import Tag from 'primevue/tag';
import Button from 'primevue/button';
import Dialog from 'primevue/dialog';
import Textarea from 'primevue/textarea';
import InputText from 'primevue/inputtext';
import { useToast } from 'primevue/usetoast';

const toast = useToast();

const loading = ref(false);
const saving = ref(false);

const tenants = ref([]);
const features = ref([]);
const selectedTenantId = ref(null);

const planAllowed = ref(new Set());
const planKey = ref(null);
const overrides = ref({});
const exceptionsLog = ref([]);

const filterText = ref('');

const dlg = ref({
    open: false,
    feature: null,
    nextEnabled: false,
    isException: false,
    reason: ''
});

const selectedTenant = computed(() => tenants.value.find((t) => t.id === selectedTenantId.value) || null);

const rows = computed(() => {
    const ft = String(filterText.value || '').trim().toLowerCase();
    return features.value
        .filter((f) => !ft || f.key.toLowerCase().includes(ft) || (f.name || '').toLowerCase().includes(ft))
        .map((f) => {
            const inPlan = planAllowed.value.has(f.key);
            const ov = overrides.value[f.key];
            let status = 'inactive';
            if (ov === true) status = inPlan ? 'active_plan' : 'exception';
            else if (ov === false) status = 'off_pref';
            else status = inPlan ? 'active_plan' : 'inactive';
            return { ...f, in_plan: inPlan, override: ov, status };
        });
});

function statusLabel(s) {
    return (
        {
            active_plan: 'Ativa (plano)',
            off_pref: 'Desligada (preferência)',
            exception: 'Exceção comercial',
            inactive: 'Não disponível'
        }[s] || s
    );
}

function statusSeverity(s) {
    return (
        {
            active_plan: 'success',
            off_pref: 'warn',
            exception: 'info',
            inactive: 'secondary'
        }[s] || 'secondary'
    );
}

async function loadTenants() {
    try {
        tenants.value = await svcListTenants();
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao carregar clínicas', life: 4000 });
    }
}

async function loadFeatures() {
    try {
        features.value = await svcListFeatures();
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao carregar catálogo', life: 4000 });
    }
}

async function loadTenantState(tenantId) {
    if (!tenantId) {
        planAllowed.value = new Set();
        planKey.value = null;
        overrides.value = {};
        exceptionsLog.value = [];
        return;
    }

    loading.value = true;
    try {
        const state = await svcLoadTenantState(tenantId);
        planAllowed.value = state.planAllowed;
        planKey.value = state.planKey;
        overrides.value = state.overrides;
        exceptionsLog.value = state.exceptionsLog;
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro ao carregar tenant', detail: e?.message || 'falha', life: 4000 });
    } finally {
        loading.value = false;
    }
}

function openDialog(feature, nextEnabled) {
    const isException = nextEnabled === true && !planAllowed.value.has(feature.key);
    dlg.value = {
        open: true,
        feature,
        nextEnabled,
        isException,
        reason: ''
    };
}

async function confirmChange() {
    const { feature, nextEnabled, isException } = dlg.value;
    const reason = String(dlg.value.reason || '').trim();

    if (isException && reason.length < 4) {
        toast.add({ severity: 'warn', summary: 'Motivo obrigatório', detail: 'Exceção comercial exige motivo (≥ 4 caracteres).', life: 3500 });
        return;
    }

    saving.value = true;

    try {
        await svcSetFeatureException(selectedTenantId.value, feature.key, nextEnabled, reason);

        toast.add({
            severity: 'success',
            summary: 'Atualizado',
            detail: `${feature.name || feature.key}: ${nextEnabled ? 'ativada' : 'desativada'}${isException ? ' (exceção)' : ''}`,
            life: 3000
        });

        dlg.value.open = false;
        await loadTenantState(selectedTenantId.value);
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Falha', detail: e?.message || 'erro ao alterar feature', life: 4500 });
    } finally {
        saving.value = false;
    }
}

function clearOverride(feature) {
    // "Limpar override" = setar conforme o plano (volta ao padrão)
    const back = planAllowed.value.has(feature.key);
    openDialog(feature, back);
    dlg.value.reason = 'Limpeza de override (volta ao padrão do plano)';
}

watch(selectedTenantId, async (id) => {
    await loadTenantState(id);
});

onMounted(async () => {
    await Promise.all([loadTenants(), loadFeatures()]);
});
</script>

<template>
    <div class="flex flex-col gap-4 p-4">
        <!-- Header -->
        <div class="cfg-subheader">
            <div class="cfg-subheader__icon"><i class="pi pi-sitemap" /></div>
            <div class="min-w-0 flex-1">
                <div class="cfg-subheader__title">Recursos por Clínica</div>
                <div class="cfg-subheader__sub">Overrides de features por tenant. Exceções comerciais exigem motivo e ficam logadas.</div>
            </div>
        </div>

        <div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-5">
            <div class="grid grid-cols-1 md:grid-cols-3 gap-3">
                <div>
                    <label class="text-[0.85rem] text-[var(--text-color-secondary)]">Clínica</label>
                    <Select v-model="selectedTenantId" :options="tenants" optionLabel="name" optionValue="id" placeholder="Selecione…" class="w-full mt-1" filter showClear />
                </div>
                <div class="md:col-span-2 flex items-end">
                    <div v-if="selectedTenant" class="text-[0.95rem]">
                        <span class="text-[var(--text-color-secondary)]">Plano ativo:</span>
                        <Tag :value="planKey || 'sem assinatura'" :severity="planKey ? 'info' : 'warn'" class="ml-2" />
                    </div>
                </div>
            </div>
        </div>

        <div v-if="selectedTenantId" class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-5">
            <div class="flex items-center justify-between gap-3 mb-3">
                <div class="font-semibold">Catálogo de features</div>
                <InputText v-model="filterText" placeholder="filtrar por chave ou nome…" class="max-w-xs" />
            </div>

            <DataTable :value="rows" :loading="loading" dataKey="id" responsiveLayout="scroll" size="small" stripedRows>
                <Column field="key" header="Chave" sortable>
                    <template #body="{ data }">
                        <span class="font-mono text-[0.85rem]">{{ data.key }}</span>
                    </template>
                </Column>
                <Column field="name" header="Nome" sortable />
                <Column header="No plano">
                    <template #body="{ data }">
                        <Tag :value="data.in_plan ? 'sim' : 'não'" :severity="data.in_plan ? 'success' : 'secondary'" />
                    </template>
                </Column>
                <Column header="Estado">
                    <template #body="{ data }">
                        <Tag :value="statusLabel(data.status)" :severity="statusSeverity(data.status)" />
                    </template>
                </Column>
                <Column header="Ações" style="width: 320px">
                    <template #body="{ data }">
                        <div class="flex gap-2 flex-wrap">
                            <Button v-if="data.status === 'active_plan'" label="Desligar (preferência)" icon="pi pi-times" size="small" severity="warn" outlined @click="openDialog(data, false)" />

                            <Button v-if="data.status === 'off_pref'" label="Religar" icon="pi pi-check" size="small" severity="success" outlined @click="openDialog(data, true)" />

                            <Button v-if="data.status === 'inactive'" label="Liberar exceção" icon="pi pi-key" size="small" severity="info" outlined @click="openDialog(data, true)" />

                            <Button v-if="data.status === 'exception'" label="Cancelar exceção" icon="pi pi-undo" size="small" severity="danger" outlined @click="openDialog(data, false)" />

                            <Button v-if="data.override !== undefined" label="Limpar override" icon="pi pi-eraser" size="small" text @click="clearOverride(data)" />
                        </div>
                    </template>
                </Column>
            </DataTable>
        </div>

        <div v-if="selectedTenantId && exceptionsLog.length" class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-5">
            <div class="font-semibold mb-3">Histórico de mudanças (50 mais recentes)</div>
            <DataTable :value="exceptionsLog" size="small" stripedRows responsiveLayout="scroll">
                <Column header="Quando">
                    <template #body="{ data }">{{ new Date(data.created_at).toLocaleString('pt-BR') }}</template>
                </Column>
                <Column field="feature_key" header="Feature">
                    <template #body="{ data }"><span class="font-mono text-[0.85rem]">{{ data.feature_key }}</span></template>
                </Column>
                <Column header="Estado">
                    <template #body="{ data }">
                        <Tag :value="data.enabled ? 'on' : 'off'" :severity="data.enabled ? 'success' : 'warn'" />
                    </template>
                </Column>
                <Column field="reason" header="Motivo">
                    <template #body="{ data }">
                        <span :class="!data.reason && 'opacity-50 italic'">{{ data.reason || '—' }}</span>
                    </template>
                </Column>
                <Column field="created_by" header="Por">
                    <template #body="{ data }"><span class="font-mono text-[0.75rem] opacity-70">{{ data.created_by?.slice(0, 8) || '—' }}</span></template>
                </Column>
            </DataTable>
        </div>

        <Dialog v-model:visible="dlg.open" :header="`${dlg.nextEnabled ? 'Ativar' : 'Desativar'}: ${dlg.feature?.name || dlg.feature?.key}`" modal :style="{ width: '480px' }" :closable="!saving">
            <div v-if="dlg.isException" class="rounded-md border border-amber-400/40 bg-amber-400/10 px-3 py-2 mb-3 text-[0.9rem]">
                <i class="pi pi-exclamation-triangle text-amber-500 mr-2" />
                Esta feature <b>não está no plano</b> do tenant. Ao confirmar, vai ser registrada como <b>exceção comercial</b>.
            </div>

            <label class="text-[0.85rem] text-[var(--text-color-secondary)]">Motivo {{ dlg.isException ? '(obrigatório)' : '(opcional)' }}</label>
            <Textarea v-model="dlg.reason" rows="3" class="w-full mt-1" :placeholder="dlg.isException ? 'Ex: Cliente pagou R$50/mês via PIX em 19/04' : 'Ex: Tenant desligou módulo por preferência'" autoResize />

            <template #footer>
                <Button label="Cancelar" text :disabled="saving" @click="dlg.open = false" />
                <Button :label="dlg.nextEnabled ? 'Ativar' : 'Desativar'" :icon="dlg.nextEnabled ? 'pi pi-check' : 'pi pi-times'" :severity="dlg.isException ? 'info' : dlg.nextEnabled ? 'success' : 'warn'" :loading="saving" @click="confirmChange" />
            </template>
        </Dialog>
    </div>
</template>