<?php
namespace Base\Service;

use Base\Business\ShiftPlayer;
use Base\Model\PromoteModel;
use Base\Model\UserPlayInfoModel;
use Base\Model\UserPlayModel;
use Base\Model\UserModel;
use Base\Tool\IdCard;
use Base\Tool\Registry;
use Base\Tool\Redis;
use Think\Model;
use Base\Repository\SpendRepository;

class PromoteService {

    private $model;

    public static $levels = [
        1 => '会长',
        2 => '部门长',
        3 => '组长',
        4 => '推广员',
    ];

    public function __construct()
    {
        $this->model = new PromoteModel();
    }

    public function froze($id)
    {
        $data = [
            'status' => 2
        ];
        return $this->model->where("id=".$id)->save($data);
    }

    public function unfreeze($id)
    {
        $data = [
            'status' => 1
        ];
        return $this->model->where("id=".$id)->save($data);
    }

    public function resetPassword($id, $password = null)
    {
        if (!$password) {
            $password = $this->getRandomPassword(10, false);
        }
        $passwordSecret = $this->password($password, UC_AUTH_KEY);
        if ($this->model->where("id=".$id)->save(['password' => $passwordSecret])) {
            return $password;
        }
    }

    public function password($str, $key = 'ThinkUCenter')
    {
        return '' === $str ? '' : md5(sha1($str) . $key);
    }

    private function getRandomPassword($length, $special = true){
        $chars = array(
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
            'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
            'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
            'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2',
            '3', '4', '5', '6', '7', '8', '9'
        );
    
        if($special){
            $chars = array_merge($chars, array(
                '!', '@', '#', '$', '?', '|', '{', '/', ':', ';',
                '%', '^', '&', '*', '(', ')', '-', '_', '[', ']',
                '}', '<', '>', '~', '+', '=', ',', '.'
            ));
        }
    
        $charsLen = count($chars) - 1;
        shuffle($chars);
        
        $password = '';
        for($i=0; $i<$length; $i++){
            $password .= $chars[mt_rand(0, $charsLen)];
        }
        return $password;
    }

    public function addShiftTask($params)
    {
        $fromPromoteId = isset($params['from_promote_id']) ? $params['from_promote_id'] : 0;
        $toPromoteId = isset($params['to_promote_id']) ? $params['to_promote_id'] : 0;
        $orderTime = isset($params['order_time']) ? $params['order_time'] : '';
        $balanceCoinMode = isset($params['balance_coin_mode']) ? $params['balance_coin_mode'] : 0;
        $type = isset($params['type']) ? $params['type'] : 0;
        $shiftIds = isset($params['shift_ids']) && $params['shift_ids'] ? $params['shift_ids'] : [];
        $creatorId = isset($params['creator_id']) ? $params['creator_id'] : 0;
        $creatorType = isset($params['creator_type']) ? $params['creator_type'] : 0;
        $remark = isset($params['remark']) ? $params['remark'] : '';

        if ($fromPromoteId == $toPromoteId) {
            return [
                'status' => false, 
                'msg'=>'相同推广帐号不可迁移'
            ];
        }
        if ($orderTime == 0) {
            return [
                'status' => false, 
                'msg'=>'订单日期不能为空'
            ];
        }

        /* if ($type == 1 && $balanceCoinMode == 0) {
            return [
                'status' => false, 
                'msg'=>'请选择平台币管理方式'
            ];
        } */

        if (count($shiftIds) > 15) {
            return [
                'status' => false, 
                'msg'=>'部分迁移时,迁移人数不能超过15'
            ];
        }

        /* $shiftTask = M('shift_task', 'sys_')->field(['id'])->where(['type' => $type, 'status' => 0, 'from_promote_id' => $fromPromoteId])->find();
        if ($shiftTask) {
            return [
                'status' => false, 
                'msg' => '含有类似未执行迁移任务,请稍后再试'
            ];
        } */

        $data = [
            'from_promote_id' => $fromPromoteId,
            'to_promote_id' => $toPromoteId,
            'order_time' => strtotime($orderTime),
            'balance_coin_mode' => $balanceCoinMode,
            'create_time' => time(),
            'creator_id' => $creatorId,
            'creator_type' => $creatorType,
            'status' => 0,
            'type' => $type,
            'remark' => $remark,
            'shift_ids' => json_encode($shiftIds)
        ];

        if (M('shift_task', 'sys_')->add($data)) {
            if ($type == 2) {
                $data['id'] = M()->getLastInsID();
                $this->addMendsByTask($data);
            }
            return [
                'status' => true, 
                'msg'=>'迁移任务创建成功'
            ];
        } else {
            return [
                'status' => false, 
                'msg'=>'迁移失败'
            ];
        }
    }

