<?php

declare(strict_types=1);

namespace app\common\traits;

use app\common\arw\adjfut\src\Exception\ErrorMsg;
use app\common\model\User\User;
use app\Request;
use think\Model as ThinkModel;
use app\common\arw\adjfut\src\Tool;
use app\common\arw\adjfut\src\Validate;

/**
 * 模型层
 * @mixin ThinkModel
 */
trait Model
{
    private static $cacheUserGuid = '';

    /**
     * 设置用户guid
     *
     * @param string|bool $id
     * @return void
     * @date 2022-04-25
     * @example
     * @author admin
     * @since 1.0.0
     */
    public static function setUserGuid($id)
    {
        self::$cacheUserGuid = $id;
    }

    /**
     * 完善添加字段
     *
     * @param string $user
     * @param string $timeType
     * @return void
     * @date 2022-12-27
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function completeCreateField($user = 'user', string $timeType = 'datetime'): void
    {
        $this->completeBaseField('create', $user, $timeType);
    }

    /**
     * 完善更新字段
     *
     * @param string $user
     * @param string $timeType
     * @return void
     * @date 2022-12-27
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function completeUpdateField($user = 'user', string $timeType = 'datetime'): void
    {
        $this->completeBaseField('update', $user, $timeType);
    }

    /**
     * 完善删除字段
     *
     * @param string $user
     * @param string $timeType
     * @return void
     * @date 2022-12-27
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function completeDeleteField($user = 'user', string $timeType = 'datetime'): void
    {
        $this->completeBaseField('delete', $user, $timeType);
    }

    /**
     * 完善基础字段
     *
     * @param string $type create|update|delete
     * @param User|string $user
     * @param string $timeType datetime|timestamp
     * @return void
     * @date 2022-03-02
     * @example
     * @author admin
     * @since 1.0.0
     */
    public function completeBaseField($type, $user = 'user', string $timeType = 'datetime'): void
    {
        $table = $this->getTable();
        $createFieldTime = "${table}_create_time";
        $createFieldUserGuId = "${table}_create_user_guid";
        $updateFieldTime = "${table}_update_time";
        $updateFieldUserGuId = "${table}_update_user_guid";
        $deleteFieldTime = "${table}_delete_time";
        $deleteFieldUserGuId = "${table}_delete_user_guid";
        $guidField = "${table}_guid";

        $time = self::getCompleteBaseFieldTimeType($timeType);
        $user_guid = self::getCompleteBaseFieldUser($user);
        if (!$type) {
            throw new ErrorMsg("时间类型异常", 1);
        }
        $this->$updateFieldTime = $time;
        $this->$updateFieldUserGuId = $user_guid;

        if ($type === 'create') {
            $this->$createFieldTime = $time;
            $this->$createFieldUserGuId = $user_guid;
            $this->$guidField = self::generateGuid();
        }
        if ($type === 'delete') {
            $this->$deleteFieldTime = $time;
            $this->$deleteFieldUserGuId = $user_guid;
        }
    }

    // /**
    //  * 设置不使用的全局查询范围更新
    //  * 支持 onBeforeUpdate|onAfterUpdate|onBeforeWrite|onAfterWrite 事件
    //  *
    //  * @return void
    //  * @date 2022-03-12
    //  * @example
    //  * @author admin
    //  * @since 1.0.0
    //  */
    // public static function withoutGlobalScopeUpdate(array $scope, array $data)
    // {
    //     $model = new static;
    //     $pk = $model->getPk();
    //     if (!isset($data[$pk])) {
    //         throw new ErrorMsg("缺少主键", 1);
    //     }
    //     $query = $model::withoutGlobalScope($scope)->find($data[$pk]);
    //     if ($query === null) {
    //         throw new ErrorMsg("数据不存在", 1);
    //     }
    //     if (
    //         $model::onBeforeWrite($model) === false ||
    //         $model::onBeforeUpdate($model) === false
    //     ) {
    //         return false;
    //     }
    //     $model::withoutGlobalScope($scope)->save(array_merge($data, $model->getData()));
    //     $model::onAfterUpdate($model);
    //     $model::onAfterWrite($model);
    // }

    /**
     * 生成guid
     *
     * @param array|string $value
     * @return string
     * @date 2022-02-22
     * @example
     * @author admin
     * @since 1.0.0
     */
    protected static function generateGuid($value = '')
    {
        return Tool::generateGuid($value);
    }

    /**
     * 数据验证
     * 除非是require字段 有数据才验证
     *
     * @param array $data 数据
     * @param array $rules 规则
     * @param array $message 提示信息
     * @return void
     * @throws ValidateException
     */
    protected static function dataValidate(array $data, array $rules, array $message = [])
    {
        $_rules = [];
        $dataKeys = array_keys($data);
        foreach ($rules as $key => $rule) {
            list($field) = explode('|', $key);
            // 字段存在规则并且有值 或者 必传
            if ((in_array($field, $dataKeys) && !is_null($data[$field])) || preg_match('/require/', $rule)) {
                $_rules[$key] = $rule;
            }
        }
        Validate::check($data, $_rules, $message);
    }

    /**
     * 获取完善基础字段用户
     *
     * @param User|string $user
     * @return string
     * @date 2022-12-27
     * @example
     * @author admin
     * @since 1.0.0
     */
    private static function getCompleteBaseFieldUser($user): string
    {
        $cacheUserGuid = self::$cacheUserGuid;
        $user_guid = '';
        switch (true) {
            case (is_string($cacheUserGuid) && $cacheUserGuid):
                $user_guid = $cacheUserGuid;
                break;
            case (is_bool($cacheUserGuid) && $cacheUserGuid === false):
                // 无需验证 获取用户Guid
                break;
            case (is_bool($user) && $user === false):
                // 无需验证 获取用户Guid
                break;
            case ($user === 'user'):
            case ($user instanceof User):
                $user = $user === 'user' ? Request::getCurrentUser() : $user;
                $user_guid = $user->user_guid;
                break;
        }
        return $user_guid;
    }

    /**
     * 获取模型时间类型
     *
     * @param string $timeType datetime|timestamp
     * @return string
     * @date 2022-12-27
     * @example
     * @author admin
     * @since 1.0.0
     */
    private static function getCompleteBaseFieldTimeType($timeType): string
    {
        $time = '';
        switch ($timeType) {
            case 'datetime':
                $time = date('Y-m-d H:i:s');
                break;
            case 'timestamp':
                $time = time();
                break;
        }
        return $time;
    }
}
