<script setup lang="ts">
/**
 * Админка SaaS → Система.
 *
 * Глобальные настройки SaaS-уровня (system_settings по schema v8.7 §10):
 * лимиты квот, тарифные планы, фичефлаги, fallback supplier_id.
 *
 * Display + edit-режим. Данные с backend GET /api/admin/system-settings.
 */
import type { AdminSystemSetting } from '../../composables/mockAdmin';
import * as adminApi from '../../api/admin';
import type { SystemSetting as ApiSystemSetting } from '../../api/admin';
import { extractErrorMessage } from '../../api/client';
import { computed, onMounted, reactive, ref } from 'vue';
import SystemSettingEditDialog from '../../components/admin/SystemSettingEditDialog.vue';

const search = ref('');
const loading = ref(false);
const fetchError = ref<string | null>(null);

/**
 * Settings-state. Наполняется на mount через `adminApi.listSystemSettings()`.
 * До загрузки и при ошибке — пустой; ошибка показывается через fetchError-banner.
 */
const settingsState = reactive<AdminSystemSetting[]>([]);

async function loadSettings() {
    loading.value = true;
    fetchError.value = null;
    try {
        const fromApi = await adminApi.listSystemSettings();
        // Replace всё содержимое сохранив reactive-ref.
        settingsState.splice(0, settingsState.length, ...(fromApi as unknown as AdminSystemSetting[]));
    } catch (err) {
        // На fail — settingsState пустой, показываем error-banner.
        fetchError.value = extractErrorMessage(err, 'Не удалось загрузить настройки с сервера. Попробуйте обновить.');
    } finally {
        loading.value = false;
    }
}

onMounted(() => {
    loadSettings();
});

const filteredSettings = computed(() => {
    const q = search.value.trim().toLowerCase();
    if (!q) return settingsState;
    return settingsState.filter((s) => s.key.toLowerCase().includes(q) || s.description.toLowerCase().includes(q));
});

const typeColor: Record<AdminSystemSetting['type'], string> = {
    int: 'info',
    string: 'success',
    bool: 'warning',
    json: 'secondary',
};

function formatDate(iso: string): string {
    return new Date(iso).toLocaleDateString('ru-RU', {
        day: '2-digit',
        month: '2-digit',
        year: 'numeric',
    });
}

const editOpen = ref(false);
const editSetting = ref<ApiSystemSetting | null>(null);
const ADMIN_USER_ID = 1;

function openEdit(s: AdminSystemSetting) {
    editSetting.value = {
        key: s.key,
        value: s.value,
        type: s.type as ApiSystemSetting['type'],
        description: s.description,
        updated_at: s.updated_at,
        updated_by: null,
    };
    editOpen.value = true;
}

function onSettingUpdated(payload: { key: string; value: string; updated_at: string }) {
    const target = settingsState.find((s) => s.key === payload.key);
    if (target) {
        target.value = payload.value;
        target.updated_at = payload.updated_at;
    }
}

// ─── Ручной баланс Яндекс 360 (почта) ───────────────────────────────────────
const y360Input = ref<string>('');
const y360Status = ref<adminApi.Yandex360BalanceStatus>({ balance: null, updated_at: null });
const y360Saving = ref(false);
const y360Error = ref<string | null>(null);
const Y360_TOPUP_URL = 'https://admin.yandex.ru/products';

async function loadY360Status() {
    try {
        y360Status.value = await adminApi.getYandex360Balance();
        y360Input.value = y360Status.value.balance !== null ? String(y360Status.value.balance) : '';
    } catch {
        // тихо: статус не критичен для экрана
    }
}

async function saveY360Balance() {
    y360Saving.value = true;
    y360Error.value = null;
    try {
        const val = y360Input.value.trim() === '' ? null : Number(y360Input.value.replace(',', '.'));
        y360Status.value = await adminApi.setYandex360Balance(val);
    } catch (err) {
        y360Error.value = extractErrorMessage(err, 'Не удалось сохранить баланс.');
    } finally {
        y360Saving.value = false;
    }
}

onMounted(() => {
    loadY360Status();
});

defineExpose({ settingsState, editOpen, editSetting, openEdit, onSettingUpdated, loadSettings, loading, fetchError, y360Input, y360Status, saveY360Balance });
</script>