    public function addMendsByTask($task)
    {
        $userIds = json_decode($task['shift_ids'], true);
        $users = M('user', 'tab_')->field(['id', 'account', 'nickname'])->where(['id' => ['in', $userIds]])->select();
        $users = index_by_column('id', $users);
        $toPromote = M('promote','tab_')->field(['id', 'account'])->where(['id' => $task['to_promote_id']])->find();
        $fromPromote = M('promote','tab_')->field(['id', 'account'])->where(['id' => $task['from_promote_id']])->find();

        $creator = null;
        $opAccount = '';
        if ($task['creator_type'] == 1) {
            $creator = M('promote', 'tab_')->where(['id' => $task['creator_id']])->find();
            $opAccount = $creator ? $creator['account'] : '';
        } else {
            $creator = M('ucenter_member', 'sys_')->where(['id' => $task['creator_id']])->find();
            $opAccount = $creator ? $creator['username'] : '';
        }

        $mends = [];
        foreach ($userIds as $userId) {
            $user = $users[$userId];
            $mends[] = [
                'task_id' => $task['id'],
                'user_id' => $userId,
                'user_account' => $user['account'],
                'user_nickname' => $user['nickname'],
                'promote_id' => $fromPromote ? $fromPromote['id'] : 0,
                'promote_account' => $fromPromote ? $fromPromote['account'] : C('OFFICIEL_CHANNEL'),
                'promote_id_to' => $toPromote ? $toPromote['id'] : 0,
                'promote_account_to' => $toPromote ? $toPromote['account'] : C('OFFICIEL_CHANNEL'),
                'remark' => $task['remark'] == '' ? ($task['creator_type'] == 0 ? '后台补链' : '玩家迁移') : $task['remark'],
                'order_time' => $task['order_time'],
                'create_time' => time(),
                'pay_amount' => 0,
                'op_id' => $task['creator_id'],
                'op_account' => $opAccount,
                'op_type' => $task['creator_type'],
                'bind_type' => 1,
            ];
        }
        M('mend', 'tab_')->addAll($mends);
    }

    public function shiftPromote($task)
    {
        $model = new Model();
        $model->startTrans();
        
        $shiftIds = $task['shift_ids'] ? (json_decode($task['shift_ids'], true) ?? []) : [];

        $toPromote = M('promote', 'tab_')->where(['id' => $task['to_promote_id']])->find();
        $fromPromote = M('promote', 'tab_')->where(['id' =>  $task['from_promote_id']])->find();

        $childrenMap  = ['parent_id' =>  $fromPromote['id']];
        if (count($shiftIds) > 0) {
            $childrenMap['id'] = ['in', $shiftIds];
        }
        $count = M('promote', 'tab_')->where($childrenMap)->count();
        if ($count == 0) {
            return ['status' => true, 'msg' => '推广帐号迁移成功,无子账号需要迁移'];
        }

        $topPromote = $this->getTopPromote($fromPromote);
        // $status = $this->shiftRemoveCoin($fromPromote, $task);

        /* if (!$status) {
            $model->rollback();
            return ['status' => false, 'msg' => '系统异常, 处理推广员平台币失败'];
        } */

        $firstMap = ['parent_id' => $fromPromote['id']];
        $secondMap = ['chain' => ['like', $fromPromote['chain'] . $fromPromote['id'] . '/%']];
        if (count($shiftIds) > 0) {
            $firstMap['id'] = ['in', $shiftIds];
            $secondMap['parent_id'] = ['in', $shiftIds];
        }

        try {
            M('promote', 'tab_')->where($firstMap)->save([
                'parent_id' => $toPromote['id'], 
                'parent_name' => $toPromote['account'],
                'chain' => $toPromote['chain'] . $toPromote['id'] . '/',
                'level' . $toPromote['level'] . '_id' => $toPromote['id']
            ]);

            M('promote', 'tab_')->where($secondMap)->save([
                'chain' => ['exp', 'REPLACE(chain, "/' . $fromPromote['id'] . '/","/' . $toPromote['id'] . '/")'],
                'level' . $toPromote['level'] . '_id' => $toPromote['id']
            ]);

            $model->commit();
            return ['status' => true, 'msg' => '推广帐号迁移成功'];
        } catch (\Exception $e) {
            $model->rollback();
            return ['status' => true, 'msg' => '推广帐号迁移失败: ' . $e->getMessage()];
        }
    }

    public function shiftRemoveCoin($promote, $task)
    {
        $shiftIds = json_decode($task['shift_ids'], true) ?? [];
        $topPromote = $this->getTopPromote($promote);
        $coinRecordService = new PromoteCoinRecordService();
        $promoteCoinService = new PromoteCoinService();
        $topBalanceCoin = $this->getBalanceCoin($topPromote['id'], 0);
        $topBalancePlus = 0;

        $map = ['chain' => $promote['chain'] . $promote['id'] . '/%'];
        if (count($shiftIds) > 0) {
            $map['id'] = ['in', $shiftIds];
        }
        $subPromotes = M('promote', 'tab_')->field(['id', 'balance_coin', 'level'])->where($map)->select();
        $subPromotes = index_by_column('id', $subPromotes);
        $ids = array_keys($subPromotes);
        // $ids[] = $promote['id'];

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

        $promoteCoins = [];
        $balances = M('PromoteBalanceCoin', 'tab_')->where(['promote_id' => ['in', $ids]])->select();

        if (count($balances) == 0) {
            return true;
        }
        $records = [];
        foreach ($balances as $balance) {
            if ($balance['num'] == 0) {
                continue;
            }
            $records[] = $coinRecordService->createRecord([
                'type' => 2,
                'sub_type' => 7,
                'ref_id' => 0,
                'promote_id' => $balance['promote_id'],
                'target_id' => $topPromote['id'],
                'target_level' => $topPromote['level'],
                'target_type' => 1,
                'game_id' => $balance['game_id'],
                'coin' => $balance['num'],
                'balance_coin' => 0,
                'description' => $balance['game_id'] > 0 ? '绑定币回收' : '迁移扣除',
            ]);

            if ($task['balance_coin_mode'] == 1 && $balance['game_id'] == 0) {
                $topBalanceCoin += $balance['num'];
                $topBalancePlus += $balance['num'];
                $records[] = $coinRecordService->createRecord([
                    'type' => 1,
                    'sub_type' => 6,
                    'ref_id' => 0,
                    'promote_id' => $topPromote['id'],
                    'target_id' => $balance['promote_id'],
                    'target_type' => 1,
                    'target_level' => $subPromotes[$balance['promote_id']]['level'],
                    'game_id' => $balance['game_id'],
                    'coin' => $balance['num'],
                    'balance_coin' => $topBalanceCoin,
                    'description' => '迁移回收',
                ]);
            }
        }

        M('PromoteBalanceCoin', 'tab_')->where(['promote_id' => ['in', $ids]])->save(['num' => 0]);
        M('Promote', 'tab_')->where(['id' => ['in', $ids]])->save(['balance_coin' => 0]);

        if (count($records) > 0) {
            M('PromoteCoinRecord', 'tab_')->addAll($records);
        }

        if ($topBalancePlus > 0) {
            return $this->incCoin($topPromote['id'], $topBalancePlus, 0);
        }
        return true;
    }

