<?php

namespace app\service\game;

use addons\webman\model\Game;
use addons\webman\model\GamePlatform;
use addons\webman\model\Player;
use addons\webman\model\PlayerGamePlatform;
use addons\webman\model\PlayerWalletTransfer;
use app\exception\GameException;
use Exception;
use support\Log;
use support\Response;

class CSServiceInterface extends GameServiceFactory implements GameServiceInterface
{
    public $method = 'POST';
    public $successCode = '0';
    /** @var PlayerGamePlatform $playerGamePlatform */
    public $playerGamePlatform;
    public $gameType = [
        'CB' => 'CARD & BOARDGAME',
        'ES' => 'E-GAMES',
        'SB' => 'SPORTBOOK',
        'LC' => 'LIVE-CASINO',
        'SL' => 'SLOTS',
        'LK' => 'LOTTO',
        'FH' => 'FISH HUNTER',
        'PK' => 'POKER',
        'MG' => 'MINI GAME',
        'OT' => 'OTHERS'
    ];
    public $failCode = [
        '61' => '货币不兼容',
        '70' => '集成系统余额不足',
        '71' => '单据号不正确',
        '72' => '余额不足',
        '73' => '转账金额不正确',
        '74' => '转账金额不能多过两个小数点 0.00',
        '75' => '不允许在游戏中进行转移',
        '81' => '会员账号不存在',
        '82' => '会员账号已存在',
        '83' => '代理号已存在',
        '90' => '请求参数不正确',
        '91' => '代理号不正确',
        '92' => '供应商代号不正确',
        '93' => '请求参数类型不正确',
        '94' => '账号不正确',
        '95' => '密码不正确',
        '96' => '旧密码不正确',
        '97' => '请求链接/域名不正确',
        '98' => '账号/密码错误',
        '99' => '加密错误',
        '600' => '前期检验失败。 存款/取款 操作已被无视',
        '601' => '此产品的存款 功能暂时停用维修',
        '602' => '此产品的取款 功能暂时停用维修',
        '603' => '即将执行在线系统维护，为了避免维护时导致的系统不稳定，转账API暂时停止（暂停时间大约5～10分钟，若提早完毕会提早解放）',
        '992' => '平台不兼容请求的游戏类型',
        '991' => '代理号已冻结',
        '994' => '接口访问被禁止',
        '995' => '平台未开通',
        '996' => '平台不支持',
        '998' => '请联系客服',
        '999' => '系统维护中',
        '9999' => '未知错误',
        '-987' => '交易单号不存在；产品不支持',
        '-997' => '系统错误，请联络客服。',
        '-998' => '集成系统接口余额不足',
        '-999' => '接口错误',
    ];
    private $apiDomain;
    private $providerCode;
    private $appId;
    private $appSecret;
    private $path = [
        'createPlayer' => '/createMember.aspx',
        'getGameList' => '/getGameList.aspx',
        'getBalance' => '/getBalance.aspx',
        'getLoginH5' => '/launchGames.aspx',
        'getDLoginH5' => '/launchDGames.ashx',
        'changePassword' => '/changePassword.aspx',
        'checkAgentCredit' => '/checkAgentCredit.aspx',
        'checkMemberProductUsername' => '/checkMemberProductUsername.aspx',
        'launchAPP' => '/launchAPP.ashx',
        'checkTransaction' => '/checkTransaction.ashx',
        'setBalanceTransfer' => '/makeTransfer.aspx',
        'getDailyWager' => '/getDailyWager.ashx',
        'fetchArchieve' => '/fetchArchieve.aspx',
        'markbyjson' => '/markbyjson.aspx',
        'markArchieve' => '/markArchieve.ashx',
        'getGameRecord' => '/fetchbykey.aspx',
    ];
    private $lang = [
        'zh-CN' => 'zh-ch',
        'en' => 'en_us',
        'zh_tc' => 'zh_tc',
        'en-us' => 'en-us',
        'id' => 'id',
        'th' => 'th',
        'my' => 'my',
        'vi' => 'vi',
        'fi_fi' => 'fi_fi',
        'kr_ko' => 'kr_ko',
        'hi_hi' => 'hi_hi',
        'br_po' => 'br_po',
        'lo_la' => 'lo_la',
        'cam_dia' => 'cam_dia', // 柬埔寨语
    ];
    
