<script setup>
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
import { arrowSvg, iconPaths, moonMark } from './symbols';

const props = defineProps({
    registerEndpoint: { type: String, required: true },
    csrfToken: { type: String, required: true },
    auth: { type: Object, required: true },
    flash: { type: Object, required: true },
});

const hints = {
    username: 'Используй латиницу и цифры. Регистр символов при входе не имеет значения.',
    invite_code: 'Регистрация доступна только по действующему инвайт-коду.',
};

const initialErrors = props.flash.errors || {};
const submitted = ref(Boolean(props.flash.success));
const submitting = ref(false);
const form = reactive({
    username: props.flash.old?.username || '',
    email: props.flash.old?.email || '',
    invite_code: props.flash.old?.invite_code || '',
    password: '',
    password_confirmation: '',
    terms: false,
});
const touched = reactive(Object.fromEntries(Object.keys(initialErrors).map((key) => [key, true])));
const serverErrors = reactive({ ...initialErrors });

const clientErrors = computed(() => {
    const errors = {};
    if (form.username && !/^[a-zA-Z0-9]{3,32}$/.test(form.username)) errors.username = 'Только латиница и цифры, 3-32 символа.';
    if (form.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) errors.email = 'Похоже на некорректный email.';
    if (form.invite_code && !/^[A-Za-z0-9-]{6,32}$/.test(form.invite_code)) errors.invite_code = 'Код из букв, цифр и тире, 6-32 символа.';
    if (form.password && form.password.length < 8) errors.password = 'Минимум 8 символов.';
    else if (form.password && !/[A-Za-z]/.test(form.password)) errors.password = 'Должна быть хотя бы одна буква.';
    else if (form.password && !/\d/.test(form.password)) errors.password = 'Должна быть хотя бы одна цифра.';
    if (form.password_confirmation && form.password_confirmation !== form.password) errors.password_confirmation = 'Пароли не совпадают.';
    return errors;
});

const valid = computed(() => Boolean(
    form.username &&
    form.email &&
    form.invite_code &&
    form.password &&
    form.password_confirmation &&
    form.terms &&
    Object.keys(clientErrors.value).length === 0
));

onMounted(() => {
    if (submitted.value || props.flash.error || Object.keys(initialErrors).length) {
        nextTick(() => document.getElementById('join')?.scrollIntoView({ behavior: 'smooth', block: 'start' }));
    }
});

function firstError(field) {
    const value = serverErrors[field];
    return Array.isArray(value) ? value[0] : value;
}

function errorFor(field) {
    return firstError(field) || (touched[field] && clientErrors.value[field]) || null;
}

function updateField(field, value) {
    form[field] = value;
    delete serverErrors[field];
}

function submit(event) {
    if (valid.value) {
        submitting.value = true;
        return;
    }

    event.preventDefault();
    ['username', 'email', 'invite_code', 'password', 'password_confirmation', 'terms'].forEach((field) => {
        touched[field] = true;
    });
}
</script>

