<script setup lang="ts">
/**
 * Админка → Тенанты. Список всех тенантов SaaS с балансами/тарифами/MRR.
 *
 * Sprint 4 Phase B/1 (audit O-refactor-04 хвост): UI-блоки выделены в
 * components/admin/tenants/{TenantsStatsHeader,TenantsFilters,TenantsTable}.
 * State (filterStatuses/filterTariffs/clearFilters/tenantsState/stats и др.)
 * остаётся в этом view ради `defineExpose`-контракта, который Vitest тесты
 * используют для прямого доступа.
 *
 * Источник дизайна: liderra_v8_handoff/concepts/v8_admin.html секция #page-tenants.
 * По схеме v8.7 §3 (tenants table) + ТЗ §22 (админка).
 *
 * Click по строке → /admin/tenants/{code} (карточка тенанта).
 */
import { computed, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { MOCK_STATS, MOCK_TENANTS, type AdminTenant, type TenantStatus } from '../../composables/mockTenants';
import { mapApiAdminTenant } from '../../composables/adminTenantsMapper';
import { usePolling } from '../../composables/usePolling';
import * as adminApi from '../../api/admin';
// NB: ImpersonationDialog оставлен sync-import — Vitest test через
// `findComponent({ name: 'ImpersonationDialog' })` + `stubs`, defineAsyncComponent
// ломает identity wrapper'а в test-utils.
import ImpersonationDialog from '../../components/admin/ImpersonationDialog.vue';
import TenantsStatsHeader from '../../components/admin/tenants/TenantsStatsHeader.vue';
import TenantsFilters from '../../components/admin/tenants/TenantsFilters.vue';
import TenantsTable from '../../components/admin/tenants/TenantsTable.vue';

const router = useRouter();

const tenantsState = reactive<AdminTenant[]>(MOCK_TENANTS.map((t) => ({ ...t })));
const stats = reactive({ ...MOCK_STATS });
const loading = ref(false);
const fetchError = ref(false);

async function loadTenants() {
    loading.value = true;
    fetchError.value = false;
    try {
        const res = await adminApi.listAdminTenants();
        const mapped = res.tenants.map((t) => mapApiAdminTenant(t));
        tenantsState.splice(0, tenantsState.length, ...mapped);
        stats.total = res.stats.total;
        stats.active = res.stats.active;
        stats.trial = res.stats.trial;
        stats.overdue = res.stats.overdue;
    } catch {
        fetchError.value = true;
    } finally {
        loading.value = false;
    }
}

onMounted(loadTenants);
usePolling(loadTenants);

function openTenantDetail(t: AdminTenant) {
    router.push({ name: 'admin-tenant-detail', params: { code: t.code } });
}

const search = ref('');
const filterStatuses = ref<TenantStatus[]>([]);
const filterTariffs = ref<string[]>([]);

const impersonationOpen = ref(false);
const impersonationTenant = ref<AdminTenant | null>(null);

const availableTariffs = computed(() => Array.from(new Set(tenantsState.map((t) => t.tariff))).sort());

function clearFilters() {
    filterStatuses.value = [];
    filterTariffs.value = [];
}

const ADMIN_USER_ID = 1;

function openImpersonation(tenant: AdminTenant) {
    impersonationTenant.value = tenant;
    impersonationOpen.value = true;
}

defineExpose({
    filterStatuses,
    filterTariffs,
    clearFilters,
    impersonationOpen,
    impersonationTenant,
    tenantsState,
    stats,
    loading,
    fetchError,
    loadTenants,
});

const filteredTenants = computed<AdminTenant[]>(() => {
    const q = search.value.trim().toLowerCase();
    const statuses = new Set(filterStatuses.value);
    const tariffs = new Set(filterTariffs.value);

    return tenantsState.filter((t) => {
        if (statuses.size > 0 && !statuses.has(t.status)) return false;
        if (tariffs.size > 0 && !tariffs.has(t.tariff)) return false;
        if (q) {
            const haystack = `${t.name} ${t.inn} ${t.code}`.toLowerCase();
            if (!haystack.includes(q)) return false;
        }
        return true;
    });
});
</script>

<template>
    <v-container fluid class="admin-tenants pa-6">
        <TenantsStatsHeader :stats="stats" :loading="loading" @refresh="loadTenants" />

        <v-alert
            v-if="fetchError"
            type="warning"
            variant="tonal"
            density="compact"
            closable
            class="mt-3"
            data-testid="fetch-error-alert"
        >
            Backend недоступен — показаны mock-данные.
        </v-alert>

        <TenantsFilters
            :search="search"
            :filter-statuses="filterStatuses"
            :filter-tariffs="filterTariffs"
            :available-tariffs="availableTariffs"
            @update:search="search = $event"
            @update:filter-statuses="filterStatuses = $event"
            @update:filter-tariffs="filterTariffs = $event"
            @clear="clearFilters"
        />

        <TenantsTable :tenants="filteredTenants" @row-click="openTenantDetail" @impersonate="openImpersonation" />

        <ImpersonationDialog v-model="impersonationOpen" :tenant="impersonationTenant" :requested-by="ADMIN_USER_ID" />
    </v-container>
</template>

<style scoped>
.admin-tenants {
    max-width: 1440px;
}
</style>
