<?php

namespace app\common\model\User;

use app\common\arw\adjfut\src\Validate;
use app\BaseModel;
use app\common\model\Menu\Menu;
use app\common\model\Role\Role;
use app\common\model\User\UserRole as ModelUserRole;
use app\common\model\Token;
use think\db\Query;
use think\facade\Db;
use think\facade\Config;
use think\facade\Request;
use think\model\concern\SoftDelete;
use think\model\relation\BelongsToMany;
use app\common\arw\adjfut\src\Traits\Dictionary;
use app\common\arw\adjfut\src\Excel;

class User extends BaseModel
{
    use Dictionary;
    use SoftDelete;
    // 删除字段
    protected $deleteTime = 'user_delete_time';
    // 设置主键名
    protected $pk = 'user_guid';
    // 设置废弃字段
    protected $disuse = [];
    // 设置字段信息
    protected $schema = [
        'user_id' => 'int',
        'user_guid' => 'string',
        'user_img' => 'string',
        'user_name'        => 'string',
        'user_password'        => 'string',
        'user_phone'        => 'string',
        'user_status'      => 'int',
        'user_department' => 'string',
        'user_position' => 'string',
        'user_create_time' => 'datetime',
        'user_create_user_guid' => 'string',
        'user_update_time' => 'datetime',
        'user_update_user_guid' => 'string',
        'user_delete_time' => 'datetime',
        'user_delete_user_guid' => 'string',
    ];
    // 只读
    protected $readonly = [
        'user_id',
        'user_guid',
        'user_create_time',
        'user_create_user_guid'
    ];
    // 开启自动写入时间戳字段
    protected $autoWriteTimestamp = 'datetime';
    // 创建时间
    protected $createTime = 'user_create_time';
    // 修改时间
    protected $updateTime = 'user_update_time';

    public static $dictionaryMap = [
        'user_status' => [
            self::STATUS_ENABLE => '启用',
            self::STATUS_DISABLE => '停用'
        ],
    ];
    /**
     * 状态 启用
     */
    const STATUS_ENABLE = 1;
    /**
     * 状态 禁用
     */
    const STATUS_DISABLE = 2;
    // 状态查询范围
    public function scopeStatus(Query $query, $status = self::STATUS_ENABLE)
    {
        $query->where('user_status', $status);
    }

    /**
     * 写入前
     *
     * @param self $model
     * @return void
     * @date 2023-01-11
     * @example
     * @author admin
     * @since 1.0.0
     */
    public static function onBeforeWrite(self $model): void
    {
        self::checkRepeatData($model);
    }

    /**
     * 新增前
     *
     * @date 2022-02-22
     * @example
     * @author admin
     * @since 1.0.0
     */
    public static function onBeforeInsert(self $model): void
    {
        $model->completeCreateField();
    }

    /**
     * 更新前
     *
     * @date 2022-02-28
     * @example
     * @author admin
     * @since 1.0.0
     */
    public static function onBeforeUpdate(self $model): void
    {
        $model->completeUpdateField();
    }

    /**
     * 删除前
     *
     * @date 2022-02-28
     * @example
     * @author admin
     * @since 1.0.0
     */
    public static function onBeforeDelete(self $model): void
    {
        $model->completeDeleteField();
    }