<template>
    <section id="join" data-screen-label="04 Join">
        <div class="wrap">
            <div v-if="submitted && flash.success" class="join-card join-success reveal is-visible">
                <div class="join-success-mark" v-html="moonMark(56)"></div>
                <span class="eyebrow" style="justify-content: center">Добро пожаловать</span>
                <h3 class="h-display" style="font-size: 36px; margin-top: 16px">Аккаунт создан</h3>
                <p class="lead" style="margin-top: 14px">
                    Логин <span style="color: var(--moon); font-style: normal">{{ flash.success_username || form.username }}</span> готов к входу. Открывай лаунчер и жми «Играть».
                </p>
                <div class="hero-cta" style="justify-content: center; margin-top: 28px">
                    <a :href="auth.cabinet_url || auth.login_url || '#'" class="btn btn-primary">Войти в личный кабинет <span v-html="arrowSvg"></span></a>
                </div>
            </div>

            <div v-else class="join-grid reveal">
                <div class="join-intro">
                    <span class="eyebrow">Регистрация</span>
                    <div style="height: 20px"></div>
                    <h2 class="h-display" style="font-size: clamp(36px, 5vw, 56px)">Создай игровой аккаунт</h2>
                    <div class="divider-ornament" style="justify-content: flex-start; margin: 22px 0"><span style="opacity: 0.6">✦</span></div>
                    <p class="lead" style="font-style: italic">Укажи инвайт-код, логин, почту и пароль - аккаунт будет готов к входу в игру сразу после регистрации.</p>
                    <div class="join-note">
                        <span class="join-note-k">Закрытый бета-доступ</span>
                        <span class="join-note-v">Пока идет закрытый этап: регистрация только по инвайт-кодам. Код можно получить у друзей-игроков или в нашем Discord.</span>
                    </div>
                </div>

                <form class="join-card" method="POST" :action="registerEndpoint" novalidate @submit="submit">
                    <input type="hidden" name="_token" :value="csrfToken" />
                    <div class="join-card-corner tl" aria-hidden="true"></div>
                    <div class="join-card-corner tr" aria-hidden="true"></div>
                    <div class="join-card-corner bl" aria-hidden="true"></div>
                    <div class="join-card-corner br" aria-hidden="true"></div>
                    <div v-if="flash.error" class="join-error" style="margin-bottom: 14px">{{ flash.error }}</div>

                    <div :class="['join-field', { 'has-error': errorFor('username') }]">
                        <label class="join-label">Логин</label>
                        <div class="join-input"><input type="text" name="username" autocomplete="username" placeholder="Moonwalker" :value="form.username" maxlength="32" @input="updateField('username', $event.target.value)" @blur="touched.username = true" /></div>
                        <div v-if="errorFor('username')" class="join-error">{{ errorFor('username') }}</div>
                        <div v-else class="join-hint">{{ hints.username }}</div>
                    </div>

                    <div :class="['join-field', { 'has-error': errorFor('email') }]">
                        <label class="join-label">Email</label>
                        <div class="join-input"><input type="email" name="email" autocomplete="email" placeholder="player@example.com" :value="form.email" @input="updateField('email', $event.target.value)" @blur="touched.email = true" /></div>
                        <div v-if="errorFor('email')" class="join-error">{{ errorFor('email') }}</div>
                    </div>

                    <div :class="['join-field', { 'has-error': errorFor('invite_code') }]">
                        <label class="join-label">Инвайт-код</label>
                        <div class="join-input">
                            <span class="join-input-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round" v-html="iconPaths.mask"></svg></span>
                            <input type="text" name="invite_code" placeholder="ABCD-EFGH-IJKL" :value="form.invite_code" maxlength="32" style="letter-spacing: 0.14em; font-family: var(--f-mono)" @input="updateField('invite_code', $event.target.value.toUpperCase())" @blur="touched.invite_code = true" />
                        </div>
                        <div v-if="errorFor('invite_code')" class="join-error">{{ errorFor('invite_code') }}</div>
                        <div v-else class="join-hint">{{ hints.invite_code }}</div>
                    </div>

                    <div class="join-row">
                        <div :class="['join-field', { 'has-error': errorFor('password') }]">
                            <label class="join-label">Пароль</label>
                            <div class="join-input"><input type="password" name="password" autocomplete="new-password" placeholder="Минимум 8 символов" :value="form.password" maxlength="32" @input="updateField('password', $event.target.value)" @blur="touched.password = true" /></div>
                            <div v-if="errorFor('password')" class="join-error">{{ errorFor('password') }}</div>
                        </div>
                        <div :class="['join-field', { 'has-error': errorFor('password_confirmation') }]">
                            <label class="join-label">Повтор пароля</label>
                            <div class="join-input"><input type="password" name="password_confirmation" autocomplete="new-password" placeholder="Повтори пароль" :value="form.password_confirmation" maxlength="32" @input="updateField('password_confirmation', $event.target.value)" @blur="touched.password_confirmation = true" /></div>
                            <div v-if="errorFor('password_confirmation')" class="join-error">{{ errorFor('password_confirmation') }}</div>
                        </div>
                    </div>

                    <label class="join-check">
                        <input type="checkbox" name="terms" value="1" :checked="form.terms" @change="updateField('terms', $event.target.checked)" />
                        <span class="box" aria-hidden="true"></span>
                        <span>Я принимаю <a href="#">правила сервера</a> и согласен на обработку данных для создания игрового аккаунта.</span>
                    </label>
                    <div v-if="errorFor('terms')" class="join-error">{{ errorFor('terms') }}</div>

                    <button type="submit" :class="['btn btn-primary join-submit', { 'is-disabled': !valid || submitting }]" :disabled="!valid || submitting">
                        {{ submitting ? 'Создаем аккаунт...' : 'Зарегистрировать аккаунт' }} <span v-html="arrowSvg"></span>
                    </button>
                </form>
            </div>
        </div>
    </section>
</template>
