<?php
namespace app\admin\logic\distribution;

use app\common\basics\Logic;
use app\common\model\distribution\Distribution;
use app\common\model\distribution\DistributionGoods;
use app\common\model\distribution\DistributionLevel;
use app\common\model\distribution\DistributionLevelUpdate;
use app\common\model\distribution\DistributionOrderGoods;
use app\common\model\order\Order;
use app\common\model\order\OrderTrade;
use think\facade\Db;

class DistributionLevelLogic extends Logic
{
    /**
     * @notes 分销等级列表
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author Tab
     * @date 2021/9/1 16:19
     */
    public static function index()
    {
        $field = [
            'id',
            'name',
            'weights' => 'weights_desc',
            'first_ratio',
            'second_ratio',
            'is_default',
            'id' => 'members_num'
        ];
        $lists = DistributionLevel::field($field)
            ->order('weights', 'asc')
            ->select()
            ->toArray();

        $count = DistributionLevel::count();

        return [
            'count' => $count,
            'lists' => $lists,
        ];
    }

    /**
     * @notes 添加分销会员等级
     * @param $params
     * @return bool
     * @author Tab
     * @date 2021/9/1 14:53
     */
    public static function add($params)
    {
        Db::startTrans();
        try{
            // 写入等级主表
            $params['remark'] = $params['remark'] ?? '';
            $newLevel = DistributionLevel::create($params);

            // 写入升级条件表
            self::addUpdateCondition($params, $newLevel->id);

            // 处理分销商品比例
            self::updateDistributionGoods($newLevel->id);

            Db::commit();
            return true;
        }catch(\Exception $e) {
            Db::rollback();
            self::$error = $e->getMessage();
            return false;
        }
    }

    /**
     * @notes 添加更新升级条件
     * @param $params
     * @param $level_id
     * @throws \Exception
     * @author Tab
     * @date 2021/9/1 15:08
     */
    public static function addUpdateCondition($params, $level_id)
    {
        $updateConditionData = [];
        foreach($params['update_condition'] as $key) {
            // 判断是否在规定的条件字段
            if(!in_array($key, DistributionLevel::UPDATE_CONDITION_FIELDS, true)) {
                continue;
            }
            if ($params[$key] < 0) {
                throw new \Exception('升级条件不允许小于0');
            }
            // 获取键对应值的字段名
            $valueField = DistributionLevel::getValueFiled($key);
            $updateConditionData[] = [
                'level_id' => $level_id,
                'key' => $key,
                $valueField => $params[$key]
            ];
        }
        (new DistributionLevelUpdate())->saveAll($updateConditionData);
    }

    /**
     * @notes 获取分销等级详情
     * @param $params
     * @return array
     * @author Tab
     * @date 2021/9/1 15:36
     */
    public static function detail($params)
    {
        $level = DistributionLevel::withoutField('create_time,update_time,delete_time')->findOrEmpty($params['id']);
        if($level->isEmpty()) {
            return [];
        }
        $level = $level->toArray();
        // 默认等级
        if($level['is_default']) {
            unset($level['self_ratio']);
            unset($level['third_ratio']);
            unset($level['update_relation']);
            return $level;
        }
        // 自定义等级
        $level['update_condition'] = self::getUpdateCondition($level);
        unset($level['self_ratio']);
        unset($level['third_ratio']);

        return $level;
    }

    /**
     * @notes 获取升级条件
     * @param $level
     * @return array
     * @author Tab
     * @date 2021/9/1 15:36
     */
    public static function getUpdateCondition($level)
    {
        $updateCondition = DistributionLevelUpdate::where('level_id', $level['id'])->column('key,value_int,value_decimal,value_text');
        $updateConditionData = [];
        foreach($updateCondition as $item) {
            if($item['value_int']) {
                $updateConditionData[$item['key']] = $item['value_int'];
                continue;
            }
            if($item['value_decimal']) {
                $updateConditionData[$item['key']] = $item['value_decimal'];
                continue;
            }
            if($item['value_text']) {
                $updateConditionData[$item['key']] = $item['value_text'];
                continue;
            }
        }
        $data = [
            'keys' => array_keys($updateConditionData),
            'data' => $updateConditionData
        ];
        // 补全条件
        foreach(DistributionLevel::UPDATE_CONDITION_FIELDS as $field) {
            if(!isset($data['data'][$field])) {
                $data['data'][$field] =  '';
            }
        }
        return $data;
    }

