<script setup lang="ts">
/**
 * Админка SaaS → Инциденты.
 *
 * Журнал инцидентов SaaS-уровня (incidents_log по schema v8.7 §9).
 * Категории: PDN-breach, service_outage, security, billing, data_loss.
 * При PDN-breach — обязательное уведомление РКН за 24 ч (152-ФЗ).
 *
 * Display + фильтр по статусу/severity. Данные с backend GET /api/admin/incidents.
 */
import { computed, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { usePolling } from '../../composables/usePolling';
import * as adminApi from '../../api/admin';

interface IncidentRow {
    id: number;
    incident_id: string;
    title: string;
    severity: 'low' | 'medium' | 'high' | 'critical';
    /** Backend type или mock-category — оба строки. */
    category: string;
    /** Backend: open/investigating/resolved. Mock включает closed — поддерживаем для legacy. */
    status: string;
    detected_at: string;
    affected_tenants: number;
    rkn_notified: boolean;
    rkn_deadline_at: string | null;
}

const router = useRouter();

const filterStatus = ref<string>('all');

const statusMap: Record<string, { label: string; color: string }> = {
    open: { label: 'Открыт', color: 'error' },
    investigating: { label: 'Расследуется', color: 'warning' },
    resolved: { label: 'Решён', color: 'info' },
    closed: { label: 'Закрыт', color: 'success' },
};
function statusInfo(s: string) {
    return statusMap[s] ?? { label: s, color: 'default' };
}

const severityMap: Record<string, { label: string; color: string }> = {
    critical: { label: 'Critical', color: 'error' },
    high: { label: 'High', color: 'warning' },
    medium: { label: 'Medium', color: 'info' },
    low: { label: 'Low', color: 'success' },
};
function severityInfo(s: string) {
    return severityMap[s] ?? { label: s, color: 'default' };
}

// Backend type slugs мапятся на UI-категории. data_breach → pdn_breach (UI-naming).
const categoryMap: Record<string, string> = {
    data_breach: 'Утечка ПДн',
    pdn_breach: 'Утечка ПДн',
    service_outage: 'Сбой сервиса',
    security_incident: 'Безопасность',
    security: 'Безопасность',
    billing_failure: 'Биллинг',
    billing: 'Биллинг',
    data_corruption: 'Потеря данных',
    data_loss: 'Потеря данных',
    integration_failure: 'Сбой интеграции',
    performance_degradation: 'Деградация производительности',
    other: 'Прочее',
};
function categoryLabel(c: string): string {
    return categoryMap[c] ?? c;
}

// Reactive — наполняется через loadIncidents (API).
const rowsState = reactive<IncidentRow[]>([]);
const stats = reactive({ open: 0, investigating: 0, rkn_pending: 0 });
const loading = ref(false);
const fetchError = ref(false);

async function loadIncidents() {
    loading.value = true;
    fetchError.value = false;
    try {
        const res = await adminApi.listAdminIncidents();
        const mapped: IncidentRow[] = res.incidents.map((i) => ({
            id: i.id,
            incident_id: i.incident_id,
            title: i.summary,
            severity: i.severity,
            category: i.type, // backend: data_breach/service_outage/etc.
            status: i.status,
            detected_at: i.detected_at,
            affected_tenants: i.affected_tenants_count,
            rkn_notified: i.rkn_notified,
            rkn_deadline_at: i.rkn_deadline_at,
        }));
        rowsState.splice(0, rowsState.length, ...mapped);
        stats.open = res.summary.open;
        stats.investigating = res.summary.investigating;
        stats.rkn_pending = res.summary.rkn_pending;
    } catch {
        fetchError.value = true;
    } finally {
        loading.value = false;
    }
}

onMounted(loadIncidents);
usePolling(loadIncidents);

const filteredRows = computed(() =>
    filterStatus.value === 'all' ? rowsState : rowsState.filter((r) => r.status === filterStatus.value),
);

defineExpose({ rowsState, stats, loading, fetchError, loadIncidents });

function formatDate(iso: string): string {
    return new Date(iso).toLocaleString('ru-RU', {
        day: '2-digit',
        month: '2-digit',
        year: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
    });
}
</script>

<template>
    <v-container fluid class="admin-incidents pa-6">
        <header class="page-head mb-4 d-flex justify-space-between align-start">
            <div>
                <h1 class="text-h4 page-title">Инциденты</h1>
                <p class="text-body-2 text-medium-emphasis ma-0">
                    Журнал инцидентов SaaS-уровня. PDN-breach — уведомление РКН за 24 ч (152-ФЗ).
                </p>
            </div>
            <v-btn
                variant="outlined"
                prepend-icon="mdi-refresh"
                :loading="loading"
                data-testid="reload-btn"
                @click="loadIncidents"
            >
                Обновить
            </v-btn>
        </header>

        <v-alert
            v-if="fetchError"
            type="warning"
            variant="tonal"
            density="compact"
            closable
            class="mb-4"
            data-testid="fetch-error-alert"
        >
            Не удалось загрузить инциденты. Попробуйте обновить.
        </v-alert>

        <v-row class="mb-4" data-testid="incidents-stats">
            <v-col cols="12" sm="4">
                <v-card variant="outlined" class="pa-3">
                    <div class="text-caption text-medium-emphasis">Открыто</div>
                    <div class="text-h6 text-error">{{ stats.open }}</div>
                </v-card>
            </v-col>
            <v-col cols="12" sm="4">
                <v-card variant="outlined" class="pa-3">
                    <div class="text-caption text-medium-emphasis">Расследуется</div>
                    <div class="text-h6 text-warning">{{ stats.investigating }}</div>
                </v-card>
            </v-col>
            <v-col cols="12" sm="4">
                <v-card variant="outlined" class="pa-3">
                    <div class="text-caption text-medium-emphasis">РКН-уведомлений</div>
                    <div class="text-h6 text-error">{{ stats.rkn_pending }}</div>
                </v-card>
            </v-col>
        </v-row>

        <v-card variant="outlined" class="pa-4">
            <div class="d-flex justify-space-between align-center mb-3 flex-wrap ga-2">
                <h2 class="text-h6 ma-0">События</h2>
                <v-btn-toggle v-model="filterStatus" mandatory density="comfortable" variant="outlined">
                    <v-btn value="all" size="small">Все</v-btn>
                    <v-btn value="open" size="small">Открыты</v-btn>
                    <v-btn value="investigating" size="small">Расследуются</v-btn>
                    <v-btn value="resolved" size="small">Решены</v-btn>
                    <v-btn value="closed" size="small">Закрыты</v-btn>
                </v-btn-toggle>
            </div>

            <v-list lines="three" class="incidents-list">
                <div
                    v-if="filteredRows.length === 0"
                    class="pa-6 text-center text-body-2 text-medium-emphasis"
                    data-testid="incidents-empty"
                >
                    Инцидентов нет.
                </div>
                <v-list-item
                    v-for="row in filteredRows"
                    :key="row.id"
                    class="incident-row"
                    :data-testid="`incident-row-${row.id}`"
                    style="cursor: pointer"
                    @click="router.push({ name: 'admin-incident-detail', params: { id: row.id } })"
                >
                    <div class="incident-header">
                        <span class="font-mono text-caption text-medium-emphasis">{{ row.incident_id }}</span>
                        <v-chip :color="severityInfo(row.severity).color" size="x-small" variant="tonal" class="ml-2">
                            {{ severityInfo(row.severity).label }}
                        </v-chip>
                        <v-chip :color="statusInfo(row.status).color" size="x-small" variant="tonal" class="ml-2">
                            {{ statusInfo(row.status).label }}
                        </v-chip>
                        <v-chip
                            v-if="
                                (row.category === 'pdn_breach' || row.category === 'data_breach') && !row.rkn_notified
                            "
                            color="error"
                            size="x-small"
                            variant="flat"
                            class="ml-2"
                        >
                            РКН pending
                        </v-chip>
                    </div>
                    <div class="font-weight-medium mt-1">{{ row.title }}</div>
                    <div class="text-caption text-medium-emphasis mt-1">
                        Категория: {{ categoryLabel(row.category) }} · Затронуто тенантов: {{ row.affected_tenants }} ·
                        Обнаружен: {{ formatDate(row.detected_at) }}
                        <span v-if="row.rkn_deadline_at"> · Дедлайн РКН: {{ formatDate(row.rkn_deadline_at) }}</span>
                    </div>
                </v-list-item>
            </v-list>
        </v-card>
    </v-container>
</template>

<style scoped>
.admin-incidents {
    max-width: 1200px;
}
.page-title {
    font-variation-settings: 'opsz' 28;
    letter-spacing: -0.018em;
}
.incident-row {
    padding-block: 12px;
    border-bottom: 1px solid #e1eeea;
}
.incident-row:last-child {
    border-bottom: none;
}
.incident-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
}
.font-mono {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
}
</style>
