<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/4/25
 * Time: 14:10
 */

namespace App\Lib\Settlement;
set_time_limit(600);
ini_set('memory_limit', '256M');

use Illuminate\Support\Facades\DB;
use App\Lib\Settlement\SettlementBase;
use App\Models\SettlementMiddleDetail as SettlementMiddleDetailModel;


/**
 * 按订单结算或重结算
 */
class SettlementOrder extends SettlementBase
{
    private $orderId = '';   //订单ID
    private $orderType = 1; //订单类型  1单式  2串式;
    private $BuyDatasMainModel = [];  //订单豪华版  单式一条   串式可能多条
    private $BuyDatas = [];  //订单豪华版  单式一条   串式可能多条
    private $match_id = 0;
    private $game_code = '';
    private $SN = 0;    //结算批次号
    private $hissettlementDetail = [];
    private $set_type = 0;


    //返回数据
    public static function makeData($status = 1, $message = 'success', $data = '')
    {
        return [
            'status' => $status,
            'message' => $message,
            'data' => $data,
        ];
    }


    ///$order_ids 某场比塞全部订单数组, $bettype=2 订单类型: 1单式  2串式（默认）,    $settype = 1 结算次数:1首次(默认)  2非首次或重结算
    public function reSettlement($order_ids, $bettype = 2, $settype = 1, $game_code = 0, $match_id = 0)
    {
        $order_ids = array_unique($order_ids);

        if (intval($match_id) <= 0) {
            return self::makeData(8, 'matchid不能为空或0!');
        }

        if (!in_array($bettype, [1, 2])) {
            return self::makeData(6, '订单类型参数错误!');
        }
        $this->orderType = $bettype;

        if (!in_array($settype, [1, 2])) {
            return self::makeData(6, '结算参数错误');
        }
        $this->set_type = $settype;

        if (empty($order_ids)) {
            $needs_matchs = DB::table('money_buy_match')->where(['game_code' => $game_code, 'match_id' => $match_id])->get();
            if (count($needs_matchs) <= 0) {
                $this->cgStatus($game_code, $match_id);
                return self::makeData();
            } else {
                return self::makeData(5, '订单号不能为空');
            }
        }


        if ($bettype == 1) {
            $chekArr = $this->Match_check($order_ids, $bettype);
            if (empty($chekArr) || count($chekArr) != 1) {
                return self::makeData(10, '不同场比赛不能同时结算！' . print_r($order_ids, true));
            }
        }
        $this->match_id = $match_id;
        $this->game_code = $game_code;


        try {
            DB::beginTransaction();

            $this->UndoSettlement($this->game_code, $this->match_id, $order_ids, $bettype);

            foreach ($order_ids as $order_id) {
                $this->BuyDatasMainModel = $this->orderTypeGet($order_id, $bettype);

                if ($this->BuyDatasMainModel->settle_status == 2 && $settype == 1) {
                    continue;
                }
                if ($bettype == 1) {
                    $this->SingOrder($order_id);
                } else {
                    $this->ChuanOrder($order_id);
                }
            }

            $this->cgStatus($game_code, $match_id);


            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            return self::makeData(-2, $e->getMessage());
        }
        return self::makeData();

    }

    public function orderTypeGet($order_id, $bettype)
    {
        if ($bettype == 1) {
            $datas = DB::table('money_buy_simplex')->where('order_id', $order_id)->first();
            $this->orderType = 1;
        } else {
            $datas = DB::table('money_buy_str')->where('order_id', $order_id)->first();
            $this->orderType = 2;
        }

        if (!$datas) {
            throw  new  \Exception('没有主订单信息');
        }

        return $datas;
    }