    public function shiftPlayer($task)
    {
        try {
            $shiftPlayer = new ShiftPlayer($task);
            $shiftPlayer->handle();
            return ['status' => true, 'msg' => '玩家迁移成功'];
        } catch (\Exception $e) {
            return ['status' => false, 'msg' => $e->getMessage()];
        }
    }

    public function afterShift($task, $result)
    {
        $data = [];
        if ($result['status']) {
            $data = ['status' => 1, 'result' => $result['msg'], 'handle_time' => time()];
        } else {
            $data = ['status' => 2, 'result' => $result['msg'], 'handle_time' => time()];
        }
        M('shift_task', 'sys_')->where('id=' . $task['id'])->save($data);
    }

    /**
     * 玩家补充迁移(处理在迁移过程中玩家正在充值的订单无法迁移的问题)
     */
    public function replenishShift($task)
    {
        try {
            $shiftPlayer = new ShiftPlayer($task);
            $shiftPlayer->handleReplenish();
            M('shift_task', 'sys_')->where('id=' . $task['id'])->save(['is_replenished' => 1]);
            return ['status' => true, 'msg' => '玩家补充迁移完成'];
        } catch (\Exception $e) {
            return ['status' => false, 'msg' => $e->getMessage()];
        }
    }

    public function shift($task)
    {
        $result = null;
        if ($task['type'] == 1) {
            $result = $this->shiftPromote($task);
        } elseif ($task['type'] == 2) {
            $result = $this->shiftPlayer($task);
        } else {
            $result = ['status' => false, 'msg' => '类型错误'];
        }
        $this->afterShift($task, $result);
        return $result;
    }

    public function cancelShift($params)
    {
        $promoteId = $params['promote_id'];
        $type = $params['type'];

        $status = M('ShiftTask')->where(['from_promote_id' => $promoteId, 'type' => $type, 'status' => 0])->save(['status' => 2, 'handle_time' => time()]);

        if ($status) {
            return ['status' => true, 'msg' => '取消成功'];
        } else {
            return ['status' => false, 'msg' => '取消失败'];
        }
    }

    public function shiftUserCoin($params)
    {
        $model = new Model();
        $model->startTrans();
        $promoteId = $params['from_promote_id'];
        $userId = $params['user_id'];
        $remark = $params['remark'];
        $num = $params['num'];
        $gameId = $params['game_id'];
        $isUseBind = $params['is_use_bind'];

        $promote = M('promote', 'tab_')->where(['id' => $promoteId])->find();
        $user = M('user', 'tab_')->where(['id' => $userId])->find();
        $userPlay = M('user_play', 'tab_')->where(['user_id' => $userId])->find();
        $before_value = M('user_play', 'tab_')->where(['user_id' => $userId])->sum('bind_balance');
        $game = M('game', 'tab_')->where(['id' => $gameId])->find();
        $fromBalanceCoin = 0;
        if ($isUseBind) {
            $fromBalanceCoin = $this->getBalanceCoin($promoteId, $gameId);
        } else {
            $fromBalanceCoin = $this->getBalanceCoin($promoteId, 0);
        }
        if ($fromBalanceCoin < $num) {
            return [
                'msg' => '平台币不足',
                'status' => false,
            ];
        }

        $agentParams = [];
        $agentParams['game_name'] = $game['game_name'];
        $agentParams['game_appid'] = $game['game_appid'];
        $agentParams['game_id'] = $gameId;
        $agentParams['pay_order_number'] = '';
        $agentParams['order_number'] = '';
        $agentParams['promote_id'] = $promoteId;
        $agentParams['promote_account'] = $promote['account'];
        $agentParams['user_id'] = $userId;
        $agentParams['user_account'] = $user['account'];
        $agentParams['user_nickname'] = $user['nickname'];
        $agentParams['amount'] = $num;
        $agentParams['real_amount'] = $num;
        $agentParams['pay_status'] = 1;
        $agentParams['pay_type'] = 0;
        $agentParams['create_time'] = time();
        $agentParams['zhekou'] = 10;
        $agentParams['pay_way'] = 4;

        $fromParams = [];
        $fromParams['game_id'] = $gameId;
        $fromParams['num'] = $num;
        $fromParams['promote_id'] = $promoteId;
        $fromParams['target_id'] = $userId;
        $fromParams['target_type'] = 2;
        $fromParams['target_level'] = 0;
        $fromParams['remark'] = $remark;
        $fromParams['description'] = $isUseBind ? '绑定币转账' : '通用币转账';

        $agentService = new AgentService();
        $transferLogService = new PromoteCoinTransferLogService();
        $agentRefId = $agentService->addRecord($agentParams);
        $formRefId = $transferLogService->addRecord($fromParams);

        if ($formRefId == 0 || $agentRefId == 0) {
            $model->rollback();
            return [
                'msg' => '系统异常',
                'status' => false,
            ];
        }

        $promoteCoinRecordService = new PromoteCoinRecordService();
        $fromRecord = [
            'type' => 2,
            'sub_type' => 4,
            'promote_id' => $promoteId,
            'ref_id' => $formRefId,
            'target_id' => $userId,
            'target_type' => 2,
            'game_id' => $gameId,
            'coin' => $num,
            'balance_coin' => $fromBalanceCoin - $num,
            'description' => $isUseBind ? '绑定币转账' : '通用币转账',
            'remark' => $remark,
        ];
        
        $promoteCoinRecordService->addRecord($fromRecord);
        
        $incStatus = M('user_play', 'tab_')->where(['game_id' => $gameId, 'user_id' => $userId])->setInc('bind_balance', $num);
        $decStatus = $this->decCoin($promoteId, $num, $isUseBind ? $gameId : 0);
        if (!$incStatus || !$decStatus) {
            $model->rollback();
            return [
                'msg' => '系统异常',
                'status' => false,
            ];
        }
        $model->commit();

        return [
            'msg' => '转帐成功',
            'status' => true,
        ];
    }