    /**
     * 用户名搜索器
     *
     * @param Query $query
     * @param [type] $value
     * @param [type] $data
     * @return void
     * @date 2022-02-28
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function searchUserNameAttr(Query $query, $value, $data): void
    {
        if ($value) {
            $query->whereLike(join('|', [
                'user_name',
                //                'user_phone'
            ]),  "%$value%");
        }
    }


    /**
     * 设置用户密码
     *
     * @param string $value
     * @return string
     * @date 2022-12-28
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function setUserPasswordAttr(string $value): string
    {
        return self::encryptPassword($value);
    }

    /**
     * 获取用户管理员
     *
     * @date 2022-03-08
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function getUserAdminAttr(): bool
    {
        return $this->user_id == 1;
    }

    /**
     * 用户登录
     *
     * @return Token
     * @date 2023-01-03
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function login(): Token
    {
        if ($this->user_status != self::STATUS_ENABLE) {
            throwErrorMsg('该用户已被停用');
        }
        $menus = $this->getUserMenu();
        $api = [];
        foreach ($menus as $menu) {
            $api = array_merge($api, explode(',', $menu['menu_api_url']));
        }
        $api = array_values(array_filter(array_unique($api)));
        if (!$api) {
            throwErrorMsg('无权登录');
        }
        return Token::login($this->user_guid, [
            'menu' => $menus,
            'api' => $api,
        ]);
    }

    /**
     * 获取用户菜单
     *
     * @date 2022-03-15
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function getUserMenu(): array
    {
        $result = [];
        $query = Menu::join('menu_api', 'menu_api.menu_guid = menu.menu_guid', 'left')->field([
            'menu.menu_guid',
            'menu.menu_parent_guid',
            'menu.menu_name',
            'menu.menu_url',
            'menu.menu_show',
            'menu.menu_icon',

            'group_concat(menu_api.menu_api_url)' => 'menu_api_url'
        ])->order([
            'menu.menu_index',
            'menu.menu_order' => 'desc',
        ])->group('menu.menu_guid');
        if ($this->user_admin) {
            $result = $query->select()->toArray();
        } else {
            $menus = [];
            $roles = $this->roles()->with([
                'menus'
            ])->select();
            foreach ($roles as $role) {
                $menus = array_merge($menus, $role->menus->column('menu_guid'));
            }
            $result = $query->where([
                ['menu.menu_guid', 'in', $menus]
            ])->select()->toArray();
        }
        return $result;
    }

    /**
     * 数据查重
     *
     * @param self $model
     * @return void
     * @date 2022-03-11
     * @example
     * @author admin
     * @since 1.0.0
     */
    private static function checkRepeatData(self $model)
    {
        Validate::unique(self::class, $model->user_guid, $model->getData(), [
            'user_account' => '账户',
            'user_phone' => '手机号',
        ]);
    }

    /**
     * 密码加密
     *
     * @param string $password
     * @date 2022-02-22
     * @example
     * @author admin
     * @since 1.0.0
     */
    public static function encryptPassword(string $password): string
    {
        return md5($password);
    }
    /**
     * 获取角色
     *
     * @date 2022-03-11
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function roles(): BelongsToMany
    {
        return $this->belongsToMany(
            Role::class,
            UserRole::class,
            'role_guid',
            'user_guid'
        );
    }

    /**
     * 新增用户角色
     */
    public static function addUserRole($user_guid, $params): void
    {
        $user_role_arr = $params['roles'];

        foreach ($user_role_arr as $role => $item) {
            Db::startTrans();
            try {
                $add_data = [
                    'user_guid' => $user_guid,
                    'role_guid' => $item,
                ];
                $user_role = ModelUserRole::create($add_data);

                Db::commit();
            } catch (\Throwable $th) {
                Db::rollback();
                throw $th;
            }
        }
    }

    /**
     * 编辑用户角色
     */
    public static function editUserRole($params): void
    {
        // 从学生服务(副表)查询出所有当前学生的服务，进行删除
        ModelUserRole::where('user_guid', $params['user_guid'])->select()->delete();

        // 再把传值的数据，写入副表
        $user_role_arr = $params['roles'];
        foreach ($user_role_arr as $key => $item) {
            Db::startTrans();
            try {
                $add_data = [
                    'user_guid' => $params['user_guid'],
                    'role_guid' => $item,
                ];
                ModelUserRole::create($add_data);

                Db::commit();
            } catch (\Throwable $th) {
                Db::rollback();
                throw $th;
            }
        }
    }

    /**
     * 用户角色guid获取器
     */
    public function getRolesAttr($value, $data)
    {
        $user_guid = $data['user_guid'];
        $user_role_guid_arr = ModelUserRole::field([
            'role_guid',
        ])->where('user_guid', $user_guid)->select();

        $arr = [];
        foreach ($user_role_guid_arr as $key => $value) {
            $arr[] = $value['role_guid'];
        }
        return $arr;

        // return array_values($user_key_guid_arr);
    }

