<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载:https://gitee.com/likeshop_gitee
// | github下载:https://github.com/likeshop-github
// | 访问官网:https://www.likeshop.cn
// | 访问社区:https://home.likeshop.cn
// | 访问手册:http://doc.likeshop.cn
// | 微信公众号:likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用,未经许可不能去除前后端官方版权标识
// |  likeshop系列产品收费版本务必购买商业授权,购买去版权授权后,方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------


namespace app\api\logic;


use app\common\enum\DistributionOrderGoodsEnum;
use app\common\enum\NoticeEnum;
use app\common\model\distribution\Distribution;
use app\common\model\distribution\DistributionLevel;
use app\common\server\ConfigServer;
use app\common\model\user\UserDistribution;
use app\common\model\user\User;
use app\common\model\distribution\DistributionMemberApply;
use app\common\model\distribution\DistributionOrderGoods;
use app\common\server\AreaServer;
use app\common\server\JsonServer;
use app\common\server\UrlServer;
use app\common\basics\Logic;
use app\common\logic\AccountLogLogic;
use app\common\model\AccountLog;
use think\Exception;
use think\facade\Db;

class DistributionLogic extends Logic
{
    /**
     * Notes: 根据后台设置返回当前生成用户的分销会员状态(设置了全员分销,新生成的用户即为分销会员)
     * @author 段誉(2021/4/7 14:48)
     * @return int
     */
    public static function isDistributionMember()
    {
        $is_distribution = 0;
        //分销会员申请--1,申请分销; 2-全员分销;
        $distribution = ConfigServer::get('distribution', 'member_apply', 1);
        if ($distribution == 2) {
            $is_distribution = 1;
        }
        return $is_distribution;
    }

    /**
     * Desc: 生成用户扩展表
     * @param $user_id
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function createUserDistribution($user_id)
    {
        $user_distribution = UserDistribution::where(['user_id' => $user_id])->find();

        if ($user_distribution) {
            return true;
        }

        $data = [
            'user_id' => $user_id,
            'distribution_order_num' => 0,
            'distribution_money' => 0,
            'fans' => 0,
            'create_time' => time(),
        ];
        UserDistribution::create($data);
        return true;
    }


    /**
     * 申请分销会员
     */
    public static function apply($post)
    {
            $time = time();
            $data = [
                'user_id'       => $post['user_id'],
                'real_name'     => $post['real_name'],
                'mobile'        => $post['mobile'],
                'province'      => $post['province'],
                'city'          => $post['city'],
                'district'      => $post['district'],
                'reason'        => $post['reason'],
                'status'        => 0, // 待审核
                'create_time'   => $time,
                'update_time'   => $time,
            ];
            return DistributionMemberApply::create($data);
    }

    /**
     * 最新分销申请详情
     */
    public static function applyDetail($userId)
    {
        $result = DistributionMemberApply::field(['real_name','mobile','province', 'city', 'district', 'reason', 'denial_reason', 'status'])
            ->where('user_id', $userId)
            ->order('id', 'desc')
            ->findOrEmpty();

        if ($result->isEmpty()) {
            return [];
        }
        $result = $result->toArray();
        $result['province'] = AreaServer::getAddress($result['province']);
        $result['city'] = AreaServer::getAddress($result['city']);
        $result['district'] = AreaServer::getAddress($result['district']);

        switch ($result['status']) {
            case 0:
                $result['status_str'] = '已提交,等待客服审核...';
                break;
            case 1:
                $result['status_str'] = '已审核通过';
                break;
            case 2:
                $result['status_str'] = '审核失败,请重新提交审核';
                break;
        }
        return $result;
    }