    public function shiftPromoteCoin($params)
    {
        $toPromoteId = $params['promote_id'];
        $fromPromoteId = $params['from_promote_id'];
        $remark = $params['remark'];
        $num = $params['num'];
        $gameId = $params['game_id'] ?? 0;
        $isUseBind = $params['is_use_bind'];

        $toPromote = M('promote', 'tab_')->where(['id' => $toPromoteId])->find();
        $fromPromote = M('promote', 'tab_')->where(['id' => $fromPromoteId])->find();
        $toBalanceCoin = $this->getBalanceCoin($toPromoteId, $gameId);
        $fromBalanceCoin = 0;

        if ($isUseBind && $gameId == 0) {
            return [
                'msg' => '请选择游戏',
                'status' => false,
            ];
        }

        if ($isUseBind) {
            $fromBalanceCoin = $this->getBalanceCoin($fromPromoteId, $gameId);
        } else {
            $fromBalanceCoin = $this->getBalanceCoin($fromPromoteId, 0);
        }
        if ($isUseBind && $gameId) {
            return [
                'msg' => '平台币不足',
                'status' => false,
            ];
        }
        
        if ($fromBalanceCoin < $num) {
            return [
                'msg' => '平台币不足',
                'status' => false,
            ];
        }

        $model = new Model();
        $model->startTrans();
        $params = [];
        $params['game_id'] = $gameId;
        $params['promote_id'] = $fromPromoteId;
        $params['num'] = $num;
        $params['target_type'] = 1;
        $params['target_id'] = $toPromoteId;
        $params['target_level'] = $toPromote['level'];
        $params['remark'] = $remark;
        $params['description'] = $isUseBind ? '绑定币转账' : '通用币转账';

        $transferLogService = new PromoteCoinTransferLogService();
        $refId = $transferLogService->addRecord($params);

        if ($refId == 0) {
            $model->rollback();
            return [
                'msg' => '系统异常',
                'status' => false,
            ];
        }

        $promoteCoinRecordService = new PromoteCoinRecordService();
        $fromRecord = [
            'type' => 2,
            'sub_type' => 3,
            'ref_id' => $refId,
            'promote_id' => $fromPromoteId,
            'target_id' => $toPromoteId,
            'target_type' => 1,
            'target_level' => $toPromote['level'],
            'game_id' => $gameId,
            'coin' => $num,
            'balance_coin' => $fromBalanceCoin - $num,
            'description' => '平台币转账',
            'remark' => $remark,
        ];
        $promoteCoinRecordService->addRecord($fromRecord);

        $toRecord = [
            'type' => 1,
            'sub_type' => 3,
            'ref_id' => $refId,
            'promote_id' => $toPromoteId,
            'target_id' => $fromPromote['id'],
            'target_type' => 1,
            'target_level' => $fromPromote['level'],
            'game_id' => $gameId,
            'coin' => $num,
            'balance_coin' => $toBalanceCoin + $num,
            'description' => '平台币转账',
            'remark' => $remark,
        ];
        $promoteCoinRecordService->addRecord($toRecord);

        $incStatus = $this->incCoin($toPromoteId, $num, $gameId);
        $decStatus = $this->decCoin($fromPromoteId, $num, $isUseBind ? $gameId : 0);
        if (!$incStatus || !$decStatus) {
            $model->rollback();
            return [
                'msg' => '系统异常',
                'status' => false,
            ];
        }

        $model->commit();

        return [
            'msg' => '转帐成功',
            'status' => true,
        ];
    }

    /**
     * 添加平台币(不主动产生流水)
     */
    public function incCoin($promoteId, $num, $gameId = 0)
    {
        $status = M('Promote', 'tab_')->where(['id' => $promoteId])->setInc('balance_coin', $num);
        if (!$status) {
            return false;
        }
        $promoteBalance = M('PromoteBalanceCoin', 'tab_')->where(['promote_id' => $promoteId, 'game_id' => $gameId])->find();
        if (empty($promoteBalance)) {
            $record = [
                'promote_id' => $promoteId,
                'game_id' => $gameId,
                'num' => $num,
                'status' => 1
            ];
            return M('PromoteBalanceCoin', 'tab_')->add($record);
        } else {
            return M('PromoteBalanceCoin', 'tab_')->where(['promote_id' => $promoteId, 'game_id' => $gameId])->setInc('num', $num);
        }
    }

    /**
     * 减少平台币(不主动产生流水)
     */
    public function decCoin($promoteId, $num, $gameId = 0)
    {
        $status = M('Promote', 'tab_')->where(['id' => $promoteId])->setDec('balance_coin', $num);
        if (!$status) {
            return false;
        }
        $promoteBalance = M('PromoteBalanceCoin', 'tab_')->where(['promote_id' => $promoteId, 'game_id' => $gameId])->find();
        if (empty($promoteBalance)) {
            return false;
        } else {
            return M('PromoteBalanceCoin', 'tab_')->where(['promote_id' => $promoteId, 'game_id' => $gameId])->setDec('num', $num);
        }
    }