    /**
     * 单式注单结算
     * @param mixed $order_id 注单ID
     */
    public function singOrder($order_id)
    {
        // 查询订单下所有的单式注单
        $simplexData = $this->BuyDatasMainModel;

        $matchData = DB:: table('money_buy_match')->where(['bet_type' => 1, 'batch_id' => $simplexData->batch_id, 'match_id' => $simplexData->match_id])->get();
        if (count($matchData) <= 0) {
            throw new  \Exception("没有数据的错误!");
        }
        foreach ($matchData as $val) {
            if (!in_array($val->result, [-1, 1, 2, 3, 4])) {
                throw  new  \Exception('match 比赛结果异常或还没有输赢结果->' . $val->id);
            }
        }

        // 计算总回款
        $settlementBase = new \App\Lib\Settlement\SettlementBase;
        $returnMoney = 0;
        $oddsResult = [];
        foreach ($matchData as $k => $v) {
            if ($v->result == -1) {
                continue;
            }
            $oddsResult[0]['winOrLose'] = $v->result;
            $oddsResult[0]['odds'] = $v->odds;
            $getReturnMoney = $settlementBase->stringOdds($oddsResult);
            $returnMoney += $getReturnMoney['returnMoney'] * $v->bet_money;

        }
        $returnMoney = sprintf("%.2f", substr(sprintf("%.3f", $returnMoney), 0, -1));
        // 判断盈亏  1 赢  2 输  3 平
        $game_status = $returnMoney > $simplexData->money ? 1 : ($returnMoney == $simplexData->money ? 3 : 2);
        // 修改投注表状态及盈亏
        DB:: table('money_buy_simplex')
            ->where(['order_id' => $order_id])
            ->update(['settle_status' => 2, 'game_status' => $game_status, 'gain_money' => $returnMoney, 'settlementTime' => date('Y-m-d H:i:s')]);
        $this->WriteOrAddSettlement($this->game_code, $this->match_id, $this->orderType, $order_id, $this->BuyDatasMainModel->account_identity, $returnMoney);
        $this->insertData(
            $order_id,
            $returnMoney,
            $simplexData->account_identity,
            1,
            $simplexData->game_code,
            $simplexData->info_identity,
            $simplexData->money,
            $this->match_id
        );

    }

    /**
     * 结算数据填入
     * @param mixed $order_id 注单ID
     * @param mixed $returnMoney 返现金额
     * @param mixed $account_identity 用户ID
     * @param mixed $type 1单式 2串式
     * @param mixed $game_name 游戏名（zq，lq）
     * @param mixed $buy_identity 游戏投注id
     * @param mixed $money 投注金额
     * @param mixed $match_id 赛场ID
     */
    public function insertData($order_id, $returnMoney, $account_identity, $type, $game_name, $buy_identity, $money, $match_id = 0)
    {
        // 查询用户当前剩余金额
        $accountInfo = DB:: table('account_detailed')
            ->join('account', 'account_detailed.account_identity', 'account.identity')
            ->select(['available_cash', 'cash', 'account', 'account_identity'])
            ->where(['account_identity' => $account_identity])
            ->first();
        // 计算用户回账后余额
        $available_cash = $accountInfo->available_cash + $returnMoney;
        $cash = $accountInfo->cash + $returnMoney;
        // 添加流水记录
        $info_identity = UUID();
        $money_time = date('Y-m-d H:i:s', time());
        $trade_desc = $type == 1 ? '单式投注订单回款' : '串式投注订单回款';
        $reason = $type == 1 ? '单式投注订单回款' : '串式投注订单回款';
        DB:: table('money_details')->insert([
            'info_identity' => $info_identity,
            'trade_id' => $order_id,
            'account_name' => $accountInfo->account,
            'account_identity' => $accountInfo->account_identity,
            'money' => $returnMoney,
            'money_time' => $money_time,
            'money_type' => 1,
            'money_cash' => $available_cash,
            'trade_type' => 4,
            'trade_desc' => $trade_desc,
            'reason' => $reason,
            'sysetem_user' => '系统',
            'status' => '1',
        ]);

        // 修改用余额
        DB:: table('account_detailed')
            ->where(['account_identity' => $account_identity])
            ->update(['available_cash' => $available_cash, 'cash' => $cash]);
        // 新增用户中奖信息
        $content = $type == 1 ? '您的单式投注订单' . $order_id . '于' . $money_time . '成功回款' . $returnMoney . '该次投注流程结束，如有疑问请联系客服'
            : '您的串式投注订单' . $order_id . '于' . $money_time . '成功回款' . $returnMoney . '该次投注流程结束，如有疑问请联系客服';
        DB:: table('account_news')->insert([
            'identity' => $info_identity,
            'account_identity' => $account_identity,
            'title' => '投注订单回款通知',
            'content' => $content,
            'details' => $content,
            'write_time' => $money_time,
            'read_status' => -1,
            'type' => 1,
        ]);
        // 新增中奖记录表
        $old = DB:: table('money_prize')->where(['buy_identity' => $buy_identity])->orWhere(['order_id' => $order_id])->first();
        if (count($old)) {
            DB:: table('money_prize')->where(['buy_identity' => $buy_identity])->orWhere(['order_id' => $order_id])->update(['money' => $money, 'prize_money' => $returnMoney, 'get_money' => $returnMoney - $money]);
        } else {
            DB:: table('money_prize')->insert([
                'info_identity' => $info_identity,
                'order_id' => $order_id,
                'account_identity' => $account_identity,
                'account_name' => $accountInfo->account,
                'game_name' => $game_name,
                'buy_identity' => $buy_identity,
                'money' => $money,
                'money_time' => $money_time,
                'status' => 1,
                'prize_money' => $returnMoney,
                'get_money' => $returnMoney - $money,
            ]);
        }

    }


