<script setup lang="ts">
/**
 * TransactionsTable — server-driven история транзакций с табами
 * (Все / Пополнения / Списания / Возвраты). Данные — GET
 * /api/billing/transactions (E3). Паттерн self-fetching из ChargesTab.
 */
import { ref, onMounted } from 'vue';
import { getTransactions, type BillingTransaction } from '../../api/billing';
import { formatCost, txAmountClass } from '../../composables/billingFormatters';

interface Tab {
    id: string;
    label: string;
    type: string | null;
}

const TABS: Tab[] = [
    { id: 'all', label: 'Все', type: null },
    { id: 'topup', label: 'Пополнения', type: 'topup' },
    { id: 'lead_charge', label: 'Списания', type: 'lead_charge' },
];

const activeTab = ref<string>('all');
const rows = ref<BillingTransaction[]>([]);
const total = ref(0);
const loading = ref(false);
const loadError = ref<string | null>(null);
const page = ref(1);

const headers = [
    { title: 'Дата', key: 'created_at', sortable: false },
    { title: 'Операция', key: 'description', sortable: false },
    { title: 'ID', key: 'code', sortable: false, width: 120 },
    { title: 'Сумма', key: 'amount_rub', align: 'end' as const, sortable: false, width: 140 },
];

/**
 * Ярлык столбца «Операция». Показываем сохранённый description, если он есть;
 * иначе — человекочитаемый ярлык по типу операции. Корень F4: списания за лид
 * (lead_charge) создаются LedgerService без description, отчего ячейка была пустой.
 */
const OP_LABELS: Record<string, string> = {
    lead_charge: 'Списание за лид',
    topup: 'Пополнение баланса',
    migration: 'Конвертация лидов в ₽',
};

function opLabel(tx: BillingTransaction): string {
    return tx.description?.trim() || OP_LABELS[tx.type] || '—';
}

function formatWhen(iso: string): string {
    return new Date(iso).toLocaleString('ru-RU', {
        timeZone: 'Europe/Moscow',
        year: '2-digit',
        day: '2-digit',
        month: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
    });
}

/** Числовое значение движения из display_amount_rub. */
function txAmountValue(tx: BillingTransaction): number {
    return Number(tx.display_amount_rub);
}

/** Текст суммы из display_amount_rub. */
function txAmountText(tx: BillingTransaction): string {
    return formatCost(Number(tx.display_amount_rub));
}

async function load(): Promise<void> {
    loading.value = true;
    loadError.value = null;
    try {
        const tab = TABS.find((t) => t.id === activeTab.value);
        const params: { page: number; type?: string } = { page: page.value };
        if (tab?.type) params.type = tab.type;
        const res = await getTransactions(params);
        rows.value = res.data;
        total.value = res.meta.total;
    } catch {
        loadError.value = 'Не удалось загрузить транзакции.';
        rows.value = [];
        total.value = 0;
    } finally {
        loading.value = false;
    }
}

async function changeTab(id: string): Promise<void> {
    activeTab.value = id;
    page.value = 1;
    await load();
}

async function loadOptions(opts: { page: number }): Promise<void> {
    page.value = opts.page;
    await load();
}

async function refresh(): Promise<void> {
    page.value = 1;
    await load();
}

onMounted(load);

defineExpose({ load, refresh, changeTab, activeTab, total, rows });
</script>

<template>
    <v-card variant="outlined" class="mt-4 panel">
        <div class="panel-h pa-4">
            <h2 class="text-h6 panel-title ma-0">История транзакций</h2>
            <v-btn-toggle :model-value="activeTab" mandatory color="primary" density="comfortable" variant="text">
                <v-btn v-for="tab in TABS" :key="tab.id" :value="tab.id" size="small" @click="changeTab(tab.id)">
                    {{ tab.label }}
                </v-btn>
            </v-btn-toggle>
        </div>

        <v-alert v-if="loadError" type="error" variant="tonal" density="compact" class="mx-4 mb-4" role="alert">
            {{ loadError }}
        </v-alert>

        <v-data-table-server
            :headers="headers"
            :items="rows"
            :items-length="total"
            :loading="loading"
            :items-per-page="20"
            density="comfortable"
            @update:options="loadOptions"
        >
            <template #[`item.created_at`]="{ item }">
                <span class="tx-when num">{{ formatWhen(item.created_at) }}</span>
            </template>
            <template #[`item.description`]="{ item }">
                <span class="tx-op">{{ opLabel(item) }}</span>
            </template>
            <template #[`item.code`]="{ item }">
                <span class="tx-id">#{{ item.code }}</span>
            </template>
            <template #[`item.amount_rub`]="{ item }">
                <span class="num" :class="txAmountClass(txAmountValue(item))">
                    {{ txAmountText(item) }}
                </span>
            </template>
        </v-data-table-server>
    </v-card>
</template>

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

.panel {
    background: #fff;
}
.panel-h {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
}
.panel-title {
    font-variation-settings: 'opsz' 18;
    letter-spacing: -0.01em;
}

.tx-when {
    font-size: 12px;
    color: #66635c;
}
.tx-id {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 12px;
    color: #66635c;
}
.tx-amount-up {
    color: #1b6e3b;
}
.tx-amount-down {
    color: #b83a3a;
}
.tx-amount-neutral {
    color: #66635c;
}
</style>
