<?php

declare(strict_types=1);

namespace app\admin\controller;

use ba\ClickCaptcha;
use app\common\facade\Token;
use app\admin\model\AdminLog;
use app\common\controller\Backend;
use support\validation\Validator;
use support\validation\ValidationException;
use Webman\Http\Request;
use support\Response;

class Index extends Backend
{
    protected array $noNeedLogin = ['logout', 'login'];
    protected array $noNeedPermission = ['index'];

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

        $adminInfo = $this->auth->getInfo();
        $adminInfo['super'] = $this->auth->isSuperAdmin();
        unset($adminInfo['token'], $adminInfo['refresh_token']);

        $menus = $this->auth->getMenus();
        if (!$menus) {
            return $this->error(__('No background menu, please contact super administrator!'));
        }

        $apiUrl = config('buildadmin.api_url');
        if (!$apiUrl || $apiUrl === 'https://api.buildadmin.com') {
            $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
            $apiUrl = $scheme . '://' . $request->host();
        }

        return $this->success('', [
            'adminInfo' => $adminInfo,
            'menus' => $menus,
            'siteConfig' => [
                'siteName' => get_sys_config('site_name'),
                'version' => get_sys_config('version'),
                'apiUrl' => $apiUrl,
                'upload' => keys_to_camel_case(get_upload_config($request), ['max_size', 'save_name', 'allowed_suffixes', 'allowed_mime_types']),
                'cdnUrl' => full_url(),
                'cdnUrlParams' => config('buildadmin.cdn_url_params'),
            ],
            'terminal' => [
                'phpDevelopmentServer' => str_contains($_SERVER['SERVER_SOFTWARE'] ?? '', 'Development Server'),
                'npmPackageManager' => config('terminal.npm_package_manager'),
            ]
        ]);
    }

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

        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);
        }

        $captchaSwitch = config('buildadmin.admin_login_captcha');

        if ($request->method() === 'POST') {
            $username = $request->post('username');
            $password = $request->post('password');
            $keep = $request->post('keep');

            $rules = [
                'username' => 'required|string|min:3|max:30',
                'password' => 'required|string|regex:/^(?!.*[&<>"\'\n\r]).{6,32}$/',
            ];
            $data = ['username' => $username, 'password' => $password];
            if ($captchaSwitch) {
                $rules['captchaId'] = 'required|string';
                $rules['captchaInfo'] = 'required|string';
                $data['captchaId'] = $request->post('captchaId');
                $data['captchaInfo'] = $request->post('captchaInfo');
            }

            try {
                Validator::make($data, $rules, [
                    'username.required' => __('Username'),
                    'password.required' => __('Password'),
                    'password.regex' => __('Please input correct password'),
                ])->validate();
            } catch (ValidationException $e) {
                return $this->error($e->getMessage());
            }

            if ($captchaSwitch) {
                $captchaObj = new ClickCaptcha();
                if (!$captchaObj->check($data['captchaId'], $data['captchaInfo'])) {
                    return $this->error(__('Captcha error'));
                }
            }

            AdminLog::instance($request)->setTitle(__('Login'));

            $res = $this->auth->login($username, $password, (bool) $keep);
            if ($res === true) {
                return $this->success(__('Login succeeded!'), [
                    'userInfo' => $this->auth->getInfo()
                ]);
            }
            $msg = $this->auth->getError();
            return $this->error($msg ?: __('Incorrect user name or password!'));
        }

        return $this->success('', [
            'captcha' => $captchaSwitch
        ]);
    }

    public function logout(Request $request): Response
    {
        $response = $this->initializeBackend($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]);
    }
}
