<?php

namespace app\api\controller;

use ba\Captcha;
use ba\ClickCaptcha;
use app\common\controller\Frontend;
use app\common\facade\Token;
use support\validation\Validator;
use support\validation\ValidationException;
use Webman\Http\Request;
use support\Response;

class User extends Frontend
{
    protected array $noNeedLogin = ['checkIn', 'logout'];

    public function checkIn(Request $request): Response
    {
        $response = $this->initializeFrontend($request);
        if ($response !== null) return $response;

        $openMemberCenter = config('buildadmin.open_member_center');
        if (!$openMemberCenter) {
            return $this->error(__('Member center disabled'));
        }

        if ($this->auth->isLogin()) {
            return $this->success(__('You have already logged in. There is no need to log in again~'), [
                'type' => $this->auth::LOGGED_IN
            ], $this->auth::LOGIN_RESPONSE_CODE);
        }

        $userLoginCaptchaSwitch = config('buildadmin.user_login_captcha');

        if ($request->method() === 'POST') {
            $params = $request->post();
            $params = array_merge($params, [
                'tab' => $params['tab'] ?? '',
                'email' => $params['email'] ?? '',
                'mobile' => $params['mobile'] ?? '',
                'username' => $params['username'] ?? '',
                'password' => $params['password'] ?? '',
                'keep' => $params['keep'] ?? false,
                'captcha' => $params['captcha'] ?? '',
                'captchaId' => $params['captchaId'] ?? '',
                'captchaInfo' => $params['captchaInfo'] ?? '',
                'registerType' => $params['registerType'] ?? '',
            ]);

            if (!in_array($params['tab'], ['login', 'register'])) {
                return $this->error(__('Unknown operation'));
            }

            try {
                $rules = $params['tab'] === 'login' ? $this->getLoginRules($userLoginCaptchaSwitch) : $this->getRegisterRules();
                Validator::make($params, $rules[0], $rules[1] ?? [], $rules[2] ?? [])->validate();
            } catch (ValidationException $e) {
                return $this->error($e->getMessage());
            }

            if ($params['tab'] === 'login') {
                if ($userLoginCaptchaSwitch) {
                    $captchaObj = new ClickCaptcha();
                    if (!$captchaObj->check($params['captchaId'], $params['captchaInfo'])) {
                        return $this->error(__('Captcha error'));
                    }
                }
                $res = $this->auth->login($params['username'], $params['password'], !empty($params['keep']));
            } else {
                $captchaObj = new Captcha();
                if (!$captchaObj->check($params['captcha'], $params[$params['registerType']] . 'user_register')) {
                    return $this->error(__('Please enter the correct verification code'));
                }
                $res = $this->auth->register($params['username'], $params['password'], $params['mobile'], $params['email']);
            }

            if ($res === true) {
                return $this->success(__('Login succeeded!'), [
                    'userInfo' => $this->auth->getUserInfo(),
                    'routePath' => '/user'
                ]);
            }
            $msg = $this->auth->getError();
            return $this->error($msg ?: __('Check in failed, please try again or contact the website administrator~'));
        }

        return $this->success('', [
            'userLoginCaptchaSwitch' => $userLoginCaptchaSwitch,
            'accountVerificationType' => get_account_verification_type()
        ]);
    }

    private function getLoginRules(bool $captchaSwitch): array
    {
        $rules = [
            'username' => 'required|string',
            'password' => 'required|string|regex:/^(?!.*[&<>"\'\n\r]).{6,32}$/',
        ];
        $messages = [
            'password.regex' => __('Please input correct password'),
        ];
        if ($captchaSwitch) {
            $rules['captchaId'] = 'required|string';
            $rules['captchaInfo'] = 'required|string';
        }
        return [$rules, $messages, []];
    }

    private function getRegisterRules(): array
    {
        return [
            [
                'username' => 'required|string|regex:/^[a-zA-Z][a-zA-Z0-9_]{2,15}$/|unique:user,username',
                'password' => 'required|string|regex:/^(?!.*[&<>"\'\n\r]).{6,32}$/',
                'registerType' => 'required|in:email,mobile',
                'email' => 'required_if:registerType,email|email|unique:user,email',
                'mobile' => 'required_if:registerType,mobile|regex:/^1[3-9]\d{9}$/|unique:user,mobile',
                'captcha' => 'required|string',
            ],
            [
                'username.regex' => __('Please input correct username'),
                'password.regex' => __('Please input correct password'),
            ],
            [
                'username' => __('Username'),
                'email' => __('Email'),
                'mobile' => __('Mobile'),
                'password' => __('Password'),
                'captcha' => __('captcha'),
                'registerType' => __('Register type'),
            ]
        ];
    }

    public function logout(Request $request): Response
    {
        $response = $this->initializeFrontend($request);
        if ($response !== null) return $response;

        if ($request->method() === 'POST') {
            $refreshToken = $request->post('refreshToken', '');
            if ($refreshToken) {
                Token::delete((string) $refreshToken);
            }
            $this->auth->logout();
            return $this->success();
        }
        return $this->error(__('Method not allowed'), [], 0, ['statusCode' => 405]);
    }
}
