<?php

declare(strict_types=1);

require_once __DIR__ . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'app.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_public_session.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_public_member_auth.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_register.php';

fate_public_session_start();

if (fate_public_member_current() !== null) {
    header('Location: ./member_profile.php', true, 302);
    exit;
}

$disabled = fate_public_registration_disabled();

$safeNext = static function (?string $next): string {
    return fate_public_sanitize_login_next($next);
};

if (!$disabled && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $tok = isset($_POST['csrf']) && is_string($_POST['csrf']) ? $_POST['csrf'] : '';
    $nextPost = $safeNext(isset($_POST['next']) ? (string) $_POST['next'] : null);

    $fail = static function (string $message, array $sticky = []) use ($nextPost): void {
        $_SESSION['fate_register_flash'] = [
            'bad' => $message,
            'sticky' => $sticky,
            'next' => $nextPost,
        ];
        header('Location: register.php', true, 303);
        exit;
    };

    if (!fate_public_member_csrf_check($tok)) {
        $fail('工作階段逾期，請重新整理後再試。');
    }

    if (!fate_admin_member_auth_ready()) {
        $fail('會員資料庫未設定完成。');
    }

    $pdo = null;
    try {
        require_once __DIR__ . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'pdo.php';
        if (isset($GLOBALS['pdo']) && $GLOBALS['pdo'] instanceof PDO) {
            $pdo = $GLOBALS['pdo'];
        }
    } catch (Throwable) {
        $fail('無法連線資料庫。');
    }

    if (!$pdo instanceof PDO) {
        $fail('無法連線資料庫。');
    }

    require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_email.php';
    fate_member_email_bootstrap_schema($pdo);
    unset($GLOBALS['__fate_member_cols_snapshot']);
    $GLOBALS['fate_member_table_columns_reload'] = true;

    $un = isset($_POST['username']) && is_string($_POST['username']) ? $_POST['username'] : '';
    $pw = isset($_POST['password']) && is_string($_POST['password']) ? $_POST['password'] : '';
    $pw2 = isset($_POST['password_confirm']) && is_string($_POST['password_confirm']) ? $_POST['password_confirm'] : '';
    $dn = isset($_POST['display_name']) && is_string($_POST['display_name']) ? trim($_POST['display_name']) : '';
    $em = isset($_POST['email']) && is_string($_POST['email']) ? trim($_POST['email']) : '';

    $sticky = [
        'username' => $un,
        'display_name' => $dn,
        'email' => $em,
    ];

    $featureMail = fate_member_email_verify_feature_enabled($pdo);
    $needsEmail = fate_member_register_email_required($pdo);
    $manualApproval = fate_member_manual_approval_enabled();

    if ($needsEmail && $em === '') {
        $fail(
            $manualApproval ? '請填寫 Email。' : '請填寫 Email 以接收驗證信。',
            $sticky
        );
    }
    if ($pw !== $pw2) {
        $fail('兩次輸入的密碼不一致。', $sticky);
    }

    $uvFirst = fate_public_member_validate_username_candidate($un);
    if (!$uvFirst['ok']) {
        $fail($uvFirst['err'] ?? '帳號格式不正確。', $sticky);
    }

    $unameNorm = $uvFirst['username'];
    $reg = fate_public_member_register($pdo, $unameNorm, $pw, $dn, $em);
    if (!$reg['ok']) {
        $fail($reg['error'] ?? '註冊失敗。', $sticky);
    }

    $newId = (int) ($reg['id'] ?? 0);
    if ($manualApproval && $newId > 0) {
        $_SESSION['fate_login_flash'] = [
            'ok' => true,
            'text' => fate_member_register_pending_message(),
            'username' => $unameNorm,
        ];
        header('Location: login.php?registered=1', true, 303);
        exit;
    }

    if ($featureMail && $newId > 0) {
        require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_mail_settings.php';
        require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_account.php';
        $usesToken = fate_verify_method_uses_token();
        $usesReverse = fate_verify_method_uses_reverse();

        require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_session_bridge.php';
        fate_session_assign_cookie_lifetime(fate_session_lifetime_sec());
        fate_public_member_bind_session([
            'id' => $newId,
            'username' => $unameNorm,
            'display_name' => $dn,
            'role' => '',
        ], false);
        require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_profile.php';
        fate_member_profile_hydrate_session($pdo, $newId);

        $mailSent = true;
        if ($usesToken) {
            $snd = fate_member_resend_verify_for_member_id($pdo, $newId);
            $mailSent = $snd['ok'];
        }

        $qs = 'registered=1';
        if ($usesToken && $usesReverse) {
            $qs .= '&verify=both';
        } elseif ($usesReverse) {
            $qs .= '&verify=reverse';
        } elseif ($usesToken) {
            $qs .= $mailSent ? '&verify=token' : '&mail_err=1';
        }
        header('Location: member_profile.php?' . $qs, true, 303);
        exit;
    }

    $auth = fate_public_member_authenticate($pdo, $unameNorm, $pw);
    if (!$auth['ok']) {
        if (($auth['err'] ?? '') === 'pending_approval') {
            $_SESSION['fate_login_flash'] = [
                'ok' => true,
                'text' => fate_member_register_pending_message(),
                'username' => $unameNorm,
            ];
            header('Location: login.php?registered=1', true, 303);
            exit;
        }
        if (($auth['err'] ?? '') === 'email_unverified') {
            require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_account.php';
            $cred = fate_public_member_verify_credentials($pdo, $unameNorm, $pw);
            if ($cred['ok'] && is_array($cred['member'] ?? null)) {
                require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_session_bridge.php';
                fate_session_assign_cookie_lifetime(fate_session_lifetime_sec());
                fate_public_member_bind_session($cred['member'], false);
                require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_profile.php';
                fate_member_profile_hydrate_session($pdo, (int) $cred['member']['id']);
                header('Location: member_profile.php?registered=1', true, 303);
                exit;
            }
        }
        $_SESSION['fate_login_flash'] = [
            'ok' => true,
            'text' => '帳號已建立，請登入。',
            'username' => $unameNorm,
        ];
        header('Location: login.php?registered=1', true, 303);
        exit;
    }

    require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_session_bridge.php';
    fate_session_assign_cookie_lifetime(fate_session_lifetime_sec());
    fate_public_member_bind_session($auth['member']);
    require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_profile.php';
    fate_member_profile_hydrate_session($pdo, (int) $auth['member']['id']);
    header('Location: ' . $nextPost, true, 303);
    exit;
}