    /**
     * 分销主页
     */
    public static function index($userId)
    {
        // 自身及上级信息
        $user_info = self::myLeader($userId);
        // 粉丝数(一级/二级)
        $fans = User::where([
            ['first_leader|second_leader', '=', $userId],
            ['del', '=', 0]
        ])->count();

        //今天的预估收益(待返佣)
        $today_earnings = DistributionOrderGoods::whereDay('create_time')
            ->where(['status' => 1, 'user_id' => $userId])
            ->sum('money');

        //本月预估收益(待返佣)
        $month_earnings = DistributionOrderGoods::whereMonth('create_time')
            ->where(['status' => 1, 'user_id' => $userId])
            ->sum('money');

        //累计收益(已结算)
        $history_earnings = DistributionOrderGoods::where(['status' => 2, 'user_id' => $userId])
            ->sum('money');

        // 用户分销会员等级
        $levelId = Distribution::where('user_id', $userId)->value('level_id');
        $levelName = DistributionLevel::getLevelNameTwo($levelId);

        $data = [
            'user' => $user_info['user'],
            'leader' => $user_info['leader'],
            'fans' => $fans,
            'able_withdrawal' => $user_info['user']['earnings'],//可提现佣金
            'today_earnings' => round($today_earnings, 2),//今天预估收益
            'month_earnings' => round($month_earnings, 2),//本月预估收益
            'history_earnings' => round($history_earnings, 2),//累计收益
            'level_name' => $levelName
        ];
        return $data;
    }

    /***
     * 获取自身及上级信息
     */
    public static function myLeader($userId)
    {
        $field = 'nickname,avatar,is_distribution,mobile,first_leader,distribution_code,earnings';

        $user = User::field($field)->where(['id' => $userId, 'del'=>0])->findOrEmpty();

        $first_leader = User::field('nickname,mobile')
            ->where(['id' => $user['first_leader'], 'del'=>0])
            ->findOrEmpty();

        $user['avatar'] = UrlServer::getFileUrl($user['avatar']);
        return [
            'user' => $user,
            'leader' => $first_leader,
        ];
    }

