import { defineStore } from 'pinia';
import { computed, ref } from 'vue';
import * as authApi from '../api/auth';
import type { AuthUser, LoginPayload, RegisterPayload, RegisterResult, ResetPasswordPayload } from '../api/auth';
import { extractRateLimitRetry } from '../api/client';

/**
 * Auth-store: состояние текущего user'а + auth-actions через Sanctum SPA.
 *
 * Использование:
 *   const auth = useAuthStore();
 *   await auth.login({ email, password });        // редирект на /dashboard или /2fa
 *   await auth.fetchMe();                          // restore session при старте app
 *   if (auth.isAuthenticated) { ... }
 *   await auth.logout();
 *
 * Не входит:
 * - Persist user в localStorage (session-cookie держит state на backend; при
 *   page-reload `fetchMe()` восстанавливает user). Если cookie expired — 401
 *   и redirect на /login через Vue Router auth-guard.
 */
export const useAuthStore = defineStore('auth', () => {
    const user = ref<AuthUser | null>(null);
    const loading = ref(false);
    const requires2fa = ref(false);
    /** Секунды до следующей разрешённой попытки login/2fa-verify (ТЗ §22.4.4). */
    const lockoutSeconds = ref<number | null>(null);
    /** G1/SP3a: email/код самозаписи между экраном регистрации и подтверждения. */
    const pendingEmail = ref<string | null>(null);
    const pendingDevCode = ref<string | null>(null);

    const isAuthenticated = computed(() => user.value !== null);

    async function login(payload: LoginPayload) {
        loading.value = true;
        lockoutSeconds.value = null;
        try {
            const response = await authApi.login(payload);
            // При requires_2fa=true НЕ ставим user в state — иначе isAuthenticated
            // станет true и auth-guard пустит на /dashboard минуя 2FA. Backend
            // тоже НЕ создаёт session-auth до verifyTwoFactor.
            if (response.requires_2fa) {
                user.value = null;
                requires2fa.value = true;
            } else {
                user.value = response.user;
                requires2fa.value = false;
            }
            return response;
        } catch (error) {
            const retry = extractRateLimitRetry(error);
            if (retry !== null) lockoutSeconds.value = retry;
            throw error;
        } finally {
            loading.value = false;
        }
    }

    async function register(payload: RegisterPayload): Promise<RegisterResult> {
        loading.value = true;
        lockoutSeconds.value = null;
        try {
            const result = await authApi.register(payload);
            // Новый поток SP1: user НЕ ставится — сессия создаётся при confirm-email.
            pendingEmail.value = result.email;
            pendingDevCode.value = result._dev_plain_code ?? null;
            return result;
        } catch (error) {
            const retry = extractRateLimitRetry(error);
            if (retry !== null) lockoutSeconds.value = retry;
            throw error;
        } finally {
            loading.value = false;
        }
    }

    async function confirmEmail(payload: { email: string; code: string }) {
        loading.value = true;
        try {
            const response = await authApi.confirmEmail(payload);
            user.value = response.user;
            requires2fa.value = false;
            pendingEmail.value = null;
            pendingDevCode.value = null;
            return response;
        } finally {
            loading.value = false;
        }
    }

    async function resendCode(email: string) {
        loading.value = true;
        try {
            const result = await authApi.resendCode(email);
            if (result._dev_plain_code) pendingDevCode.value = result._dev_plain_code;
            return result;
        } finally {
            loading.value = false;
        }
    }

    async function requestPasswordReset(email: string) {
        loading.value = true;
        lockoutSeconds.value = null;
        try {
            const response = await authApi.forgotPassword(email);
            return response;
        } catch (error) {
            const retry = extractRateLimitRetry(error);
            if (retry !== null) lockoutSeconds.value = retry;
            throw error;
        } finally {
            loading.value = false;
        }
    }

    async function resetPassword(payload: ResetPasswordPayload) {
        loading.value = true;
        lockoutSeconds.value = null;
        try {
            const response = await authApi.resetPassword(payload);
            return response;
        } catch (error) {
            const retry = extractRateLimitRetry(error);
            if (retry !== null) lockoutSeconds.value = retry;
            throw error;
        } finally {
            loading.value = false;
        }
    }

    async function verifyTwoFactor(code: string) {
        loading.value = true;
        lockoutSeconds.value = null;
        try {
            const response = await authApi.verifyTwoFactor(code);
            user.value = response.user;
            requires2fa.value = false;
            return response;
        } catch (error) {
            const retry = extractRateLimitRetry(error);
            if (retry !== null) lockoutSeconds.value = retry;
            throw error;
        } finally {
            loading.value = false;
        }
    }

    async function useRecoveryCode(code: string) {
        loading.value = true;
        lockoutSeconds.value = null;
        try {
            const response = await authApi.useRecoveryCode(code);
            user.value = response.user;
            requires2fa.value = false;
            return response;
        } catch (error) {
            const retry = extractRateLimitRetry(error);
            if (retry !== null) lockoutSeconds.value = retry;
            throw error;
        } finally {
            loading.value = false;
        }
    }

    async function fetchMe(): Promise<AuthUser | null> {
        try {
            const fetched = await authApi.me();
            user.value = fetched;
            return fetched;
        } catch {
            user.value = null;
            return null;
        }
    }

    async function logout() {
        // Логаут всегда успешен с точки зрения UI: даже если backend упал —
        // клиент локально считается вышедшим. Иначе пользователь может остаться
        // «залипшим» в авторизованном состоянии при сетевой ошибке.
        try {
            await authApi.logout();
        } catch {
            // ignore — backend всё равно очистит сессию по cookie-expiry.
        }
        user.value = null;
        requires2fa.value = false;
    }

    return {
        user,
        loading,
        requires2fa,
        lockoutSeconds,
        pendingEmail,
        pendingDevCode,
        isAuthenticated,
        login,
        register,
        confirmEmail,
        resendCode,
        verifyTwoFactor,
        useRecoveryCode,
        requestPasswordReset,
        resetPassword,
        fetchMe,
        logout,
    };
});
