<?php

namespace app\api\controller;

use app\api\controller\Common;
use app\common\model\PartyJoin;
use fast\Random;
use app\common\controller\RedisLeaderboard;
use Redis;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use think\exception\ValidateException;
use think\Request;
use app\common\service\RoomService;
use app\common\library\GatewayworkerTools;

/**
 * 派对信息接口
 */
class Party extends Common
{
    protected $noNeedLogin = ['updatePartyInfo','getPatyType','addUserPositionToParty', 'clearMoney','clearCharm','getPartyRankList','getDefaultBackground','getPartGifList','getPartHeadgifList','isNotalk','getMusicList','updateTops','handleParty'];
    protected $noNeedRight = ['*'];

    public function __construct(Request $request = null)
    {
        $this->roomTypeArr = [1=>"party",2=>"live"];

        parent::__construct($request);
    }




    /**
     * 全麦/单独赠送礼物
     */
    public function giveGiftToYou() {
        // 是否背包赠送: 1=是,0=否
        $is_back = $this->request->request("is_back",0);

        // 接口防并发
        if($is_back){
            if (!$this->apiLimit(50, 1000)) {
                //1000毫秒50次
                $this->error(__('Operation frequently'));
            }
        }else{
            if (!$this->apiLimit(10, 1000)) {
                //1000毫秒10次
                $this->error(__('Operation frequently'));
            }
        }

        //送礼物权限
        if($this->auth->power['give_gift'] == 1){
            $this->error('您已被限制:赠送礼物,请联系管理员');
        }

        //接收参数
        $user_ids = $this->request->request("user_id");// 赠送对象
        $gift_id = $this->request->request("gift_id");// 礼物ID。如果是背包赠送,则是gift_back表的id,这样不合理,但是已经不好改了
        $party_id = $this->request->request("party_id",0);// 派对ID
        $room_type = $this->request->request('room_type',1); // 房间类型
        $number = $this->request->request("number");// 赠送数量

        if (!$user_ids || !in_array($is_back,[0,1]) || !$gift_id || !$number || !in_array($room_type,[1,2]))
        {
            $this->error(__('Invalid parameters'));
        }
        if(!$party_id){
            $this->error('只有房间内能送礼物');
        }

        //处理参数
        $user_id_arr = explode(",",$user_ids);
        $userCount = count($user_id_arr);
        $userauthid = $this->auth->id;
        $money_to_jewel = config('site.money_to_jewel') ?: 10; //余额兑换钻石
        $userModel = new \app\common\model\User();

        // 不可以赠送给自己
        //if(in_array($userauthid,$user_id_arr)) $this->error("不可以赠送给自己!");

        $backGiftId = 0; //背包礼物表的 gift_id
        $boxgiftInfo = [];

        //每个人都能得到的礼物价值
        $giftValue = 0;
        //每个人都能得到的礼物价值
        $getValue = 0;
        //热度值
        $hotValue = 0;

        if($is_back == 1) {
            // 获取背包礼物信息
            $giftInfo = \app\common\model\GiftBack::get($gift_id);
            if(!$giftInfo){
                $this->error("背包礼物获取失败");
            }
            $backGiftId = $giftInfo->gift_id;

            // 随机获取一个礼物
            $allCount = $number*$userCount;
            $giftbackList = \app\common\model\GiftBack::where(["gift_id"=>$backGiftId,"user_id"=>$userauthid,'is_use'=>0])->limit($allCount)->select();
            $giftInfo = isset($giftbackList[0]) ? $giftbackList[0] : [];
            $giftcount = 0;
            $giftList = [];

            if(!empty($giftbackList)) {
                foreach($giftbackList as $k => $v) {
                    $giftcount =  $giftcount + $v["number"];
                    $giftList[$k] = $v;
                    if($giftcount >= $allCount) {
                        break;
                    }
                }
            }

            if($giftcount < $allCount) $this->error("背包数量不足");
            $giftValue = $giftInfo["value"] * $number;
            $getValue  = $giftValue;
        } else {

            // 获取礼物信息
            $giftInfo = Db::name('gift')->where('id',$gift_id)->find();
            if (!$giftInfo) {
                $this->error("请选择礼物!");
            }
            $giftValue = $giftInfo["value"] * $number;
            $getValue  = $giftValue;

            // 判断当前用户余额,这里不需要锁表,钱包操作会锁
            $giftCountValue = $giftInfo["value"] * $number * $userCount;
            if($this->auth->jewel < $giftCountValue){
                $this->error("您的钻石余额不足!");
            }

        }

        //此时 $giftValue,$getValue,$hotValue是相等的
        $hotValue = $getValue;

        // 转换声币后 再进行抽点设置
        $partyInfo = null;
        if(!$party_id) {
            $platRate = 10;
            $guilderRate = 30;
        } else {
            $partyInfo = \app\common\model\Party::field("user_id,platRate,guilderRate")->where(["id"=>$party_id])->find();
            // 获取系统配置信息
            $platRate    = $partyInfo->platRate; // 平台抽成百分比
            $guilderRate = $partyInfo->guilderRate; // 工会长抽成百分比
        }

        $platValue    = bcmul($platRate/100   ,$getValue,2); //平台抽成
        $guilderValue = bcmul($guilderRate/100,$getValue,2);// 工会长抽成
        $getValue     = bcsub(bcsub($getValue ,$platValue,2),$guilderValue,2);//减去抽成剩余价值

//        $gif_image = $is_back==1?$giftInfo["gif_image"]:$giftInfo["special"];
        $returnData = [];
        Db::startTrans();
        try {
            $redis = new Redis();
            $redisconfig = config("redis");
            $redis->connect($redisconfig["host"], $redisconfig["port"], 86400 * 31);
            if ($redisconfig['redis_pwd']) {
                $redis->auth($redisconfig['redis_pwd']);
            }
            if($redisconfig['redis_selectdb'] > 0){
                $redis->select($redisconfig['redis_selectdb']);
            }

            // 获取当天零点
            $day = date("Ymd");
            // 获取本周第一天
            $weekday = $this->firstOfWeek(date("Y-m-d H:i:s"));
            // 获取本月第一天
            $monthday = date("Ym01");

            $allVal = 0;
            $i = 0;
            foreach($user_id_arr as $user_id) {
                // 获取赠送用户信息
                $where = [];
                $where["id"] = $user_id;
                $touserInfo = $userModel->where($where)->find();

                if($is_back == 1) {
                    $b=0;
                    foreach($giftList as $k => $v) {
                        for($a=1;$a<=$v["number"];$a++) {
                            $b++;
                            $num = $v["number"] - $a;
                            if($num > 0) {
                                $res1 = \app\common\model\GiftBack::where(["id"=>$v["id"]])->setDec("number");
                            } else {
                                $res1 = \app\common\model\GiftBack::update(["is_use"=>1,"use_time"=>time()],["id"=>$v["id"]]);
                            }
                            if($b == $number) break;
                        }

                    }
                    $res2 = true;
                } else {
                    $res1 = true;
                    $res2 = true;

                    // 扣除当前用户钻石余额
                    $rs_wallet = model('wallet')->lockChangeAccountRemain($userauthid, $giftValue, '-', $this->auth->jewel, "赠送礼物:'" . $giftInfo["name"] . "',扣除" . $giftValue . "钻石!", 3,'jewel');
                    if($rs_wallet['status'] == false){
                        $this->error($rs_wallet['msg']);
                        Db::rollback();
                    }
                }

                $giftuserpartyModel = new \app\common\model\GiftUserParty();
                // 添加礼物赠送记录表
                $data = [];
                $data["user_id"] = $userauthid;
                $data["user_to_id"] = $user_id;
                $data["party_id"] = $party_id;

                if($boxgiftInfo){
                    $data["gift_id"] = $boxgiftInfo['gift_id'];
                    $data["gift_give_type"] = 2;
                    $data["gift_name"] = $boxgiftInfo["gift_name"];
                    $data["gift_gif_image"] = $boxgiftInfo["image"];
                    $data["number"] = $number;
                    $data["price"] = $boxgiftInfo["price"];
                    $data["value"] = $boxgiftInfo["price"] * $number;
                }else{
                    $data["gift_id"] = $backGiftId > 0 ? $backGiftId : $gift_id;
                    $data["gift_give_type"] = $is_back ? 1 : 2;
                    $data["gift_name"] = $giftInfo["name"];
                    $data["gift_gif_image"] = $giftInfo["image"];
                    $data["number"] = $number;
                    $data["price"] = $giftInfo["value"];
                    $data["value"] = $giftValue;
                }

                //每个礼物都要计算平台抽成和房主抽成
                $data['platvalue'] = bcmul($platRate/100,$data["value"],2);
                $data['guildervalue'] = bcmul($guilderRate/100,$data["value"],2);
                $data['guildermoney'] = bcdiv($data['guildervalue'],$money_to_jewel,2);

                $data["createtime"] = time();
                $res5 = $giftuserpartyModel->allowField(true)->save($data);
                $this->bigGiftNotice($giftuserpartyModel);

                // 添加获赠用户余额
                if($getValue > 0){
                    $getMoney = bcdiv($getValue,$money_to_jewel,2);
                    if($getMoney > 0){
                        $rs_wallet = model('wallet')->lockChangeAccountRemain($user_id,$getMoney,'+',0,"{$this->auth->nickname}送你{$giftInfo['name']}x{$number}",101,'money');
                        if($rs_wallet['status'] == false){
                            $this->error($rs_wallet['msg']);
                            Db::rollback();
                        }
                    }
                }

                // 增加房主抽成
                if ($partyInfo && $guilderValue > 0) {
                    $guilderMoney = bcdiv($guilderValue,$money_to_jewel,2);
                    if($guilderMoney > 0){
                        $rs_wallet = model('wallet')->lockChangeAccountRemain($partyInfo->user_id,$guilderMoney,'+',0,"{$this->auth->nickname}送礼物{$giftInfo['name']}x{$number}给{$touserInfo['nickname']},房间礼物抽成",102,'money');
                        if($rs_wallet['status'] == false){
                            $this->error($rs_wallet['msg']);
                            Db::rollback();
                        }
                    }
                }


                if ($res1 && $res2 && $res5) {
                    $i++;
                    if($party_id > 0) {
                        // 添加redis记录做财富排行榜日榜用
                        $redis->zIncrBy($this->roomTypeArr[$room_type] . "_jewel_get_" . $party_id . ":" . $day . "d", $hotValue, $user_id);
                        // 添加redis记录做财富排行榜周榜用
                        $redis->zIncrBy($this->roomTypeArr[$room_type] . "_jewel_get_" . $party_id . ":" . $weekday . "w", $hotValue, $user_id);
                        // 添加redis记录做财富排行榜月榜用
                        $redis->zIncrBy($this->roomTypeArr[$room_type] . "_jewel_get_" . $party_id . ":" . $monthday . "m", $hotValue, $user_id);
                        // 添加redis记录做贡献排行榜日榜用
                        $redis->zIncrBy($this->roomTypeArr[$room_type] . "_jewel_to_" . $party_id . ":" . $day . "d", $giftValue, $userauthid);
                        // 添加redis记录做贡献排行榜周榜用
                        $redis->zIncrBy($this->roomTypeArr[$room_type] . "_jewel_to_" . $party_id . ":" . $weekday . "w", $giftValue, $userauthid);
                        // 添加redis记录做贡献排行榜月榜用
                        $redis->zIncrBy($this->roomTypeArr[$room_type] . "_jewel_to_" . $party_id . ":" . $monthday . "m", $giftValue, $userauthid);

                        // tcp 更新用户魅力值
                        $this->updateUserCharm($party_id, $user_id, $hotValue);

                        // 如果是主播,则添加魅力值记录做榜单统计
                        if($room_type == 2) {
                            $data = [];
                            $data["user_id"] = $user_id;
                            $data["party_id"] = $party_id;
                            $data["charm"] = $hotValue;
                            $data["createtime"] = time();
                            \app\common\model\UserCharmRank::insert($data);

                        }

                    }
                    $getempirical = config("site.getempirical");
                    $getempirical = $getempirical * $hotValue;
                    // 获取用户贵族信息
                    $noble = \app\common\model\User::getUserNoble($this->auth->id);
                    if(isset($noble["noble_on"]) && $noble["noble_on"] == 1) {
                        $getempirical = $getempirical + $getempirical * ($noble["explain"]/100);
                    }

                    // 增加用户经验值
                    $res = \app\common\model\User::addEmpirical($this->auth->id,$getempirical);
                    if ($res){
                        $this->auth->level = $res->level;
                    }

                    //增加被送礼物用户的魅力等级
                    $res_charm = \app\common\model\User::add_charm_level($user_id,$giftValue);


                    // +exp
                    \app\common\model\TaskLog::tofinish($this->auth->id,"OBHqCX4g",$number);

                    //贵族升级处理
                    //$this->checkBeNoble($redis,$this->auth->id,$giftCountValue);

                    // +message
                    \app\common\model\Message::addMessage($user_id,"礼物通知","收到 ".$this->auth->nickname." 赠送的".$giftInfo["name"]." x".$number." 价值 ".$giftValue ." 钻石");

                    $allVal = $allVal + $hotValue;

//                    // 剪掉背包礼物
//                    if($is_back == 1) {
//                        \app\common\model\GiftBack::update(["is_use"=>1],["id"=>$gift_id]);
//                    }

                }
            }

            // 获取用户魅力值
            $users = $redis->zRange("hourCharm_".$party_id,0,-1,true);
            $u = [];
            if($users) {
                foreach($users as $k => $v) $u[] = [
                    "user_id"=>$k,
                    "charm"=>$this->changeW($v)
                ];
            }
            $userCharm = $u;
            // tcp 更新房间热度
            $partyHot = $this->updatePartyHot($party_id, $allVal, $room_type);

            // 如果是派对,则添加派对热度值记录做榜单统计
            if($room_type == 1) {
                $data = [];
                $data["party_id"] = $party_id;
                $data["hot"] = $allVal;
                $data["createtime"] = time();
                \app\common\model\PartyHot::insert($data);
            }

            //增加送礼用户的财富等级
            $res_wealth = \app\common\model\User::add_wealth_level($this->auth->id,$allVal);

            // tcp 获取房间用户周前三名
            $partyUserTop = $this->getPartyUserTop($party_id, $room_type);

            if($i == $userCount) {
                $returnData["userCharm"] = $userCharm;
                $returnData["partyHot"] = $this->changeW($partyHot);
                $returnData["partyUserTop"] = $partyUserTop;
                if($is_back != 1) {
                    if($giftInfo->box_type > 0) { // 不是背包,宝箱中赠送
                        $returnData["box_type"] = $giftInfo->box_type;
                        $returnData["box_image"] = $giftInfo->image;
                        $returnData["image"] = $boxgiftInfo["image"];
                        $returnData["name"] = $boxgiftInfo["gift_name"];
                        $returnData["gif_image"] = $boxgiftInfo["special"];
                    } else {
                        $returnData["image"] = $giftInfo["image"];
                        $returnData["gif_image"] = $giftInfo["special"];
                    }
                } else {
                    $returnData["image"] = $giftInfo["image"];
                    $returnData["gif_image"] = $giftInfo["gif_image"];
                }

                // 增加抽点记录
                $data = [];
                $data["user_id"] = $user_ids;
                $data["party_id"] = $party_id?$party_id:0;
                $data["gift_value"] = $giftValue;
                $data["plat_value"] = $platValue;
                $data["guilder_value"] = $guilderValue;
                $data["createtime"] = time();
                \app\common\model\UserProfitLog::insert($data);

                Db::commit();
                $this->success("赠送成功!",$returnData);
            } else {
                $this->success("赠送失败!");
            }
        } catch (ValidateException $e) {
            Db::rollback();
            $this->error($e->getMessage());
        } catch (PDOException $e) {
            Db::rollback();
            $this->error($e->getMessage());
        } catch (Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
    }

}