    /**
     * 清除绑定平台币(不主动产生流水)
     */
    public function clearBindCoin($promoteId)
    {
        $num = M('PromoteBalanceCoin', 'tab_')->where(['promote_id' => $promoteId, 'game_id' => ['gt', 0]])->sum('num');
        $num = intval($num);
        if ($num == 0) {
            return true;
        }

        $status = M('Promote', 'tab_')->where(['id' => $promoteId])->setDec('balance_coin', $num);
        if (!$status) {
            return false;
        }
        return M('PromoteBalanceCoin', 'tab_')->where(['promote_id' => $promoteId, 'game_id' => ['gt', 0]])->save(['num' => 0]);
    }

    /**
     * 管理员给推广员扣回平台币
     */
    public function adminDecCoin($promoteId, $num, $adminId, $gameId = 0)
    {

        $balanceCoin = $this->getBalanceCoin($promoteId, $gameId);
        $promote = M('promote', 'tab_')->where(['id' => $promoteId])->find();

        $model = new Model();
        $model->startTrans();
        
        $log = [];
        $log['game_id'] = $gameId;
        $log['banlan_type'] = $gameId > 0 ? 2 : 1;
        $log['num'] = $num;
        $log['promote_id'] = $promote['id'];
        $log['source_id'] = 0;
        $log['type'] = 2;
        $log['op_id'] = $adminId;

        $promoteCoinService = new PromoteCoinService();
        $refId = $promoteCoinService->addRecord($log);

        $promoteCoinRecordService = new PromoteCoinRecordService();
        $record = [
            'type' => 2,
            'sub_type' => 5,
            'ref_id' => $refId,
            'promote_id' => $promote['id'],
            'target_id' => $adminId,
            'target_type' => 3,
            'target_level' => $promote['level'],
            'game_id' => $gameId,
            'coin' => $num,
            'balance_coin' => $balanceCoin - $num,
            'description' => '后台回收平台币',
            'remark' => '',
        ];
        $promoteCoinRecordService->addRecord($record);

        $status = $this->decCoin($promote['id'], $num, $gameId);
        if ($refId && $status) {
            $model->commit();
            return true;
        }
        $model->rollback();
        return false;
    }

    /**
     * 管理员给推广员添加平台币
     */
    public function adminIncCoin($promoteId, $num, $adminId, $gameId = 0)
    {
        $balanceCoin = $this->getBalanceCoin($promoteId, $gameId);
        $promote = M('promote', 'tab_')->where(['id' => $promoteId])->find();

        $model = new Model();
        $model->startTrans();

        $log = [];
        $log['game_id'] = $gameId;
        $log['banlan_type'] = $gameId > 0 ? 2 : 1;
        $log['num'] = $num;
        $log['promote_id'] = $promote['id'];
        $log['source_id'] = 0;
        $log['type'] = 1;
        $log['op_id'] = $adminId;

        $promoteCoinService = new PromoteCoinService();
        $refId = $promoteCoinService->addRecord($log);
        $status = $this->incCoin($promote['id'], $num, $gameId);
        
        $record = [
            'type' => 1,
            'sub_type' => 8,
            'ref_id' => $refId,
            'promote_id' => $promote['id'],
            'target_id' => $adminId,
            'target_type' => 3,
            'target_level' => $promote['level'],
            'coin' => $num,
            'game_id' => $gameId,
            'balance_coin' => $balanceCoin + $num,
            'description' => '后台发放平台币',
            'remark' => '',
        ];

        $promoteCoinRecordService = new PromoteCoinRecordService();
        $promoteCoinRecordService->addRecord($record);

        if ($refId && $status) {
            $model->commit();
            return true;
        }
        $model->rollback();
        return false;
    }
    
    public function getBalanceCoin($promoteId, $gameId = 0)
    {
        $promoteBalance = M('PromoteBalanceCoin', 'tab_')->where(['promote_id' => $promoteId, 'game_id' => $gameId])->find();
        $balanceCoin = 0;
        if (!empty($promoteBalance)) {
            $balanceCoin = $promoteBalance['num'];
        }
        return $balanceCoin;
    }

    public function getLevelByChain($chain)
    {
        $chain = trim($chain, '/');
        return $chain == '' ? 1 : count(explode('/', $chain));
    }

    public function getIdsByChain($chain)
    {
        $chain = trim($chain, '/');
        return $chain == '' ? [] : explode('/', $chain);
    }

    public function isSub($promote, $parent)
    {
        $chainList = $this->getIdsByChain($promote['chain']);
        if (in_array($parent['id'], $chainList)) {
            return true;
        }
        return false;
    }