    /**
     * 填写邀请码
     */
    public static function code($post)
    {
        try {
            Db::startTrans();

            $firstLeader = User::field(['id', 'first_leader', 'second_leader', 'third_leader', 'ancestor_relation','user_integral'])
                ->where(['distribution_code' => $post['code']])
                ->findOrEmpty();
            if($firstLeader->isEmpty()) {
                throw new \think\Exception('无效的邀请码');
            }

            // 上级
            $first_leader_id = $firstLeader['id'];
            // 上上级
            $second_leader_id = $firstLeader['first_leader'];
            // 上上上级
            $third_leader_id = $firstLeader['second_leader'];
            // 拼接关系链
            $firstLeader['ancestor_relation'] = boolval($firstLeader['ancestor_relation']) ?? ''; // 清空null值及0
            $my_ancestor_relation = $first_leader_id. ',' . $firstLeader['ancestor_relation'];
            // 去除两端逗号
            $my_ancestor_relation = trim($my_ancestor_relation, ',');

            $user = User::findOrEmpty($post['user_id']);
            // 旧关系链
            if (!empty($user->ancestor_relation)) {
                $old_ancestor_relation = $user->id . ',' .$user->ancestor_relation;
            } else {
                $old_ancestor_relation = $user->id;
            }

            $data = [
                'first_leader' => $first_leader_id,
                'second_leader' => $second_leader_id,
                'third_leader' => $third_leader_id,
                'ancestor_relation' => $my_ancestor_relation,
                'update_time' => time()
            ];

            // 更新当前用户的分销关系
            User::where(['id' => $post['user_id']])->update($data);

            //更新当前用户下级的分销关系
            $data = [
                'second_leader' => $first_leader_id,
                'third_leader' => $second_leader_id,
                'update_time'  => time()
            ];
            User::where(['first_leader' => $post['user_id']])->update($data);

            //更新当前用户下下级的分销关系
            $data = [
                'third_leader' => $first_leader_id,
                'update_time'  => time()
            ];
            User::where(['second_leader' => $post['user_id']])->update($data);

            //更新当前用户所有后代的关系链
            $posterityArr = User::field('id,ancestor_relation')
                ->whereFindInSet('ancestor_relation', $post['user_id'])
                ->select()
                ->toArray();
            $updateData = [];
            $replace_ancestor_relation = $post['user_id'] . ','. $my_ancestor_relation;
            foreach($posterityArr as $item) {
                $updateData[] = [
                    'id' => $item['id'],
                    'ancestor_relation' => trim(str_replace($old_ancestor_relation, $replace_ancestor_relation, $item['ancestor_relation']), ',')
                ];
            }
            // 批量更新
            (new User())->saveAll($updateData);

            //邀请会员赠送积分
            $invited_award_integral = ConfigServer::get('marketing','invited_award_integral',0);
            if($invited_award_integral > 0){
                // 增加上级积分
                $firstLeader->user_integral += (int)$invited_award_integral;
                $firstLeader->save();
                // 增加上级积分变动记录
                AccountLogLogic::AccountRecord($firstLeader['id'],$invited_award_integral,1, AccountLog::invite_add_integral);
            }

            //通知用户
            event('Notice', [
                'scene' => NoticeEnum::INVITE_SUCCESS_NOTICE,
                'params' => [
                    'user_id' => $first_leader_id,
                    'lower_id' => $post['user_id'],
                    'join_time' => date('Y-m-d H:i:s', time())
                ]
            ]);

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

    /**
     * 分销订单
     */
    public static function order($get)
    {
        $where[] = ['d.user_id', '=', $get['user_id']];

        if (isset($get['status']) && in_array($get['status'], [1,2,3])) {
            $where[] = ['d.status', '=', $get['status']];
        }

        $field = 'd.create_time, d.money, d.goods_num, d.status, d.status as statusDesc, o.order_sn, og.total_pay_price as pay_price, g.image as goods_image, g.name as goods_name, gi.spec_value_str';

        $count = DistributionOrderGoods::alias('d')
            ->where($where)
            ->count();

        $lists = DistributionOrderGoods::alias('d')
            ->field($field)
            ->leftJoin('order_goods og', 'og.id = d.order_goods_id')
            ->leftJoin('order o', 'o.id = og.order_id')
            ->leftJoin('goods g', 'og.goods_id=g.id')
            ->leftJoin('goods_item gi', 'og.item_id=gi.id')
            ->where($where)
            ->order('d.create_time desc')
            ->page($get['page_no'], $get['page_size'])
            ->select()
            ->toArray();

        foreach ($lists as &$item) {
            $item['goods_image'] = empty($item['goods_image']) ? '' : UrlServer::getFileUrl($item['goods_image']);
        }

        $data = [
            'list' => $lists,
            'page' => $get['page_no'],
            'size' => $get['page_size'],
            'count' => $count,
            'more' => is_more($count, $get['page_no'], $get['page_size'])
        ];
        return $data;
    }

    /**
     * 月度账单
     */
    public static function monthBill($get)
    {
        $field = [
            "FROM_UNIXTIME(d.create_time,'%Y年%m月') as date",
            "FROM_UNIXTIME(d.create_time,'%Y') as year",
            "FROM_UNIXTIME(d.create_time,'%m') as month",
            'sum(d.money) as total_money',
            'count(d.id) as order_num'
        ];
        $count = DistributionOrderGoods::alias('d')
            ->field($field)
            ->leftJoin('order_goods g', 'g.id = d.order_goods_id')
            ->leftJoin('order o', 'o.id = g.order_id')
            ->where(['d.user_id' => $get['user_id']])
            ->where('d.status', 'in', [1, 2])
            ->group('date')
            ->count();

        $lists = DistributionOrderGoods::alias('d')
            ->field($field)
            ->leftJoin('order_goods g', 'g.id = d.order_goods_id')
            ->leftJoin('order o', 'o.id = g.order_id')
            ->where(['d.user_id' => $get['user_id']])
            ->where('d.status', 'in', [1, 2])
            ->order('d.create_time desc')
            ->page($get['page_no'], $get['page_size'])
            ->group('date')
            ->select()
            ->toArray();

        $data = [
            'list' => $lists,
            'page' => $get['page_no'],
            'size' => $get['page_size'],
            'count' => $count,
            'more' => is_more($count, $get['page_no'], $get['page_size'])
        ];
        return $data;
    }

    /**
     * 月度明细
     */
    public static function monthDetail($get)
    {
        $where[] = ['d.user_id', '=', $get['user_id']];

        $monthStr = $get['year'] . '-' . str_pad($get['month'], 2, '0', STR_PAD_LEFT);

        $field = 'd.create_time, d.money, d.goods_num, d.status, d.status as statusDesc, o.order_sn, og.total_pay_price as pay_price, g.image as goods_image, g.name as goods_name, gi.spec_value_str';

        $count = DistributionOrderGoods::alias('d')
            ->where($where)
            ->whereMonth('d.create_time', $monthStr)
            ->count();

        $lists = DistributionOrderGoods::alias('d')
            ->field($field)
            ->leftJoin('order_goods og', 'og.id = d.order_goods_id')
            ->leftJoin('order o', 'o.id = og.order_id')
            ->leftJoin('goods g', 'og.goods_id=g.id')
            ->leftJoin('goods_item gi', 'og.item_id=gi.id')
            ->where($where)
            ->whereMonth('d.create_time', $monthStr)
            ->order('d.create_time desc')
            ->page($get['page_no'], $get['page_size'])
            ->select()
            ->toArray();

        $data = [
            'list' => $lists,
            'page' => $get['page_no'],
            'size' => $get['page_size'],
            'count' => $count,
            'more' => is_more($count, $get['page_no'], $get['page_size'])
        ];
        return $data;
    }


    /**
     * Desc: 取消订单后更新分销订单为已失效
     * @param $order_id
     * @throws Exception
     * @throws \think\exception\PDOException
     */
    public static function setDistributionOrderFail($order_id)
    {
        //订单取消后更新分销订单为已失效状态
        return Db::name('distribution_order_goods d')
            ->join('order_goods og', 'og.id = d.order_goods_id')
            ->join('order o', 'o.id = og.order_id')
            ->where('o.id', $order_id)
            ->update([
                'd.status' => DistributionOrderGoodsEnum::STATUS_ERROR,
                'd.update_time' => time(),
            ]);
    }

    /**
     * @Notes: 分销佣金列表
     * @Author: 张无忌
     * @param $get
     * @param $user_id
     * @return bool|array
     */
    public static function commission($get, $user_id)
    {
        try {
            $where = [
                ['user_id', '=', $user_id],
                ['source_type', 'in', AccountLog::earnings_change]
            ];

            $model = new AccountLog();
            $count = $model->where($where)->count();
            $lists = $model->field(['id,source_type,change_amount,change_type,create_time'])
                ->where($where)
                ->order('id', 'desc')
                ->page($get['page_no'] ?? 1, $get['page_size'] ?? 20)
                ->select();

            foreach ($lists as &$item) {
                $symbol = $item['change_type'] == 1 ? '+' : '-';
                $item['change_amount'] = $symbol.$item['change_amount'];
            }

            return [
                'list'  => $lists,
                'page'  => $get['page_no']??1,
                'size'  => $get['page_size']??20,
                'count' => $count,
                'more'  => is_more($count, $get['page_no']??1, $get['page_size']??20)
            ];

        } catch (\Exception $e) {
            static::$error = $e->getMessage();
            return false;
        }
    }

    public static function fixAncestorRelation()
    {
        try {
            $userList = User::select()->toArray();
            if (empty($userList)) {
                throw new \Exception('没有用户,无需修复');
            }

            $updateEmptyData = [];
            $updateData = [];
            foreach($userList as $user) {
                $my_ancestor_relation = self::myAncestorRelation($user);
                $updateEmptyData[] = ['id' => $user['id'], 'ancestor_relation' => ''];
                $updateData[] = ['id' => $user['id'], 'ancestor_relation' => $my_ancestor_relation];
            }
            // 先清除所有关系链
            (new User())->saveAll($updateEmptyData);
            // 重新设置关系链
            (new User())->saveAll($updateData);

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

    public static function myAncestorRelation($user)
    {
        if (empty($user['first_leader'])) {
            return '';
        }

        return trim(self::findAncestorRelation($user['first_leader']), ',');
    }

    public static function findAncestorRelation($id, $flag = true)
    {
        static $ancestor_relation = '';
        if ($flag) {
            $ancestor_relation = '';
        }
        $ancestor_relation .= $id . ',';
        $user = User::findOrEmpty($id);
        if (empty($user['first_leader'])) {
            return $ancestor_relation;
        }
        return self::findAncestorRelation($user['first_leader'], false);
    }


    /**
     * @notes 获取背景海报
     * @return array|mixed|string|null
     * @author cjhao
     * @date 2021/11/29 11:35
     */
    public static function getPoster()
    {
        $poster = ConfigServer::get('invite', 'poster', '/images/share/share_user_bg.png');
        $poster = empty($poster) ? $poster : UrlServer::getFileUrl($poster);
        return ['poster'=>$poster];

    }
}