<script setup lang="ts">
/**
 * Экран установки нового пароля по email-ссылке.
 *
 * Источник логики: ТЗ §1.7 / Прил. Г.4.3 — token действителен 60 мин,
 * пароль ≥10 символов (system_settings.password_min_length).
 *
 * Deep-link формат: /reset/{token}?email=user@example.ru
 *
 * Submit → useAuthStore.resetPassword() → POST /api/auth/reset-password:
 *   - На 200 → success-state + редирект на /login через 3 сек.
 *   - На 422 → form-error «ссылка недействительна или истекла».
 *   - На 429 → lockout-alert.
 */
import { extractValidationErrors } from '../../api/client';
import { useAuthStore } from '../../stores/auth';
import { computed, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';

const route = useRoute();
const router = useRouter();
const auth = useAuthStore();

const token = computed(() => String(route.params.token ?? ''));
const email = ref(typeof route.query.email === 'string' ? route.query.email : '');
const password = ref('');
const passwordConfirmation = ref('');
const showPassword = ref(false);
const errors = ref<Record<string, string[]>>({});
const submitted = ref(false);

const canSubmit = computed(
    () =>
        token.value.length > 0 &&
        email.value.length > 0 &&
        password.value.length >= 10 &&
        password.value === passwordConfirmation.value,
);

/**
 * Ошибка поля подтверждения: client-side проверка совпадения +
 * проброс backend-ошибки `password_confirmation` если придёт с 422.
 */
const confirmationError = computed<string[]>(() => {
    if (passwordConfirmation.value.length > 0 && password.value !== passwordConfirmation.value) {
        return ['Пароли не совпадают'];
    }
    return errors.value.password_confirmation ?? [];
});

async function handleSubmit() {
    errors.value = {};
    try {
        await auth.resetPassword({
            token: token.value,
            email: email.value,
            password: password.value,
            password_confirmation: passwordConfirmation.value,
        });
        submitted.value = true;
        // Редиректим через короткую задержку, чтобы user успел прочитать success.
        setTimeout(() => router.push('/login'), 3000);
    } catch (error: unknown) {
        const validationErrors = extractValidationErrors(error);
        if (validationErrors) {
            errors.value = validationErrors;
        } else if (auth.lockoutSeconds === null) {
            errors.value = { email: ['Произошла ошибка. Попробуйте позже.'] };
        }
    }
}
</script>

<template>
    <v-card variant="flat" :max-width="380" width="100%" color="transparent" class="reset-card">
        <header class="reset-header">
            <h1 class="text-h5 mb-1">Новый пароль</h1>
            <p class="text-body-2 text-medium-emphasis ma-0">Установите новый пароль для вашего аккаунта.</p>
        </header>

        <v-alert v-if="submitted" type="success" variant="tonal" density="comfortable" data-testid="reset-success">
            Пароль успешно изменён. Сейчас вы будете перенаправлены на страницу входа.
        </v-alert>

        <v-alert
            v-if="auth.lockoutSeconds !== null"
            type="error"
            variant="tonal"
            density="compact"
            data-testid="lockout-alert"
        >
            Слишком много попыток. Попробуйте через {{ Math.ceil(auth.lockoutSeconds / 60) }} мин.
        </v-alert>

        <v-form v-if="!submitted" class="reset-form" @submit.prevent="handleSubmit">
            <v-text-field
                v-model="email"
                label="Email"
                type="email"
                autocomplete="email"
                variant="outlined"
                density="comfortable"
                required
                :error-messages="errors.email"
            />

            <v-text-field
                v-model="password"
                label="Новый пароль"
                :type="showPassword ? 'text' : 'password'"
                autocomplete="new-password"
                placeholder="Минимум 10 символов"
                variant="outlined"
                density="comfortable"
                required
                :error-messages="errors.password"
            >
                <template #append-inner>
                    <v-icon
                        class="password-toggle"
                        :icon="showPassword ? 'mdi-eye-off' : 'mdi-eye'"
                        :aria-label="showPassword ? 'Скрыть пароль' : 'Показать пароль'"
                        role="button"
                        tabindex="0"
                        @click="showPassword = !showPassword"
                        @keydown.enter.prevent="showPassword = !showPassword"
                        @keydown.space.prevent="showPassword = !showPassword"
                    />
                </template>
            </v-text-field>

            <v-text-field
                v-model="passwordConfirmation"
                label="Повторите пароль"
                :type="showPassword ? 'text' : 'password'"
                autocomplete="new-password"
                variant="outlined"
                density="comfortable"
                required
                :error-messages="confirmationError"
            />

            <v-btn
                type="submit"
                color="primary"
                block
                size="large"
                variant="flat"
                :disabled="!canSubmit"
                :loading="auth.loading"
            >
                Сохранить пароль
            </v-btn>

            <v-btn :to="{ name: 'login' }" variant="text" block size="small" prepend-icon="mdi-arrow-left">
                Вернуться ко входу
            </v-btn>
        </v-form>
    </v-card>
</template>

<style scoped>
.reset-card {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.reset-header h1 {
    font-variation-settings: 'opsz' 26;
    letter-spacing: -0.018em;
}

.reset-form {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.password-toggle:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 1px;
    border-radius: 2px;
}
</style>
