<?php
// +----------------------------------------------------------------------
// | onezan-admin 快速开发的管理平台
// +----------------------------------------------------------------------
// | 官方网址：https://www.onezan.cn
// +----------------------------------------------------------------------
// | onezan团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: 543885307@qq.com
// +----------------------------------------------------------------------
namespace app\validate\domain;


/**
 * 用户领域验证器
 * @package app\validate\domain
 */
class UserDomainValidator implements DomainValidatorInterface
{

    protected array $hooks = [];


    /**
     * 注册验证钩子
     * @param \app\validate\domain\hooks\ValidationHook $hook 钩子实例
     * @return void
     */
    public function registerHook(\app\validate\domain\hooks\ValidationHook $hook): void
    {
        $this->hooks[] = $hook;
    }


    /**
     * 校验用户数据
     * @param array $data
     * @param string $scene
     * @return array
     */
    public function validate(array $data, string $scene = ''): array
    {
        $errors = match ($scene) {
            'register' => $this->validateRegister($data),
            'login' => $this->validateLogin($data),
            'update_profile' => $this->validateUpdateProfile($data),
            'send_email_code' => $this->validateEmail($data),
            'bind_email' => $this->validateBindEmail($data),
            'cancel_account' => $this->validateCancelAccount($data),
            'set_level' => $this->validateSetLevel($data),
            'balance_adjust' => $this->validateBalanceAdjust($data),
            'points_adjust' => $this->validatePointsAdjust($data),
            'verify' => $this->validateVerify($data),
            'reset_password' => $this->validateResetPassword($data),
            default => [],
        };

        foreach ($this->hooks as $hook) {
            $hookErrors = $hook->onUserValidate($data, $scene);
            if (!empty($hookErrors)) {
                $errors = array_merge($errors, $hookErrors);
            }
        }

        return ['ok' => empty($errors), 'errors' => $errors];
    }

    /**
     * 校验注册数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateRegister(array $data): array
    {
        $errors = [];
        if (empty(trim((string)($data['username'] ?? '')))) {
            $errors['username'] = 'USERNAME_REQUIRED';
        } elseif (mb_strlen(trim((string)$data['username'])) < 2) {
            $errors['username'] = 'USERNAME_TOO_SHORT';
        }
        if (empty(trim((string)($data['password'] ?? '')))) {
            $errors['password'] = 'PASSWORD_REQUIRED';
        } elseif (strlen((string)$data['password']) < 6) {
            $errors['password'] = 'PASSWORD_TOO_SHORT';
        }
        return $errors;
    }

    /**
     * 校验登录数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateLogin(array $data): array
    {
        $errors = [];
        if (empty(trim((string)($data['username'] ?? '')))) {
            $errors['username'] = 'USERNAME_REQUIRED';
        }
        if (empty(trim((string)($data['password'] ?? '')))) {
            $errors['password'] = 'PASSWORD_REQUIRED';
        }
        return $errors;
    }

    /**
     * 校验设置用户等级数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateSetLevel(array $data): array
    {
        $errors = [];
        if (empty($data['user_id'] ?? 0)) {
            $errors['user_id'] = 'USER_ID_REQUIRED';
        }
        if (empty($data['level_id'] ?? 0)) {
            $errors['level_id'] = 'LEVEL_ID_REQUIRED';
        }
        return $errors;
    }

    /**
     * 校验更新个人资料数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateUpdateProfile(array $data): array
    {
        $errors = [];
        $nickname = trim((string)($data['nickname'] ?? ''));
        $avatar = trim((string)($data['avatar'] ?? ''));
        if ($nickname === '' && $avatar === '') {
            $errors['profile'] = 'PROFILE_UPDATE_REQUIRED';
        }
        if ($nickname !== '' && mb_strlen($nickname) < 2) {
            $errors['nickname'] = 'NICKNAME_TOO_SHORT';
        }
        return $errors;
    }

    /**
     * 校验注销账号数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateCancelAccount(array $data): array
    {
        $errors = [];
        if ((int)($data['confirm'] ?? 0) !== 1) {
            $errors['confirm'] = 'CANCEL_CONFIRM_REQUIRED';
        }
        return $errors;
    }

    /**
     * 校验邮箱格式
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateEmail(array $data): array
    {
        $errors = [];
        $email = trim((string)($data['email'] ?? ''));
        if ($email === '') {
            $errors['email'] = 'EMAIL_REQUIRED';
        } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $errors['email'] = 'EMAIL_INVALID';
        }
        return $errors;
    }

    /**
     * 校验绑定邮箱数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateBindEmail(array $data): array
    {
        $errors = $this->validateEmail($data);
        $code = trim((string)($data['code'] ?? ''));
        if ($code === '') {
            $errors['code'] = 'EMAIL_CODE_REQUIRED';
        } elseif (!preg_match('/^\d{6}$/', $code)) {
            $errors['code'] = 'EMAIL_CODE_INVALID';
        }
        return $errors;
    }

    /**
     * 校验余额调整数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateBalanceAdjust(array $data): array
    {
        $errors = [];
        if (empty($data['user_id'] ?? 0)) {
            $errors['user_id'] = 'USER_ID_REQUIRED';
        }
        $amount = (float)($data['amount'] ?? 0);
        if ($amount == 0) {
            $errors['amount'] = 'AMOUNT_REQUIRED';
        }
        if (!in_array(($data['action'] ?? ''), ['recharge', 'deduct'], true)) {
            $errors['action'] = 'ADJUST_ACTION_INVALID';
        }
        return $errors;
    }

    /**
     * 校验积分调整数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validatePointsAdjust(array $data): array
    {
        $errors = [];
        if (empty($data['user_id'] ?? 0)) {
            $errors['user_id'] = 'USER_ID_REQUIRED';
        }
        $amount = (float)($data['amount'] ?? 0);
        if ($amount == 0) {
            $errors['amount'] = 'AMOUNT_REQUIRED';
        }
        if (!in_array(($data['action'] ?? ''), ['recharge', 'deduct'], true)) {
            $errors['action'] = 'ADJUST_ACTION_INVALID';
        }
        return $errors;
    }

    /**
     * 校验认证审核数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateVerify(array $data): array
    {
        $errors = [];
        if (empty($data['verify_id'] ?? 0)) {
            $errors['verify_id'] = 'VERIFY_ID_REQUIRED';
        }
        if (!in_array(($data['action'] ?? ''), ['pass', 'reject', 'cancel'], true)) {
            $errors['action'] = 'VERIFY_ACTION_INVALID';
        }
        return $errors;
    }

    /**
     * 校验重置密码数据
     * @param array $data
     * @return array 错误信息数组
     */
    private function validateResetPassword(array $data): array
    {
        $errors = [];
        if (empty($data['user_id'] ?? 0)) {
            $errors['user_id'] = 'USER_ID_REQUIRED';
        }
        if (empty(trim((string)($data['new_password'] ?? '')))) {
            $errors['new_password'] = 'PASSWORD_REQUIRED';
        } elseif (strlen((string)$data['new_password']) < 6) {
            $errors['new_password'] = 'PASSWORD_TOO_SHORT';
        }
        return $errors;
    }
}