<script setup lang="ts">
/**
 * Админка SaaS → Система.
 *
 * Глобальные настройки SaaS-уровня (system_settings по schema v8.7 §10):
 * лимиты квот, тарифные планы, фичефлаги, fallback supplier_id.
 *
 * MVP — display + read-only edit-режим. Backend `/api/admin/system-settings`
 * + edit-flow подключаются отдельным коммитом.
 */
import { ADMIN_SYSTEM_SETTINGS } from '../../composables/mockAdmin';
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. Инициируется mock-данными (fallback если backend недоступен),
 * на mount — replace через `adminApi.listSystemSettings()`.
 *
 * Type-narrowing: AdminSystemSetting (mock) vs ApiSystemSetting различаются
 * только origin (mock vs БД), shape совместим — оба `{key, value, type, ...}`.
 */
const settingsState = reactive<AdminSystemSetting[]>([...ADMIN_SYSTEM_SETTINGS]);

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 оставляем mock (не очищаем UI). Показываем error-banner.
        fetchError.value = extractErrorMessage(err, 'Не удалось загрузить настройки с сервера. Показаны mock-данные.');
    } 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;
    }
}

defineExpose({ settingsState, editOpen, editSetting, openEdit, onSettingUpdated, loadSettings, loading, fetchError });
</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-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"
                            :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>