    /**
     * @param Player|null $player
     * @param $type
     * @throws Exception
     */
    public function __construct($type, Player $player = null)
    {
        $config = config('game_platform.' . $type);
        $this->appId = $config['app_id'];
        $this->appSecret = $config['app_secret'];
        $this->apiDomain = $config['api_domain'];
        $this->providerCode = $config['provider_code'];
        $this->platform = GamePlatform::query()->where('name', $type)->first();
        if (!empty($player)) {
            $this->player = $player;
            /** @var PlayerGamePlatform $playerGamePlatform */
            $playerGamePlatform = $this->player->playerGamePlatform->where('platform_id', $this->platform->id)->first();
            if (empty($playerGamePlatform)) {
                $this->createPlayer();
            } else {
                $this->playerGamePlatform = $playerGamePlatform;
            }
        }
    }
    
    /**
     * 创建玩家 MD5(operatorcode + username +secret_key)
     * @return array|mixed|Response
     * @throws GameException|\think\Exception
     */
    public function createPlayer()
    {
        $userName = mb_strtolower($this->providerCode . generateUniqueUsername());
        $params = [
            'operatorcode' => $this->appId,
            'username' => $userName,
        ];
        $params['signature'] = mb_strtoupper(md5($this->appId . $userName . $this->appSecret));
        $res = dogGetCurl($this->createUrl('createPlayer'), $params);
        if ($res['errCode'] != $this->successCode) {
            throw new GameException($this->failCode[$res['errCode']], 0);
        }
        $playerGamePlatform = new PlayerGamePlatform();
        $playerGamePlatform->player_id = $this->player->id;
        $playerGamePlatform->platform_id = $this->platform->id;
        $playerGamePlatform->player_name = $this->player->name;
        $playerGamePlatform->player_code = $userName;
        $playerGamePlatform->player_password = generateRandomPassword();
        $playerGamePlatform->save();
        $this->playerGamePlatform = $playerGamePlatform;
        return $res;
    }
    
    /**
     * 生成请求url
     * @param $method
     * @return string
     */
    public function createUrl($method): string
    {
        return $this->apiDomain . $this->path[$method];
    }
    
    /**
     * 查询玩家游戏平台帐号接口 MD5(operatorcode + providercode + username + secret_key)
     * @return array|mixed|Response
     * @throws GameException|\think\Exception
     */
    public function getPlayer()
    {
        $params = [
            'operatorcode' => $this->appId,
            'providercode' => $this->providerCode,
            'username' => $this->playerGamePlatform->player_code,
        ];
        $params['signature'] = mb_strtoupper(md5($this->appId . $this->providerCode . $this->playerGamePlatform->player_code . $this->appSecret));
        $res = dogGetCurl($this->createUrl('checkMemberProductUsername'), $params);
        if ($res['errCode'] != $this->successCode) {
            throw new GameException($this->failCode[$res['errCode']], 0);
        }
        
        return $res;
    }
    
    /**
     * 获取游戏列表 MD5(operatorcode.toLower() + providercode.toUpper() + secret_key)
     * @return array|mixed|Response
     * @throws GameException|\think\Exception
     */
    public function getSimpleGameList()
    {
        $params = [
            'providercode' => $this->providerCode,
            'operatorcode' => $this->appId,
            'lang' => 'en',
            'html' => '0',
            'reformatJson' => 'yes',
        ];
        $params['signature'] = strtoupper(md5(mb_strtolower($this->appId) . mb_strtoupper($this->providerCode) . $this->appSecret));
        $data = dogGetCurl($this->createUrl('getGameList'), $params);
        if ($data['errCode'] != $this->successCode) {
            throw new GameException($this->failCode[$data['errCode']], 0);
        }
        if (!empty($data['gamelist'])) {
            $gameList = json_decode($data['gamelist'], true);
            foreach ($gameList as $game) {
                try {
                    Game::query()->updateOrCreate(
                        [
                            'platform_id' => $this->platform->id,
                            'game_code' => $game['g_code']
                        ],
                        [
                            'platform_game_type' => $game['p_type'],
                            'game_data' => json_encode($game),
                            'name' => $game['gameName']['gameName_enus'] ?? '',
                            'game_image' => $game['imgFileName'] ?? '',
                        ]
                    );
                } catch (Exception $e) {
                    Log::error($e->getMessage());
                }
            }
        }
        return $data;
    }
    
