<?php
declare(strict_types=1);

require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_member_password.php';

/**
 * /admin 登入：與前台相同會員表（FATE_MEMBER_DATABASE／FATE_MEMBER_TABLE），
 * 驗證密碼（fate_member_verify_password）與 role = admin、啟用欄位（FATE_MEMBER_ACTIVE_COLUMN）。
 */

function fate_admin_mysql_ident_ok(string $name): bool
{
    return $name !== '' && preg_match('/^[A-Za-z0-9_]+$/', $name) === 1;
}

function fate_admin_member_auth_ready(): bool
{
    return fate_admin_mysql_ident_ok(FATE_MEMBER_DATABASE)
        && fate_admin_mysql_ident_ok(FATE_MEMBER_TABLE);
}

function fate_member_role_is_admin(?string $role): bool
{
    return strtolower(trim((string) $role)) === 'admin';
}

function fate_member_role_is_mod(?string $role): bool
{
    return strtolower(trim((string) $role)) === 'mod';
}

/** 管理員或版主 */
function fate_member_role_is_staff(?string $role): bool
{
    return fate_member_role_is_admin($role) || fate_member_role_is_mod($role);
}

/** 是否由環境變數鎖定人工審核（此時後台無法變更）。 */
function fate_member_manual_approval_locked_by_env(): bool
{
    return defined('FATE_MEMBER_MANUAL_APPROVAL');
}

/**
 * 新會員是否須管理員人工審核。
 * 優先序：環境變數（常數，鎖定）→ 後台設定（各站 data/fate_mail_settings.json）→ 預設關閉。
 */
function fate_member_manual_approval_enabled(): bool
{
    if (defined('FATE_MEMBER_MANUAL_APPROVAL')) {
        return (bool) FATE_MEMBER_MANUAL_APPROVAL;
    }

    static $cached = null;
    if ($cached !== null) {
        return $cached;
    }

    $settingsFile = __DIR__ . DIRECTORY_SEPARATOR . 'fate_mail_settings.php';
    if (is_file($settingsFile)) {
        require_once $settingsFile;
    }
    if (function_exists('fate_mail_settings_normalize') && function_exists('fate_mail_settings_read')) {
        $s = fate_mail_settings_normalize(fate_mail_settings_read());
        $cached = ($s['manual_approval'] ?? '0') === '1';
    } else {
        $cached = false;
    }

    return $cached;
}

/** @param array<string,mixed> $row */
function fate_member_row_pending_approval(array $row): bool
{
    if (!fate_member_manual_approval_enabled()) {
        return false;
    }
    if (!array_key_exists('approved_at', $row)) {
        return false;
    }
    $ap = $row['approved_at'];

    return $ap === null || trim((string) $ap) === '';
}

/** 依 member id 查 role（供 Session 互通時補驗）。 */
function fate_member_fetch_role_by_id(PDO $pdo, int $memberId): string
{
    if (!fate_admin_member_auth_ready() || $memberId <= 0) {
        return '';
    }
    $db = FATE_MEMBER_DATABASE;
    $tbl = FATE_MEMBER_TABLE;
    $sql = sprintf(
        'SELECT `role` FROM `%s`.`%s` WHERE `id` = ? LIMIT 1',
        str_replace('`', '``', $db),
        str_replace('`', '``', $tbl)
    );
    try {
        $st = $pdo->prepare($sql);
        $st->execute([$memberId]);
        $raw = $st->fetchColumn();

        return is_string($raw) ? trim($raw) : '';
    } catch (Throwable) {
        return '';
    }
}

/**
 * @return array{ok:true,member:array{id:int,username:string,display_name:string}}|array{ok:false,err:string}
 */