    /**
     * @notes 编辑分销等级
     * @param $params
     * @return bool
     * @author Tab
     * @date 2021/9/1 16:20
     */
    public static function edit($params)
    {
        Db::startTrans();
        try{
            $params['remark'] = $params['remark'] ?? '';
            $level = DistributionLevel::findOrEmpty($params['id']);
            if($level->isEmpty()) {
                throw new \Exception('等级不存在');
            }
            // 默认等级
            if($level->is_default) {
                $level->allowField(['name', 'first_ratio', 'second_ratio','remark'])->save($params);
                Db::commit();
                return true;
            }
            // 自定义等级 - 更新主表信息
            if(!$params['weights'] > 1) {
                throw new \Exception('级别须大于1');
            }
            if(!isset($params['update_relation'])) {
                throw new \Exception('请选择升级关系');
            }
            if(!isset($params['update_condition']) || !count($params['update_condition'])) {
                throw new \Exception('请选择升级条件');
            }
            $level->allowField(['name', 'weights', 'first_ratio', 'second_ratio','remark', 'update_relation'])->save($params);

            // 自定义等级 - 删除旧升级条件
            $deleteIds = DistributionLevelUpdate::where('level_id', $level->id)->column('id');
            DistributionLevelUpdate::destroy($deleteIds);

            // 自定义等级 - 添加新的升级条件
            self::addUpdateCondition($params, $level->id);

            Db::commit();
            return true;
        }catch(\Exception $e) {
            Db::rollback();
            self::$error = $e->getMessage();
            return false;
        }
    }

    /**
     * @notes 删除分销等级
     * @param $params
     * @return bool
     * @author Tab
     * @date 2021/9/1 16:21
     */
    public static function delete($params)
    {
        Db::startTrans();
        try{
            $level = DistributionLevel::findOrEmpty($params['id']);
            if($level->isEmpty()) {
                throw new \Exception('等级不存在');
            }
            if($level->is_default) {
                throw new \Exception('系统默认等级不允许删除');
            }

            // 重置该等级下的分销会员为系统默认等级
            $defaultId = DistributionLevel::where('is_default', 1)->value('id');
            Distribution::where('level_id', $level->id)->update(['level_id' => $defaultId]);

            // 删除升级条件
            $deleteIds = DistributionLevelUpdate::where('level_id', $level->id)->column('id');
            DistributionLevelUpdate::destroy($deleteIds);

            // 删除该等级下的分销商品比例
            $deleteIds = DistributionGoods::where('level_id', $level->id)->column('id');
            DistributionGoods::destroy($deleteIds);

            // 删除等级
            $level->delete();

            Db::commit();
            return true;
        }catch(\Exception $e) {
            Db::rollback();
            self::$error = $e->getMessage();
            return false;
        }
    }

    /**
     * @notes 更新分销会员等级
     * @param $userId
     * @return false
     * @author Tab
     * @date 2021/9/2 16:39
     */
    public static function updateDistributionLevel($userId)
    {
        // 非默认等级
        $levels = DistributionLevel::where('is_default', 0)
            ->order('weights', 'desc')
            ->column('id,name,weights,update_relation', 'id');

        $userInfo = Distribution::alias('d')
            ->leftJoin('distribution_level dl', 'dl.id = d.level_id')
            ->field('d.is_distribution,d.level_id,dl.weights')
            ->where('d.user_id', $userId)
            ->findOrEmpty()
            ->toArray();

        // 非分销会员直接返回false
        if(empty($userInfo) || !$userInfo['is_distribution']) {
            return false;
        }

        foreach($levels as $level) {
            if(self::isMeetConditions($userId, $level) && $level['weights'] > $userInfo['weights']) {
                // 满足升级条件且是升更高的等级
                Distribution::where(['user_id' => $userId])->update(['level_id' => $level['id']]);
                break;
            }
        }
    }

    /**
     * @notes 判断是否满足当前等级的升级条件
     * @param $userId
     * @param $level
     * @return bool
     * @author Tab
     * @date 2021/9/2 16:42
     */
    public static function isMeetConditions($userId, $level)
    {
        // 任一条件满足升级
        if($level['update_relation'] == 1) {
            $flagOr = self::singleConsumptionAmountFlag($userId, $level) || self::cumulativeConsumptionAmountFlag($userId, $level) || self::cumulativeConsumptionTimesFlag($userId, $level) || self::returnedCommissionFlag($userId, $level);
            return $flagOr;
        }

        // 全部条件满足升级
        if($level['update_relation'] == 2) {
            $flagAnd = self::singleConsumptionAmountFlag($userId, $level) && self::cumulativeConsumptionAmountFlag($userId, $level) && self::cumulativeConsumptionTimesFlag($userId, $level) && self::returnedCommissionFlag($userId, $level);
            return $flagAnd;
        }
    }