    //单个串式订单的处理
    public function ChuanOrder($order_id)
    {

        $batch_id = $this->BuyDatasMainModel->batch_id;
        $matchModels = DB::table('money_buy_match')->where(['batch_id' => $batch_id, 'bet_type' => 2])->get();
        if ($matchModels->count() <= 0) {
            throw  new  \Exception('match 数据异常');
        }


        $newTime = date('Y-m-d H:i:s');
        if ($this->BuyDatasMainModel->status == 1) {
            $in_array = [];
            foreach ($matchModels as $val) {
                if (!in_array($val->result, [-1, 1, 2, 3, 4])) {
                    throw  new  \Exception('match 比赛结果异常或还没有输赢结果->' . $val->id);
                }

                if ($val->result == -1) {
                    DB::table('money_buy_str')->where('batch_id', $batch_id)->update(['wait_match_num' => 0, 'prize_note' => 0, 'game_status' => 3, 'settle_status' => 2, 'gain_money' => 0, 'settlementTime' => date('Y-m-d H:i:s')]);
                    return true;
                }

                $in_array[] = ['odds' => $val->odds, 'winOrLose' => $val->result];
            }

            $chuanNum = intval(substr($this->BuyDatasMainModel->str_type, 0, 1));
            $lasPeilv = $this->stringComputing([$in_array, $chuanNum]);
            $money = floatPointDigit($this->BuyDatasMainModel->money * $lasPeilv);

        } else {
            $money = $this->BuyDatasMainModel->money;
        }

        $ret = DB::update('update money_buy_str  set settle_status=2 , game_status=1 , "settlementTime"=? , gain_money=?  where order_id = ?', [$newTime, $money, $order_id]);
        if (!($ret || $ret === 0)) {
            throw  new \Exception('更新数据出错3!');
        }

        $this->WriteOrAddSettlement($this->game_code, $this->match_id, $this->orderType, $order_id, $this->BuyDatasMainModel->account_identity, $money);
        $this->insertData($order_id, $money, $this->BuyDatasMainModel->account_identity, 2, $val->game_code, $this->BuyDatasMainModel->info_identity, $this->BuyDatasMainModel->money, $this->match_id);

        return true;

    }

