<script setup lang="ts">
/**
 * SessionsTable — активные сессии пользователя (UI-аудит 21.06.2026, Security).
 *
 * Реальные данные: GET /api/account/security → sessions (из user_sessions).
 * «Завершить» (DELETE /api/account/sessions/{id}) реально убивает сессию
 * (удаление из Redis). Заменяет прежний статичный mock из 3 фейк-сессий.
 */
import { onMounted, ref } from 'vue';
import { getAccountSecurity, revokeSession, type ActiveSession } from '../../../api/account';

const sessions = ref<ActiveSession[]>([]);
const loading = ref(true);
const fetchError = ref(false);
const revokingId = ref<number | null>(null);
const toastOpen = ref(false);
const toastText = ref('');

function formatRelative(iso: string | null): string {
    if (!iso) return '';
    const diffMs = Date.now() - new Date(iso).getTime();
    const min = Math.floor(diffMs / 60000);
    if (min < 1) return 'только что';
    if (min < 60) return `${min} мин назад`;
    const h = Math.floor(min / 60);
    if (h < 24) return `${h} ч назад`;
    const d = Math.floor(h / 24);
    if (d < 30) return `${d} дн назад`;
    return new Date(iso).toLocaleDateString('ru-RU');
}

async function load(): Promise<void> {
    loading.value = true;
    fetchError.value = false;
    try {
        const data = await getAccountSecurity();
        sessions.value = data.sessions;
    } catch {
        fetchError.value = true;
    } finally {
        loading.value = false;
    }
}

async function revoke(id: number): Promise<void> {
    revokingId.value = id;
    try {
        await revokeSession(id);
        sessions.value = sessions.value.filter((s) => s.id !== id);
        toastText.value = 'Сессия завершена.';
        toastOpen.value = true;
    } catch {
        toastText.value = 'Не удалось завершить сессию.';
        toastOpen.value = true;
    } finally {
        revokingId.value = null;
    }
}

onMounted(load);
</script>

<template>
    <v-card variant="outlined" class="pa-4">
        <h3 class="text-subtitle-2 mb-3">Активные сессии</h3>

        <v-alert
            v-if="fetchError"
            type="warning"
            variant="tonal"
            density="compact"
            data-testid="sessions-error"
        >
            Не удалось загрузить сессии.
        </v-alert>

        <div v-else-if="loading" class="text-body-2 text-medium-emphasis">Загрузка…</div>

        <p v-else-if="sessions.length === 0" class="text-body-2 text-medium-emphasis ma-0">
            Активных сессий не найдено.
        </p>

        <ul v-else class="sessions-list">
            <li v-for="s in sessions" :key="s.id" class="session-row">
                <div class="session-info">
                    <div class="session-device">
                        {{ s.device }}
                        <v-chip v-if="s.current" color="primary" size="x-small" variant="tonal" class="ml-2">
                            эта сессия
                        </v-chip>
                    </div>
                    <div class="session-meta text-caption text-medium-emphasis">
                        {{ s.ip || 'IP неизвестен' }} · {{ formatRelative(s.at) }}
                    </div>
                </div>
                <v-btn
                    v-if="!s.current"
                    variant="text"
                    size="small"
                    color="error"
                    :loading="revokingId === s.id"
                    :data-testid="`revoke-session-${s.id}`"
                    @click="revoke(s.id)"
                >
                    Завершить
                </v-btn>
            </li>
        </ul>

        <v-snackbar v-model="toastOpen" :timeout="3000" location="bottom right">
            {{ toastText }}
        </v-snackbar>
    </v-card>
</template>

<style scoped>
.sessions-list {
    list-style: none;
    padding: 0;
    margin: 0;
}
.session-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 0;
    border-bottom: 1px solid #f0ede4;
}
.session-row:last-child {
    border-bottom: none;
}
.session-device {
    font-weight: 500;
    color: #081319;
}
</style>