function fate_admin_member_authenticate(PDO $pdo, string $username, string $password): array
{
    if (!fate_admin_member_auth_ready()) {
        return ['ok' => false, 'err' => 'config'];
    }

    $u = trim($username);
    if ($u === '' || $password === '') {
        return ['ok' => false, 'err' => 'invalid'];
    }

    $db = FATE_MEMBER_DATABASE;
    $tbl = FATE_MEMBER_TABLE;
    $ac = FATE_MEMBER_ACTIVE_COLUMN;
    $sql = sprintf(
        'SELECT `id`, `username`, `password`, `display_name`, `role`, `%s` AS `_mem_active` FROM `%s`.`%s` WHERE `username` = ? LIMIT 1',
        str_replace('`', '``', $ac),
        str_replace('`', '``', $db),
        str_replace('`', '``', $tbl)
    );

    try {
        $st = $pdo->prepare($sql);
        $st->execute([$u]);
    } catch (PDOException $e) {
        $msg = $e->getMessage();
        if (str_contains($msg, 'Base table or view not found') || str_contains($msg, "doesn't exist")) {
            return ['ok' => false, 'err' => 'missing_table'];
        }
        if (str_contains($msg, 'Unknown column') && str_contains($msg, $ac)) {
            return ['ok' => false, 'err' => 'bad_column'];
        }
        throw $e;
    }
    $row = $st->fetch(PDO::FETCH_ASSOC);
    if (!is_array($row)) {
        return ['ok' => false, 'err' => 'invalid'];
    }

    $hash = isset($row['password']) ? (string) $row['password'] : '';
    if ($hash === '' || !fate_member_verify_password($password, $hash)) {
        return ['ok' => false, 'err' => 'invalid'];
    }

    if ((int) ($row['_mem_active'] ?? 0) !== 1) {
        return ['ok' => false, 'err' => 'invalid'];
    }

    $role = isset($row['role']) ? (string) $row['role'] : '';
    if (!fate_member_role_is_admin($role)) {
        return ['ok' => false, 'err' => 'forbidden'];
    }

    $id = (int) ($row['id'] ?? 0);
    if ($id <= 0) {
        return ['ok' => false, 'err' => 'invalid'];
    }

    fate_admin_member_touch_last_login($pdo, $id);

    return [
        'ok' => true,
        'member' => [
            'id' => $id,
            'username' => (string) ($row['username'] ?? ''),
            'display_name' => isset($row['display_name']) ? (string) $row['display_name'] : '',
        ],
    ];
}

function fate_admin_member_touch_last_login(PDO $pdo, int $memberId): void
{
    if (!fate_admin_member_auth_ready() || $memberId <= 0) {
        return;
    }
    $db = FATE_MEMBER_DATABASE;
    $tbl = FATE_MEMBER_TABLE;
    $sql = sprintf(
        'UPDATE `%s`.`%s` SET `last_login_at` = NOW(), `last_login_ip` = ? WHERE `id` = ?',
        str_replace('`', '``', $db),
        str_replace('`', '``', $tbl)
    );
    $ip = isset($_SERVER['REMOTE_ADDR']) ? (string) $_SERVER['REMOTE_ADDR'] : '';
    if (strlen($ip) > 45) {
        $ip = substr($ip, 0, 45);
    }
    try {
        $up = $pdo->prepare($sql);
        $up->execute([$ip !== '' ? $ip : null, $memberId]);
    } catch (Throwable $e) {
        // 無權限更新時略過，不阻擋登入
    }
}

/** @param array{id:int,username:string,display_name:string} $member */
function fate_admin_member_bind_session(array $member): void
{
    $_SESSION['fate_admin_member_id'] = $member['id'];
    $_SESSION['fate_admin_username'] = $member['username'];
    $_SESSION['fate_admin_display_name'] = $member['display_name'];
}

function fate_admin_member_display_label(): string
{
    $name = isset($_SESSION['fate_admin_display_name']) ? trim((string) $_SESSION['fate_admin_display_name']) : '';
    $user = isset($_SESSION['fate_admin_username']) ? trim((string) $_SESSION['fate_admin_username']) : '';
    if ($name !== '') {
        return $name;
    }
    if ($user !== '') {
        return $user;
    }
    return '管理員';
}
