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

use app\model\AdminUser;
use app\repository\admin\AdminUserRepository;
use app\service\domain\admin\CoreAdminPermissionService;
use Core\service\BaseCoreService;
use think\facade\Db;

/**
 * 管理员用户服务
 * Class CoreAdminUserService
 * @package app\service\domain\admin
 */
class CoreAdminUserService extends BaseCoreService
{
    /**
     * 保存管理员用户
     * @param array $payload
     * @return array
     */
    public function save(array $payload): array
    {
        $id = is_numeric($payload['id'] ?? null) ? (int)$payload['id'] : 0;
        $username = trim((string)($payload['username'] ?? ''));
        $password = (string)($payload['password'] ?? '');
        $nickname = (string)($payload['nickname'] ?? '');
        $status = (int)($payload['status'] ?? 1) ? 1 : 0;

        if ($id > 0) {
            $user = $this->adminUserRepository()->findById($id);
            if (!$user) {
                return ['code' => 1, 'msg' => ''];
            }
        } else {
            if ($username === '' || $password === '') {
                return ['code' => 1, 'msg' => ''];
            }
            if ($this->adminUserRepository()->findByUsername($username)) {
                return ['code' => 1, 'msg' => ''];
            }
            $user = new AdminUser();
            $user->username = $username;
            $user->password = password_hash($password, PASSWORD_BCRYPT);
        }

        if ($username !== '') {
            $exists = $this->adminUserRepository()->findByUsername($username);
            if ($exists && (int)$exists->id !== (int)($user->id ?? 0)) {
                return ['code' => 1, 'msg' => ''];
            }
            $user->username = $username;
        }
        if ($password !== '') {
            $user->password = password_hash($password, PASSWORD_BCRYPT);
        }
        $user->nickname = $nickname;
        $user->status = $status;
        $this->adminUserRepository()->save($user);

        return ['code' => 0, 'msg' => ''];
    }

    /**
     * 删除管理员用户
     * @param int $id
     * @return array
     */
    public function delete(int $id): array
    {
        $user = $this->adminUserRepository()->findById($id);
        if (!$user) {
            return ['code' => 1, 'msg' => ''];
        }
        if ((string)$user->username === 'admin') {
            return ['code' => 1, 'msg' => ''];
        }

        Db::startTrans();
        try {
            $this->adminUserRepository()->clearRoles($id);
            $this->adminUserRepository()->delete($user);
            Db::commit();
            return ['code' => 0, 'msg' => ''];
        } catch (\Throwable $e) {
            Db::rollback();
            return ['code' => 1, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 设置管理员用户角色
     * @param AdminUser $actor
     * @param int $userId
     * @param array $roleIds
     * @return array
     */
    public function setRoles(AdminUser $actor, int $userId, array $roleIds): array
    {
        if ((int)$actor->id === $userId) {
            return ['code' => 1, 'msg' => ''];
        }

        $user = $this->adminUserRepository()->findById($userId);
        if (!$user) {
            return ['code' => 1, 'msg' => ''];
        }

        $cleanRoleIds = [];
        foreach ($roleIds as $roleId) {
            if (is_numeric($roleId)) {
                $cleanRoleIds[] = (int)$roleId;
            }
        }
        $cleanRoleIds = array_values(array_unique($cleanRoleIds));

        $assignableRoleIds = array_map('intval', $this->permissionService()->getAssignableRoleIdsForUser($actor));
        foreach ($cleanRoleIds as $roleId) {
            if (!in_array($roleId, $assignableRoleIds, true)) {
                return ['code' => 1, 'msg' => 'Unknown error'];
            }
        }

        Db::startTrans();
        try {
            $this->adminUserRepository()->clearRoles($userId);
            if ($cleanRoleIds) {
                $exists = $this->adminUserRepository()->activeRoleIds($cleanRoleIds);
                $this->adminUserRepository()->assignRoles($userId, $exists);
            }
            Db::commit();
            return ['code' => 0, 'msg' => ''];
        } catch (\Throwable $e) {
            Db::rollback();
            return ['code' => 1, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 获取管理员用户权限服务
     * @return CoreAdminPermissionService
     */

    private function permissionService(): CoreAdminPermissionService
    {
        return $this->app->make(CoreAdminPermissionService::class);
    }

    /**
     * 获取管理员用户仓库
     * @return AdminUserRepository
     */

    private function adminUserRepository(): AdminUserRepository
    {
        return $this->app->make(AdminUserRepository::class);
    }
}