    /**
     * @notes 判断是否满足单笔消费金额条件
     * @param $userId
     * @param $level
     * @return bool
     * @author Tab
     * @date 2021/9/2 16:44
     */
    public static function singleConsumptionAmountFlag($userId, $level)
    {
        $condition = DistributionLevelUpdate::field('value_int,value_decimal,value_text')
            ->where([
                'level_id' => $level['id'],
                'key' => 'singleConsumptionAmount'
            ])
            ->findOrEmpty();
        if($condition->isEmpty()) {
            // 没有该条件代表无需判断,直接返回true
            return true;
        }
        $recentOrder = Order::where([
            'user_id' =>  $userId,
            'pay_status' => 1
        ])
            ->order('id', 'desc')
            ->findOrEmpty();
        if($recentOrder->isEmpty()) {
            return false;
        }
        $singleConsumptionAmount = OrderTrade::where('id', $recentOrder['trade_id'])->findOrEmpty()->toArray();
        if($singleConsumptionAmount['order_amount'] >= $condition['value_decimal']) {
            return true;
        }
        return false;
    }

    /**
     * @notes 判断是否满足累计消费金额条件
     * @param $userId
     * @param $level
     * @return bool
     * @author Tab
     * @date 2021/9/2 16:50
     */
    public static function cumulativeConsumptionAmountFlag($userId, $level)
    {
        $condition = DistributionLevelUpdate::field('value_int,value_decimal,value_text')
            ->where([
                'level_id' => $level['id'],
                'key' => 'cumulativeConsumptionAmount'
            ])
            ->findOrEmpty();
        if($condition->isEmpty()) {
            // 没有该条件代表无需判断,直接返回true
            return true;
        }
        $cumulativeConsumptionAmount = Order::where([
            'user_id' =>  $userId,
            'pay_status' => 1
        ])->sum('order_amount');
        if($cumulativeConsumptionAmount >= $condition['value_decimal']) {
            return true;
        }
        return false;
    }

    /**
     * @notes 判断是否满足累计消费次数条件
     * @param $userId
     * @param $level
     * @return bool
     * @author Tab
     * @date 2021/9/2 16:53
     */
    public static function cumulativeConsumptionTimesFlag($userId, $level)
    {
        $condition = DistributionLevelUpdate::field('value_int,value_decimal,value_text')
            ->where([
                'level_id' => $level['id'],
                'key' => 'cumulativeConsumptionTimes'
            ])
            ->findOrEmpty();
        if($condition->isEmpty()) {
            // 没有该条件代表无需判断,直接返回true
            return true;
        }
        $allTradeIds = Order::where([
            'user_id' =>  $userId,
            'pay_status' => 1
        ])->column('trade_id');
        $cumulativeConsumptionTimes = count(array_unique($allTradeIds));
        if($cumulativeConsumptionTimes >= $condition['value_int']) {
            return true;
        }
        return false;
    }

    /**
     * @notes 判断是否消费已返佣金条件
     * @param $userId
     * @param $level
     * @return bool
     * @author Tab
     * @date 2021/9/2 17:06
     */
    public static function returnedCommissionFlag($userId, $level)
    {
        $condition = DistributionLevelUpdate::field('value_int,value_decimal,value_text')
            ->where([
                'level_id' => $level['id'],
                'key' => 'returnedCommission'
            ])
            ->findOrEmpty();
        if($condition->isEmpty()) {
            // 没有该条件代表无需判断,直接返回true
            return true;
        }
        $returnedCommission = DistributionOrderGoods::where([
            'user_id' => $userId,
            'status' => 2
        ])->sum('money');
        if($returnedCommission >= $condition['value_decimal']) {
            return true;
        }
        return false;
    }

    /**
     * @notes 获取所有分销会员等级
     * @return array
     * @author Tab
     * @date 2021/9/2 18:31
     */
    public static function getLevels()
    {
        return DistributionLevel::order('weights', 'asc')->column('id, name,weights');
    }

    /**
     * @notes 更新分销商品比例
     * @param $levelId
     * @author Tab
     * @date 2021/9/7 17:27
     */
    public static function updateDistributionGoods($levelId)
    {
        // 处理单独设置比例的商品,新增分销会等级佣金比例初始化为0
        $field = [
            'shop_id',
            'goods_id',
            'item_id',
        ];
       $distribution = DistributionGoods::distinct(true)->field($field)->where('rule', 2)->select()->toArray();
       $addData = [];
       foreach($distribution as $item) {
            $temp = [
                'shop_id' => $item['shop_id'],
                'goods_id' => $item['goods_id'],
                'item_id' => $item['item_id'],
                'level_id' => $levelId,
                'first_ratio' => 0,
                'second_ratio' => 0,
                'rule' => 2,
            ];
            $addData[] = $temp;
       }
        (new  DistributionGoods())->saveAll($addData);
    }
}