<script setup lang="ts">
/**
 * TopupDialog — диалог пополнения рублёвого баланса (audit E1).
 *
 * MVP-stub: POST /api/billing/topup кредитует баланс немедленно (без
 * платёжного шлюза — реальная оплата post-Б-1). При успехе эмитит
 * `success` с новым балансом и закрывается.
 */
import { ref, computed, watch } from 'vue';
import { topup } from '../../api/billing';
import { extractErrorMessage, extractValidationErrors } from '../../api/client';
import { redirectTo } from '../../utils/redirect';

const model = defineModel<boolean>({ required: true });
const emit = defineEmits<{ success: [balanceRub: string] }>();

const PRESETS = [1000, 5000, 10000, 25000];

const amount = ref<number | null>(null);
const submitting = ref(false);
const errorMsg = ref<string | null>(null);

const amountError = computed<string | null>(() => {
    if (amount.value === null || !Number.isFinite(amount.value)) return null;
    if (amount.value < 100) return 'Минимум 100 ₽';
    if (amount.value > 1000000) return 'Максимум 1 000 000 ₽';
    return null;
});

const canSubmit = computed(() => Number.isFinite(amount.value) && amountError.value === null && !submitting.value);

// Сброс состояния при каждом открытии диалога (паттерн ReminderDialog/
// NewDealDialog) — нет префилла прошлой суммы и нет всплытия устаревшей ошибки.
watch(model, (open) => {
    if (open) {
        amount.value = null;
        errorMsg.value = null;
    }
});

function setPreset(value: number): void {
    amount.value = value;
}

async function submit(): Promise<void> {
    if (!canSubmit.value || amount.value === null) return;
    submitting.value = true;
    errorMsg.value = null;
    try {
        const res = await topup(amount.value);
        // Реальный шлюз (флаг ВКЛ): редирект на страницу оплаты ЮKassa.
        if (res.confirmation_url) {
            redirectTo(res.confirmation_url);
            return;
        }
        // Заглушка (флаг ВЫКЛ): баланс зачислен сразу.
        emit('success', res.balance_rub ?? '');
        model.value = false;
        amount.value = null;
    } catch (e) {
        const validation = extractValidationErrors(e);
        errorMsg.value = validation?.amount_rub?.[0] ?? extractErrorMessage(e);
    } finally {
        submitting.value = false;
    }
}

function close(): void {
    if (submitting.value) return;
    model.value = false;
    errorMsg.value = null;
}

defineExpose({ amount, submit, canSubmit, errorMsg });
</script>

<template>
    <v-dialog v-model="model" max-width="460">
        <v-card>
            <v-card-title class="text-h6">Пополнить баланс</v-card-title>
            <v-card-text>
                <v-text-field
                    v-model.number="amount"
                    type="number"
                    label="Сумма пополнения"
                    suffix="₽"
                    density="comfortable"
                    :error-messages="amountError ?? undefined"
                    autofocus
                />

                <div class="presets mb-2">
                    <v-chip v-for="p in PRESETS" :key="p" size="small" variant="outlined" @click="setPreset(p)">
                        {{ new Intl.NumberFormat('ru-RU').format(p) }} ₽
                    </v-chip>
                </div>

                <v-alert type="info" variant="tonal" density="compact" class="mt-2">
                    Платёжный шлюз подключается после регистрации юр. лица — на текущем этапе баланс пополняется сразу.
                </v-alert>

                <v-alert v-if="errorMsg" type="error" variant="tonal" density="compact" class="mt-3" role="alert">
                    {{ errorMsg }}
                </v-alert>
            </v-card-text>
            <v-card-actions>
                <v-spacer />
                <v-btn variant="text" :disabled="submitting" @click="close">Отмена</v-btn>
                <v-btn color="primary" variant="flat" :loading="submitting" :disabled="!canSubmit" @click="submit">
                    Пополнить
                </v-btn>
            </v-card-actions>
        </v-card>
    </v-dialog>
</template>

<style scoped>
.presets {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
</style>