    public function isSubOrSelf($promote, $parent)
    {
        if ($promote['id'] == $parent['id']) {
            return true;
        } elseif ($this->isSub($promote, $parent)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取最上级的推广员
     */
    public function getTopPromote($promote)
    {
        /* if ($promote['level'] == 1) {
            return $promote;
        } */
        $chain = trim($promote['chain'], '/');
        if ($chain == '') {
            return $promote;
        } else {
            $topPromoteId = explode('/', $chain)[0];
            return M('promote', 'tab_')->where(['id' => $topPromoteId])->find();
        }
    }

    /**
     * 获取所有下级推广员
     */
    public function getAllChildren($promote, $level = 0, $fields = '*')
    {
        $conditions = ['chain' => ['like', $promote['chain'] . $promote['id'] . '/%']];
        if ($level != 0) {
            $conditions['level'] = $level;
        }
        return M('promote', 'tab_')->field($fields)->where($conditions)->select();
    }

    public function subInSql($promote, $withSelf = true)
    {
        $conditions = [
            'chain' => ['like', $promote['chain'] . $promote['id'] . '/%']
        ];
        if ($withSelf != 0) {
            $conditions['_logic'] = 'or';
            $conditions['id'] = $promote['id'];
        }
        return M('promote', 'tab_')->field(['id'])->where($conditions)->select(false);
    }

    public function subInCompanySql($companyId, $withSelf = true)
    {
        return M('promote', 'tab_')->field(['id'])->where(['company_id' => $companyId])->select(false);
    }

    public function getLevelName($level)
    {
        return self::$levels[$level] ?? '未知';
    }

    public function checkAddPromote($params)
    {
        $account = isset($params['account']) ? trim($params['account']) : '';
        $password = $params['password'] ?? '';
        $repassword = $params['repassword'] ?? '';
        $mobile = $params['mobile_phone'] ?? '';
        $idcard = $params['idcard'] ?? '';
        $realName = $params['real_name'] ?? '';

        if ($account == '') {
            return [
                'status' => false,
                'message' => '请输入推广员账号',
            ];
        }
        if (strlen($account) > 15 || strlen($account) < 6) {
            return [
                'status' => false,
                'message' => '账号长度为6-15个字符',
            ];
        }
        if (!preg_match("/^[a-zA-Z0-9_\.]+$/", $account)) {
            return [
                'status' => false,
                'message' => '账号只能为数字,字母和下划线',
            ];
        }
        if ($mobile != '') {
            if (!preg_match("/^1[3456789]{1}\d{9}$/", $mobile)) {
                return [
                    'status' => false,
                    'message' => '手机号格式错误',
                ];
            }
        }
        if ($idcard != '') {
            if (!IdCard::isIdcard($idcard)) {
                return [
                    'status' => false,
                    'message' => '身份证格式错误',
                ];
            }
        }
        if ($realName != '') {
            if (mb_strlen($realName) < 2 || mb_strlen($realName) > 4) {
                return [
                    'status' => false,
                    'message' => '姓名长度为2-4个字符',
                ];
            }
        }
        if ($password == '') {
            return [
                'status' => false,
                'message' => '请输入登录密码',
            ];
        }
        if ($repassword != $password) {
            return [
                'status' => false,
                'message' => '确认密码跟密码不一致',
            ];
        }
        if (strlen($password) < 6) {
            return [
                'status' => false,
                'message' => '密码长度必须大于6位',
            ];
        }
        $promote = M('promote', 'tab_')->field(['id'])->where(['account' => $account])->find();
        if ($promote) {
            return [
                'status' => false,
                'message' => '渠道账号已存在',
            ];
        }

        $promoteCompanyService = new PromoteCompanyService();
        $verifyingPromotes = $promoteCompanyService->getVerifyingPromotes();
        if ($promoteCompanyService->isExistVerifyingPromoteAccount([$account], $verifyingPromotes)) {
            return [
                'status' => false,
                'message' => '渠道账号已存在',
            ];
        }

        return [
            'status' => true,
            'message' => '验证成功',
        ];
    }

    public function addPromote($params, $parent = null)
    {
        $data = [
            'account'       => $params['account'],
            'password'      => $this->password($params['password'], UC_AUTH_KEY),
            'nickname'      => $params['nickname'] ?? $params['account'],
            'second_pwd'    => $params['second_pwd'] ?? null,
            'real_name'     => $params['real_name'],
            'email'         => $params['email'],
            'idcard'        => $params['idcard'] ?? '',
            'status'        => $params['status'] ?? 0,
            'mobile_phone'  => $params['mobile_phone'],
            'bank_name'     => $params['bank_name'] ?? '',
            'bank_card'     => $params['bank_card'] ?? '',
            'parent_id'     => $parent ? $parent['id'] : 0,
            'parent_name'   => $parent ? $parent['account'] : C('OFFICIEL_CHANNEL'),
            'admin_id'      => $parent && $parent['admin_id'] > 0 ? $parent['admin_id'] : ($params['admin_id'] ?? 0),
            'company_id'    => $params['company_id'] ?? 0,
            'invite_code'   => $params['invite_code'] ?? '',
            'create_time'   => time(),
            'company_belong'   => $params['company_belong'] ?? 0,
            'company_relation'   => $params['company_relation'] ?? 0,
            'settlement_type'   => $params['settlement_type'] ?? 1,
            'group_remark'   => $params['group_remark'] ?? '',
            'withdraw_show'   => $params['withdraw_show'] ?? 0,
            'withdraw_done'   => $params['withdraw_done'] ?? 0,
            'can_view_recharge'=>$params['can_view_recharge'] ?? 0,
        ];

        if ($parent) {
            $data['chain'] = $parent['chain'] . $parent['id'] . '/';
            $data['level'] = $this->getLevelByChain($data['chain']) + 1;
        } else {
            $data['chain'] = '/';
            $data['level'] = 1;
        }
        $insert = M('promote', 'tab_')->add($data);

        // 如果是外团的,则自动加入市场总监审核列表
        if ($data['level'] == 1 && in_array($data['company_belong'], [1, 2])) {
            $id = M('promote', 'tab_')->getLastInsID();
            A('Market','Event')->addPresident($data['admin_id'],$id);
            resetUserAuth();
        }

        $fullChain = $data['chain'] . $insert;
        $fullChainList = explode('/', trim($fullChain, '/'));

        M('promote', 'tab_')->where(['id' => $insert])->save([
            'level1_id' => $fullChainList[0] ?? 0,
            'level2_id' => $fullChainList[1] ?? 0,
            'level3_id' => $fullChainList[2] ?? 0,
            'level4_id' => $fullChainList[3] ?? 0,
        ]);

        return $insert;
    }

    public function getLandingPageIdentifier($url)
    {
        $code = $this->getUrlParam($url, 'code');
        if ($code === null) {
            $pid = $this->getUrlParam($url, 'gid');
            $gid = $this->getUrlParam($url, 'pid');
            if ($gid === null || $gid === null) {
                return null;
            } else {
                return $gid . '-' . $pid;
            }
        }
        return $code;
    }

    public function getDownloadIdentifier($url)
    {
        $code = $this->getUrlParam($url, 'code');
        if ($code === null) {
            $pid = $this->getUrlParam($url, 'game_id');
            $gid = $this->getUrlParam($url, 'promote_id');
            if ($gid === null || $gid === null) {
                return null;
            } else {
                return $gid . '-' . $pid;
            }
        }
        return $code;
    }

    private function getUrlParam($url, $name)
    {
        $items = parse_url($url);
        $queryString = ltrim($items['query'], 's=');
        $queryString = ltrim($queryString, '/');
        $queryString = rtrim($queryString, '.html');
        $rows = explode('/', $queryString);
        $codeIndex = null;
        foreach ($rows as $key => $value) {
            if ($key >= 3 && $value == $name) {
                $codeIndex = $key;
                break;
            }
        }
        if ($codeIndex !== null) {
            return $rows[$codeIndex + 1] ?? null;
        }
        return null;
    }

    public function isPresidentAccess($promote)
    {
        $company = M('promote_company', 'tab_')->field(['id', 'company_belong'])->where(['id' => $promote['company_id']])->find();
        if (in_array($company['company_belong'], [1, 2])) {
            $record = M('president_deposit', 'tab_')->where(['company_id' => $company['id']])->find();
            if (!$record) {
                return false;
            }
            if (!in_array($record['status'], [1, 2])) {
                return false;
            }
        }
        return true;
    }

    public function getPromoteGroups($topPromoteId)
    {
        $promoteGroups = [];
        if (Registry::has('promoteGroups')) {
            $promoteGroups = Registry::get('promoteGroups');
        }
        if (!isset($promoteGroups[$topPromoteId])) {
            $data = [];
            $promotes = M('promote', 'tab_')->field(['id', 'level', 'group_remark', 'parent_id'])->where(['level' => ['in', [2, 3]], 'chain' => ['like', '/'.$topPromoteId.'/%']])->select();
            foreach ($promotes as $promote) {
                if ($promote['level'] == 2) {
                    $data[$promote['id']] = [
                        'name' => $promote['group_remark'],
                        'subs' => []
                    ];
                }
            }
            foreach ($promotes as $promote) {
                if ($promote['level'] == 3) {
                    $data[$promote['parent_id']]['subs'][$promote['id']] = [
                        'name' => $promote['group_remark'],
                    ];
                }
            }
            /*echo '<pre>';
            var_dump($data);
            echo '</pre>';die();*/
            $promoteGroups[$topPromoteId] = $data;
            Registry::set('promoteGroups', $promoteGroups);
        }
        return $promoteGroups[$topPromoteId];
    }

    public function getGroupNameByChain($chain, $promoteId)
    {
        $chain = trim($chain, '/');
        if ($chain == '') {
            return '';
        }
        $row = explode('/', $chain);
        $promoteGroups = $this->getPromoteGroups($row[0]);
        
        $groupName = '';
        if (isset($row[1])) {
            $groupName .= $promoteGroups[$row[1]]['name'];
            if (isset($row[2])) {
                $groupName .= '/' . $promoteGroups[$row[1]]['subs'][$row[2]]['name'];
            }
        }
        if (count($row) == 2) {
            $groupName .= '/' . $promoteGroups[$row[1]]['subs'][$promoteId]['name'];
        }
        if (count($row) == 1) {
            $groupName .= $promoteGroups[$promoteId]['name'];
        }
        return $groupName;
    }

    public function getVisibleBaseGames($promote)
    {
        $gameIds = $this->getVisibleGameIds($promote);
        if (count($gameIds) == 0) {
            return [];
        }
        return M('base_game', 'tab_')->where([
            '_logic' => 'or',
            'android_game_id' => ['in', $gameIds],
            'ios_game_id' => ['in', $gameIds],
        ])->select();
    }

    public function getVisibleGameIds($promote)
    {
        /* $gameIds = M('game', 'tab_')->getField('id', true);
        $selfGameIds = $promote['game_ids'] == '' ? $gameIds : explode(',', $promote['game_ids']); */

        $topPromote = $this->getTopPromote($promote);
        $topGameIds = $topPromote['game_ids'] == '' ? [] : explode(',', $topPromote['game_ids']);
        $selfGameIds = $topGameIds;
        // $selfGameIds = $promote['game_ids'] == '' ? [] : explode(',', $promote['game_ids']);
        // $selfGameIds = array_intersect($topGameIds, $selfGameIds);
        
        if ($promote['level'] == 1) {
            return $selfGameIds;
        }

        if ($topPromote['child_game_permission'] == 0) {
            $gameIds = M('apply', 'tab_')->where(['offline_status' => 0, 'promote_id' => $topPromote['id']])->getField('game_id', true);
            if (empty($gameIds)) {
                return [];
            }
            return array_intersect($selfGameIds, $gameIds);
        } else {
            return $selfGameIds;
        }
    }

    /**
     * 推广员所属公会历史所有推广过的游戏ID
     * @todo 如果没有用户充值则该游戏ID不会显示?
     */
    public function getHistoryGameIds($promote)
    {
        $topPromote = $this->getTopPromote($promote);
        $key = Redis::getKey('promote_history_games', ['promote_id' => $topPromote['level1_id']]);
        $value = Redis::get($key);
        $historyGameIds = $value ? explode(',', $value) : [];
        $nowGameIds = $topPromote['game_ids'] == '' ? [] : explode(',', $topPromote['game_ids']);
        return array_unique(array_merge($historyGameIds, $nowGameIds));
    }

    public function checkPromoteLimitRule($promote)
    {
        $accountString = 'wangshuai1,ouyangtianlin,zhangjiayuan02,zhangchuang,huangjian,lixiaojie01,youjinbo01,laijiansen,liutao001,huangdonyu,huangwenlu,qiujinwei,qiucanlon,panhailang,linzilun,xuechonbiao,chenfayun01,pengjun,shenyanwei,wusiju,kechengwei,linruidong,huzhoujian,linzelong,linwei1,zhanghanying,xushiming,linxuchen,zhengchengzhi,yaokaijie,wengyongbang,liaofaqian,zhangqing,liaojunwei,zhangming,zhaoxiaoyi01,zhongkaixin,zhangkaiyu,linwei01,dukunpeng,zhengjianzhou,wengshouxiong,caizhenxing,xiuguanxin,suyuelong,guozhijie,chenzhenghao,zhongyouling,linjian,xuwenye,zhengjinhe,huangyongqing,wangqiaozhen,jiangweihao,lijianfeng01,shaowenhui,huangyuhang,lianglingui,baoxiaohui,heyuming,linwanxi,jiangnan,ouzhijie,liguangcai,lican1,caiwenxin,xianggengyu,songzhibin,jinweiyuan,chenyixing,zhangxiang,denglan,yejiehui,wangbencai,huangzhenhon,liumeifu,xuliuyang,zhengmingquan,huangshengguang,liuweihuang,lixuemeng,xurongcheng,chenzhuo,caixiaodong,linhui,luwenjie,huangyonghao,xuguojin,ningyi01,zhouchongliang,chenshigang,chenyangwen,lijiayu,lanhua,zuojingjing,zhangxingliang,huangxinyu,pujianhao,zhengdongwei,xueyiqiang,lijiawei,tongqiang,huangxirui,wangjinfu,linhao01,chenlinzhi,zengjiawei,lijunjie01,xuwei01,diaowenfeng,guoyinzhen,chenzongda,luwujun,hongye,yangdegao,hehaiwei,zhangyutao,zhengxinyao,wangjunqi,wuyuze,linzejun,yangyunfeng,huangxiaojia,linqianyun,liyao01,huangkai,aihu01,wangshuai,zhangjiayuan01,youjinbo,zhangjiayuan,wengshouxion,ningyi';
        $accounts = explode(',', $accountString);
        if (in_array($promote['account'], $accounts)) {
            return false;
        }

        $topPromote = $this->getTopPromote($promote);
        $rule = M('promote_limit_rules', 'tab_')->where(['promote_id' => $topPromote['id']])->order('created_at desc')->limit(1)->find();
        if ($rule) {
            if ($rule['started_at'] === null && $rule['ended_at'] === null) {
                return false;
            } elseif ($rule['started_at'] === null && $rule['ended_at'] !== null) {
                if (time() < strtotime($rule['ended_at'] . ' 23:59:59')) {
                    return false;
                }
            } elseif ($rule['started_at'] !== null && $rule['ended_at'] === null) {
                if (time() >= strtotime($rule['started_at'] . ' 00:00:00')) {
                    return false;
                }
            } else {
                if (time() >= strtotime($rule['started_at'] . ' 00:00:00') && time() < strtotime($rule['ended_at'] . ' 23:59:59')) {
                    return false;
                }
            }
        }
        return true;
    }

    public function getPromoteCompanyBySite($url)
    {
        $domain = C('DOMAIN', null, '');
        if ($domain == '') {
            return null;
        }
        if (strpos($url, $domain) === false) {
            return null;
        }
        $url = str_replace('http://', '', $url);
        $url = str_replace('https://', '', $url);
        $url = str_replace($domain, '', $url);
        $domainPrefix = '';
        if ($url != 'tg') {
            $domainPrefix = str_replace('tg-', '', $url);
        }
        return M('promote_company', 'tab_')->where(['site_domain_prefix' => $domainPrefix])->find();
    }

    public function getSiteConfig($promoteCompany)
    {
        $siteConfig = $promoteCompany && $promoteCompany['is_site_custom'] == 1 ? json_decode($promoteCompany['site_config'], true) : null;
        if (!$siteConfig) {
            $siteConfig = [];
            $siteConfig['logo'] = check_logo_is_exist(C('CH_LOGO_BACKSTAGE'), 'logo_default.png');
            // $siteConfig['login_logo'] = check_logo_is_exist(C('CH_SET_LOGO'),'logo_default.png');
            $siteConfig['icon'] = get_cover(C('CH_SET_ICO'), 'path');
            $siteConfig['title'] = seo_replace(C('channel_index.seo_title'),'','channel') . '_' . C('CH_SET_TITLE');
        } else {
            $siteConfig['logo'] = get_cover($siteConfig['logo'], 'path');
            $siteConfig['icon'] = get_cover($siteConfig['icon'], 'path');
            $siteConfig['title'] = '推广平台_手机游戏推广联盟_手游推广员赚钱平台';
        }
        $siteConfig['description'] = '首页 登录 欢迎您回来!';
        $siteConfig['keywords'] = C('channel_index.seo_keyword');
        return $siteConfig;
    }

    /**
     * 获取推广员实际拥有的测试资源数据操作范围(测试资源跨部门操作权限)
     */
    public function getTSPermPromote($promote)
    {
        if (empty($promote)) {
            return null;
        }
        if ($promote['ts_over_apply'] == 1) {
            return $this->getTopPromote($promote);
        }
        return $promote;
    }
}