<template>
    <v-container fluid class="admin-system pa-6">
        <header class="page-head mb-4">
            <h1 class="text-h4 page-title">Система</h1>
            <p class="text-body-2 text-medium-emphasis ma-0">
                Глобальные настройки SaaS: лимиты квот, тарифные планы, фичефлаги.
            </p>
        </header>

        <v-alert type="info" variant="tonal" class="mb-4" density="compact">
            Edit-flow требует основания ≥30 символов и двухстадийного подтверждения; результат записывается в
            <code>saas_admin_audit_log</code> с hash-chain (OPEN-И-15).
        </v-alert>

        <v-card variant="outlined" class="mb-4" data-testid="y360-balance-card">
            <v-card-title class="text-subtitle-1">✉️ Баланс почты (Яндекс 360)</v-card-title>
            <v-card-text>
                <v-alert type="info" variant="tonal" density="compact" class="mb-3">
                    У Яндекс 360 нет автоматического способа узнать баланс, поэтому впишите сумму вручную —
                    она из кабинета Яндекс 360 → «Оплата и тариф» (строка «Баланс»). Обновляйте по мере надобности;
                    на плитке она покажется со светофором. Кнопка «Открыть оплату» ведёт прямо в кабинет.
                </v-alert>
                <div class="mb-2 text-body-2">
                    Текущий баланс:
                    <strong v-if="y360Status.balance !== null" class="text-success">{{ y360Status.balance }} ₽</strong>
                    <strong v-else class="text-medium-emphasis">не задан</strong>
                    <span v-if="y360Status.updated_at" class="text-medium-emphasis">
                        · обновлён {{ formatDate(y360Status.updated_at) }}</span>
                </div>
                <v-alert v-if="y360Error" type="warning" variant="tonal" density="compact" class="mb-2">
                    {{ y360Error }}
                </v-alert>
                <div class="d-flex align-center ga-3 flex-wrap">
                    <v-text-field
                        v-model="y360Input"
                        label="Баланс, ₽"
                        type="number"
                        density="compact"
                        hide-details
                        style="max-width: 200px"
                    />
                    <v-btn color="primary" :loading="y360Saving" @click="saveY360Balance">Сохранить</v-btn>
                    <v-btn variant="text" :href="Y360_TOPUP_URL" target="_blank" prepend-icon="mdi-open-in-new">
                        Открыть оплату
                    </v-btn>
                </div>
            </v-card-text>
        </v-card>

        <v-alert
            v-if="fetchError"
            type="warning"
            variant="tonal"
            class="mb-4"
            density="compact"
            data-testid="fetch-error-alert"
            closable
            @click:close="fetchError = null"
        >
            {{ fetchError }}
        </v-alert>

        <v-card variant="outlined" class="pa-4">
            <div class="d-flex justify-space-between align-center mb-3 ga-2 flex-wrap">
                <h2 class="text-h6 ma-0">system_settings</h2>
                <v-spacer />
                <v-text-field
                    v-model="search"
                    label="Поиск"
                    placeholder="по ключу или описанию"
                    prepend-inner-icon="mdi-magnify"
                    density="compact"
                    variant="outlined"
                    hide-details
                    clearable
                    style="max-width: 320px"
                />
                <v-btn
                    variant="outlined"
                    size="small"
                    prepend-icon="mdi-refresh"
                    :loading="loading"
                    data-testid="reload-btn"
                    @click="loadSettings"
                >
                    Обновить
                </v-btn>
            </div>

            <v-list class="settings-list">
                <v-list-item
                    v-for="setting in filteredSettings"
                    :key="setting.key"
                    class="setting-row"
                    data-testid="setting-row"
                >
                    <div class="setting-header">
                        <span class="setting-key font-mono">{{ setting.key }}</span>
                        <v-chip :color="typeColor[setting.type]" size="x-small" variant="tonal" class="ml-2">
                            {{ setting.type }}
                        </v-chip>
                        <v-spacer />
                        <v-btn
                            variant="text"
                            size="small"
                            density="comfortable"
                            prepend-icon="mdi-pencil"
                            :aria-label="`Изменить настройку ${setting.key}`"
                            :data-testid="`edit-${setting.key}-btn`"
                            @click="openEdit(setting)"
                        >
                            Изменить
                        </v-btn>
                    </div>
                    <div class="setting-value font-mono mt-1">{{ setting.value }}</div>
                    <div class="text-caption text-medium-emphasis mt-1">
                        {{ setting.description }} · обновлено {{ formatDate(setting.updated_at) }}
                    </div>
                </v-list-item>
            </v-list>
        </v-card>

        <SystemSettingEditDialog
            v-model="editOpen"
            :setting="editSetting"
            :requested-by="ADMIN_USER_ID"
            @updated="onSettingUpdated"
        />
    </v-container>
</template>

<style scoped>
.admin-system {
    max-width: 1100px;
}
.page-title {
    font-variation-settings: 'opsz' 28;
    letter-spacing: -0.018em;
}
.setting-row {
    padding-block: 12px;
    border-bottom: 1px solid #e1eeea;
}
.setting-row:last-child {
    border-bottom: none;
}
.setting-header {
    display: flex;
    align-items: center;
}
.setting-key {
    font-weight: 500;
    font-size: 14px;
    color: #081319;
}
.setting-value {
    font-size: 13px;
    background: #f6f3ec;
    padding: 4px 8px;
    border-radius: 4px;
    display: inline-block;
}
.font-mono {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
}
</style>