$flash = isset($_SESSION['fate_register_flash']) && is_array($_SESSION['fate_register_flash'])
    ? $_SESSION['fate_register_flash'] : null;
unset($_SESSION['fate_register_flash']);

$msgBad = is_array($flash) && isset($flash['bad']) && is_string($flash['bad']) ? $flash['bad'] : '';
$stickyData = is_array($flash) && isset($flash['sticky']) && is_array($flash['sticky']) ? $flash['sticky'] : [];
$next = $safeNext(
    is_array($flash) && isset($flash['next']) && is_string($flash['next'])
        ? $flash['next']
        : (isset($_GET['next']) ? (string) $_GET['next'] : null)
);

$stickyUsername = isset($stickyData['username']) && is_string($stickyData['username']) ? $stickyData['username'] : '';
$stickyDisplay = isset($stickyData['display_name']) && is_string($stickyData['display_name']) ? $stickyData['display_name'] : '';
$stickyEmail = isset($stickyData['email']) && is_string($stickyData['email']) ? $stickyData['email'] : '';

$csrf = fate_public_member_csrf_token();
$needVerifyEmailUi = false;
$needEmailUi = false;
$reverseOnlyUi = false;
$tokenOnlyUi = false;
$bothVerifyUi = false;
$needManualApprovalUi = fate_member_manual_approval_enabled();

if (!$disabled && fate_admin_member_auth_ready()) {
    try {
        require_once __DIR__ . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'pdo.php';
        if (isset($GLOBALS['pdo']) && $GLOBALS['pdo'] instanceof PDO) {
            require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_email.php';
            require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_mail_settings.php';
            fate_member_email_bootstrap_schema($GLOBALS['pdo']);
            unset($GLOBALS['__fate_member_cols_snapshot']);
            $GLOBALS['fate_member_table_columns_reload'] = true;
            $needVerifyEmailUi = fate_member_email_verify_feature_enabled($GLOBALS['pdo']);
            $needEmailUi = fate_member_register_email_required($GLOBALS['pdo']);
            $usesToken = fate_verify_method_uses_token();
            $usesReverse = fate_verify_method_uses_reverse();
            $reverseOnlyUi = $usesReverse && !$usesToken;
            $tokenOnlyUi = $usesToken && !$usesReverse;
            $bothVerifyUi = $usesToken && $usesReverse;
        }
    } catch (Throwable) {
        $needVerifyEmailUi = false;
        $needEmailUi = false;
        $reverseOnlyUi = false;
        $tokenOnlyUi = false;
        $bothVerifyUi = false;
    }
}

require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_template.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_ui_settings.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_admin_nav_visibility.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_plugins.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_page_counter.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_seo.php';

$fatePublicMember = null;
$fateAdminNavVisible = fate_admin_nav_visible_for_frontend();
$fateForumNavVisible = fate_store_forum_plugin_active();

$pdo = null;
try {
    if (isset($GLOBALS['pdo']) && $GLOBALS['pdo'] instanceof PDO) {
        $pdo = $GLOBALS['pdo'];
    } else {
        require_once __DIR__ . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'pdo.php';
        if (isset($GLOBALS['pdo']) && $GLOBALS['pdo'] instanceof PDO) {
            $pdo = $GLOBALS['pdo'];
        }
    }
} catch (Throwable) {
    $pdo = null;
}

$fateBrand = fate_public_site_branding();
$fatePageTitle = $fateBrand['title_main'] . ' — 註冊會員';
$fateSeoContext = fate_seo_private_page_context();
$fatePageStatsFooter = fate_page_stats_for_footer($pdo, 'member.register', null, $fatePageTitle);
$fatePageHitCount = $fatePageStatsFooter['fatePageHitCount'];
$fatePageStatsDbOk = $fatePageStatsFooter['fatePageStatsDbOk'];

header('Content-Type: text/html; charset=UTF-8');

fate_render_register(compact(
    'next',
    'msgBad',
    'stickyUsername',
    'stickyDisplay',
    'stickyEmail',
    'csrf',
    'disabled',
    'needVerifyEmailUi',
    'needEmailUi',
    'reverseOnlyUi',
    'tokenOnlyUi',
    'bothVerifyUi',
    'needManualApprovalUi',
    'fatePublicMember',
    'fateAdminNavVisible',
    'fateForumNavVisible',
    'fatePageHitCount',
    'fatePageStatsDbOk',
    'fatePageTitle',
    'fateSeoContext',
));