    /**
     * 登录游戏MD5(operatorcode + password + providercode + type + username + secret_key)
     * @param array $data
     * @return string
     * @throws GameException|\think\Exception
     */
    public function login(array $data = []): string
    {
        $params = [
            'operatorcode' => $this->appId,
            'providercode' => $this->providerCode,
            'username' => $this->playerGamePlatform->player_code,
            'password' => $this->playerGamePlatform->player_password,
            'type' => $data['platformGameType'],
            'gameid' => $data['gameCode'] ?? 0,
            'lang' => 'en',
            'html5' => 1,
        ];
        $params['signature'] = mb_strtoupper(md5($this->appId . $this->playerGamePlatform->player_password . $this->providerCode . $data['platformGameType'] . $this->playerGamePlatform->player_code . $this->appSecret));
        $res = dogGetCurl($this->createUrl('getLoginH5'), $params);
        
        if ($res['errCode'] != $this->successCode) {
            Log::error($this->failCode[$res['errCode']], ['res' => $res]);
            throw new GameException($this->failCode[$res['errCode']], 0);
        }
        return $res['gameUrl'];
    }
    
    
    /**
     * 玩家钱包转入游戏平台
     * @return array|mixed|null
     * @throws GameException|\think\Exception
     */
    public function balanceTransferOut()
    {
        
        return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_OUT, intval($this->player->wallet->money));
    }
    
    /**
     * 资金转账接口MD5(amount + operatorcode + password + providercode + referenceid + type + username + secret_key)
     * @param $type
     * @param float $amount
     * @return array|mixed|null
     * @throws GameException
     * @throws \think\Exception
     */
    protected function setBalanceTransfer($type, float $amount = 0)
    {
        if ($type == PlayerWalletTransfer::TYPE_OUT) {
            $platformType = 0;
        } else {
            $platformType = 1;
        }
        
        $no = createOrderNo();
        $params = [
            'operatorcode' => $this->appId,
            'providercode' => $this->providerCode,
            'username' => $this->playerGamePlatform->player_code,
            'password' => $this->playerGamePlatform->player_password,
            'referenceid' => $no,
            'type' => $platformType,
            'amount' => $amount
        ];
        $params['signature'] = mb_strtoupper(md5($amount . $this->appId . $this->playerGamePlatform->player_password . $this->providerCode . $no . $platformType . $this->playerGamePlatform->player_code . $this->appSecret));
        $res = dogGetCurl($this->createUrl('setBalanceTransfer'), $params);
        if ($res['errCode'] != $this->successCode) {
            throw new GameException($this->failCode[$res['errCode']], 0);
        }
        // 记录玩家钱包转出转入记录
        $this->createWalletTransfer($type, $amount, 0, $res['innerCode'] ?? '');
        
        return $res;
    }
    
    /**
     * 玩家钱包转入游戏平台
     * @return array|mixed|null
     * @throws GameException|\think\Exception
     */
    public function balanceTransferIn()
    {
        $balance = $this->getBalance();
        return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_IN, $balance['balance'] ?? 0);
    }
    
    /**
     * 獲取玩家餘額信息
     * 簽名密鑰方式 MD5(operatorcode + password + providercode + username + secret_key)
     * @return array|mixed|Response
     * @throws GameException|\think\Exception
     */
    public function getBalance()
    {
        $params = [
            'operatorcode' => $this->appId,
            'providercode' => $this->providerCode,
            'username' => $this->playerGamePlatform->player_code,
            'password' => $this->playerGamePlatform->player_password
        ];
        $params['signature'] = mb_strtoupper(md5($this->appId . $this->playerGamePlatform->player_password . $this->providerCode . $this->playerGamePlatform->player_code . $this->appSecret));
        $res = dogGetCurl($this->createUrl('getBalance'), $params);
        if ($res['errCode'] != $this->successCode) {
            throw new GameException($this->failCode[$res['errCode']], 0);
        }
        
        return $res;
    }
    
    /**
     * 依據時間獲取遊戲紀錄
     * MD5 (Id+Method+SN+StartTime+EndTime+APISecretKey)
     * @param int $pageIndex
     * @param string $startTime
     * @param string $endTime
     * @return array|mixed|null
     * @throws GameException
     */
    public function getGameRecordByTime(int $pageIndex = 1, string $startTime = '', string $endTime = '')
    {
    
    }
    
    /**
     * 獲取玩家遊戲歷史紀錄
     * MD5 (Id+Method+SN+APISecretKey)
     * @return array|mixed|null
     * @throws GameException
     */
    public function getGameRecord()
    {
    }
}