    /**
     * 用户角色名称获取器
     */
    public function getRoleNameAttr($value, $data)
    {
        $user_guid = $data['user_guid'];
        $user_role_guid_arr = ModelUserRole::field([
            'role_guid',
        ])->where('user_guid', $user_guid)->select();

        $arr = [];
        foreach ($user_role_guid_arr as $key => $value) {
            $model = Role::where('role_guid', $value['role_guid'])->find()->role_name;
            $arr[] = $model;
        }
        return implode(",", $arr);

        // return array_values($user_key_guid_arr);
    }

    /**
     * 用户角色名
     */
    public static function getRoleName($data)
    {
        $user_guid = $data['user_guid'];
        $user_role_guid_arr = ModelUserRole::field([
            'role_guid',
        ])->where('user_guid', $user_guid)->select();

        $arr = [];
        foreach ($user_role_guid_arr as $key => $value) {
            $model = Role::where('role_guid', $value['role_guid'])->find()->role_name;
            $arr[] = $model;
        }
        return implode(",", $arr);

        // return array_values($user_key_guid_arr);
    }


    /**
     * 角色名称转角色guid数组
     */
    public static function RoleNameToRoleGuidArr($params)
    {
        $roles = explode(",", $params['roles']);

        $user_role_guid_arr = [];
        foreach ($roles as $key => $item) {
            $role = Role::where('role_name', $item)->find();
            if (!$role) throwErrorMsg('角色不存在!');
            $user_role_guid_arr[] = $role->role_guid;
        }

        return $user_role_guid_arr;
    }

    /**
     * 导出Excel
     */
    public static function exportExcel($select)
    {
        $data = [[
            '用户名',
            '头像',
            '角色',
            '手机号',
        ]];
        foreach ($select as $key => $val) {

            $val['user_img'] = Excel::ExportImgFiled($val['user_img']);
            $user_role_name = self::getRoleName($val);

            $data[] = [
                $val['user_name'],
                $val['user_img'],
                $user_role_name,
                $val['user_phone'],
            ];
        }
        $excel = (new Excel())->exporTsheet($data);
        $excel->save('用户.xlsx');
    }


    /**
     * 导入数据处理
     */
    public static function HanleImportData($value)
    {
        // 判断用户是否存在
        $user_name = $value['user_name'];
        $user_type = self::where('user_name', $user_name)->find();
        if ($user_type) throwErrorMsg("{$user_name} 用户已存在，导入失败!");


        // 判断角色是否存在
        $roles_arr = explode(",", $value['roles']);
        foreach ($roles_arr as $key => $item) {
            $role = Role::where('role_name', $item)->find();
            if (!$role) throwErrorMsg("{$item} 角色不存在，导入失败!");
        }

        $password = md5($value['user_password']);

        $model = self::create([
            'user_name' => $value['user_name'],
            'user_img' => $value['user_img'],
            'user_phone' => $value['user_phone'],
            'user_password' => $password,
            'user_status' => 1,
        ]);

        $user_guid = $model->user_guid;
        $value['roles'] = self::RoleNameToRoleGuidArr($value);
        self::addUserRole($user_guid, $value);
    }


    /**
     * 导入Excel
     */
    public static function importExcel($file)
    {
        Db::startTrans();
        try {
            $excel = new Excel($file);
            // 表头
            $data = $excel->parseExcel(
                [
                    [
                        'title' => '用户名',
                        'validate' => 'require',
                        'field' => 'user_name',
                    ], [
                        'title' => '头像',
                        'field' => 'user_img',
                    ], [
                        'title' => '角色',
                        'validate' => 'require',
                        'field' => 'roles',
                    ], [
                        'title' => '手机号',
                        'field' => 'user_phone',
                    ], [
                        'title' => '密码',
                        'field' => 'user_password',
                    ]
                ],
                [
                    'titleLine' => [1]
                ]
            );
            if (!$data)  throwErrorMsg('excel无数据', 1);
            $error = [];

            foreach ($data as $line => $value) {
                try {
                    self::HanleImportData($value);
                    $error[] = "{$line}  用户:【{$value['user_name']}】<span style='color:#27af49'>新增成功!</span><br>";
                } catch (\Throwable $th) {
                    $error[] = "{$line}  用户:【{$value['user_name']}】<span style='color:red'>{$th->getMessage()}</span><br>";
                }
            }
            Db::commit();
            return implode(', ', $error);
        } catch (\Throwable $th) {
            Db::rollback();
            throw $th;
        }
    }
}