    //校验是否同一场比赛的订单处理
    private function Match_check($idsArray, $betType)
    {
        array_walk($idsArray, function (&$item, $key) {
            $item = "'" . $item . "'";
        });

        $idString = implode(",", $idsArray);

        $table = "money_buy_simplex";
        $sql = "select game_code,match_id   from  $table  where  status=1 and  order_id in ($idString)  group by  game_code,match_id ";

        $ret = DB::select($sql);

        return $ret;

    }

    //取消某个赛事订单的结算数据
    public function UndoSettlement($game_code, $match_id, $order_ids, $bettype)
    {
        if ($this->set_type == 1) {
            return;
        }
        $modelSMD = new SettlementMiddleDetailModel();
        $hisData = $modelSMD->getSettledatas($game_code, $match_id, $bettype);

        if (count($hisData) <= 0) {
            return true;
        }


        $this->hissettlementDetail = $hisData;
        $orderList = [];


        if ($bettype == 1) {
            $order_list = DB::table('money_buy_simplex')->where(['game_code' => $game_code, 'match_id' => $match_id, 'status' => 1])->whereIn('order_id', $order_ids)->get();

            foreach ($order_list as $val) {
                $orderList[$val->order_id] = $val;
            }

        } else {
            $order_list = DB::table('money_buy_str')->where(['status' => 1])->whereIn('order_id', $order_ids)->get();

            foreach ($order_list as $val) {
                $orderList[$val->order_id] = $val;
            }
        }


        foreach ($hisData as $oid => $val) {
            if (!isset($orderList[$val->order_id])) {
                throw  new  \Exception("订单数据缺失异常!($game_code,$match_id,$oid)");
            }
            $money = $val->money * (-1);
            if (intval($money) * 100 == 0) {
                continue;
            }
            $this->insertData($oid, $money, $val->account_identity, $bettype, $game_code, $orderList[$oid]->info_identity, $money, $this->match_id);
        }
        $table = $bettype == 1 ? 'money_buy_simplex' : 'money_buy_str';
        if ($bettype == 1) {
            $ret1 = DB::table($table)->where(['game_code' => $game_code, 'match_id' => $match_id, 'status' => 1])->whereIn('order_id', $order_ids)->update(['settle_status' => 1, 'gain_money' => 0, 'game_status' => 0]);
        } else {
            $ret1 = DB::table($table)->where(['status' => 1])->whereIn('order_id', $order_ids)->update(['settle_status' => 1, 'gain_money' => 0]);
        }

        $ret2 = DB::table('settlement_middle_detail')->where(['game_code' => $game_code, 'match_id' => $match_id, 'bet_type' => $bettype])->whereIn('order_id', $order_ids)->update(['money' => 0]);

        if ($ret1 && $ret2) {
            return true;
        } else {
            throw new \Exception("取消结算更新数据状态出错操作中止($ret1 $ret2)!");
        }

    }

    private function WriteOrAddSettlement($game_code, $match_id, $bet_type, $order_id, $account_ident, $money)
    {

        if (isset($this->hissettlementDetail[$order_id])) {
            $ret = DB::table('settlement_middle_detail')
                ->where(['game_code' => $game_code, 'match_id' => $match_id, 'bet_type' => $bet_type, 'order_id' => $order_id])
                ->update(['money' => $money]);
        } else {
            $ret = DB::table('settlement_middle_detail')
                ->insertGetId([
                    'game_code' => $game_code,
                    'match_id' => $match_id,
                    'account_identity' => $account_ident,
                    'bet_type' => $bet_type,
                    'order_id' => $order_id,
                    'money' => $money
                ]);
        }
        if (!$ret) {
            throw  new  \Exception("更新数据异常(bt:$bet_type  od:$order_id  ret:$ret)");
        }
        return true;
    }

    private function cgStatus($game_code, $match_id)
    {
        DB::table("st_" . $game_code . "_result")->where(['match_id' => $match_id])->update(['status' => 3]);
        DB::table("st_" . $game_code . "_competition")->where(['id' => $match_id])->update(['status' => 3]);
    }

}