<script setup lang="ts">
/**
 * Биллинг и тарифы — финансовый экран. Кошелёк ₽, баланс лидов,
 * текущий тариф, история транзакций и счета.
 *
 * Sprint 2 Plan C (E3): Overview-таб подвязан на real API
 * (GET /api/billing/wallet → BalanceCard + шапка; TransactionsTable и
 * InvoicesTable тянут данные сами). Списания — ChargesTab (Plan 4).
 * Sprint 5C (E4): pending-баннер убран — платёжного шлюза нет (Б-1), реального состояния «платёж в обработке» в БД не существует.
 * TopupDialog «Пополнить баланс» — Task 5 (E1).
 */
import { ref, computed, onMounted } from 'vue';
import BalanceCard from '../components/billing/BalanceCard.vue';
import TierPricesPanel from '../components/billing/TierPricesPanel.vue';
import TransactionsTable from '../components/billing/TransactionsTable.vue';
import InvoicesTable from '../components/billing/InvoicesTable.vue';
import TopupDialog from '../components/billing/TopupDialog.vue';
import ChargesTab from './billing/ChargesTab.vue';
import { formatPlain } from '../composables/billingFormatters';
import { getWallet, type Wallet } from '../api/billing';
import { extractErrorMessage } from '../api/client';
import { useTenantStore } from '../stores/tenantStore';

const activeView = ref<'overview' | 'charges'>('overview');
const tenant = useTenantStore();

const wallet = ref<Wallet | null>(null);
const loading = ref(true);
const loadError = ref<string | null>(null);
const topupOpen = ref(false);
const topupSnackbar = ref(false);
// Возврат с платёжной страницы шлюза (?topup=return): баланс зачислится по webhook.
const paymentReturn = ref(false);
const txTableRef = ref<InstanceType<typeof TransactionsTable> | null>(null);

const walletRub = computed(() => Number(wallet.value?.balance_rub ?? 0));
const affordableLeads = computed(() => wallet.value?.affordable_leads ?? 0);
const currentTierPriceRub = computed(() => wallet.value?.current_tier?.price_rub ?? '0.00');
const tiersPreview = computed(() => wallet.value?.tiers_preview ?? []);
const currentTierNo = computed(() => wallet.value?.current_tier?.no ?? null);

async function loadWallet(): Promise<void> {
    loading.value = true;
    loadError.value = null;
    try {
        wallet.value = await getWallet();
    } catch (e) {
        // Сброс устаревших данных: при неудачном повторе не оставляем
        // прошлый успешный wallet в памяти (защита от ложного рендера).
        wallet.value = null;
        loadError.value = extractErrorMessage(e, 'Не удалось загрузить данные биллинга.');
    } finally {
        loading.value = false;
    }
}

async function onTopupSuccess(): Promise<void> {
    // success-событие несёт новый баланс, но мы намеренно перезапрашиваем
    // кошелёк (loadWallet) — единый источник истины надёжнее точечного патча.
    topupOpen.value = false;
    topupSnackbar.value = true;
    await loadWallet();
    // Пополнение могло снять заморозку → обновляем статус баланса (баннер/индикатор).
    await tenant.load();
    txTableRef.value?.refresh();
}

onMounted(() => {
    paymentReturn.value = new URLSearchParams(window.location.search).get('topup') === 'return';
    void loadWallet();
    void tenant.load();
});

defineExpose({ loadWallet, wallet, topupOpen });
</script>

<template>
    <v-container fluid class="billing pa-6">
        <header class="page-head">
            <div>
                <h1 class="text-h4 mb-2 page-title">Биллинг и тарифы</h1>
                <div v-if="wallet" class="page-stats text-body-2 text-medium-emphasis">
                    <span
                        ><span class="num text-primary">{{ formatPlain(walletRub) }}</span> кошелёк</span
                    >
                </div>
            </div>
            <v-btn color="primary" variant="flat" prepend-icon="mdi-plus" @click="topupOpen = true"
                >Пополнить баланс</v-btn
            >
        </header>

        <v-alert
            v-if="paymentReturn"
            type="info"
            variant="tonal"
            density="comfortable"
            class="mt-4"
            closable
            @click:close="paymentReturn = false"
        >
            Платёж обрабатывается. Баланс обновится автоматически в течение минуты после подтверждения оплаты.
        </v-alert>

        <v-tabs v-model="activeView" color="primary" class="mt-4">
            <v-tab value="overview">Обзор</v-tab>
            <v-tab value="charges">Списания</v-tab>
        </v-tabs>

        <v-tabs-window v-model="activeView">
            <v-tabs-window-item value="overview">
                <div v-if="loading" class="py-12 d-flex justify-center">
                    <v-progress-circular indeterminate color="primary" />
                </div>

                <v-alert v-else-if="loadError" type="error" variant="tonal" class="mt-4" role="alert">
                    {{ loadError }}
                    <template #append>
                        <v-btn size="small" variant="text" @click="loadWallet">Повторить</v-btn>
                    </template>
                </v-alert>

                <template v-else-if="wallet">
                    <BalanceCard
                        :wallet-rub="walletRub"
                        :affordable-leads="affordableLeads"
                        :current-tier-price-rub="currentTierPriceRub"
                        :required-leads-per-day="tenant.requiredLeadsPerDay"
                        @topup="topupOpen = true"
                    />

                    <TierPricesPanel :tiers="tiersPreview" :current-tier-no="currentTierNo" />

                    <TransactionsTable ref="txTableRef" />

                    <InvoicesTable />
                </template>
            </v-tabs-window-item>

            <v-tabs-window-item value="charges">
                <ChargesTab />
            </v-tabs-window-item>
        </v-tabs-window>

        <TopupDialog v-model="topupOpen" @success="onTopupSuccess" />

        <v-snackbar v-model="topupSnackbar" color="success" :timeout="4000"> Баланс пополнен. </v-snackbar>
    </v-container>
</template>

<style scoped>
.billing {
    max-width: 1440px;
}

.page-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
}
.page-title {
    font-variation-settings: 'opsz' 28;
    letter-spacing: -0.018em;
}
.page-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}
.page-stats .sep {
    /* WCAG2AA 4.5:1: #6b6356 → 5.33:1 on ivory. */
    color: #6b6356;
}

.num {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-feature-settings: 'tnum';
    font-weight: 500;
}
</style>
