<?php

namespace App\Game\Services;

use App\Game\GlobalUserInfo;
use App\Http\helper\NumConfig;
use App\Models\AccountsInfo;
use App\Notification\TelegramBot;
use App\Util;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class EvoplayService
{
    protected $client;
    protected $currency;
    protected $apiUrl;
    protected $projectId;
    protected $secretKey;
    protected $version;
    protected $systemId;

    public function __construct()
    {
        $this->client = new Client();
        $this->currency = env('CONFIG_24680_CURRENCY');
        $this->apiUrl = env('EVOPLAY_API_URL', 'https://api.evoplay.games');
        $this->projectId = env('EVOPLAY_PROJECT_ID', '11800');
        $this->secretKey = env('EVOPLAY_SECRET_KEY', '68e071e88a198e25d847c30d0724eb2c');
        $this->version = env('EVOPLAY_API_VERSION', '1');
        $this->systemId = env('EVOPLAY_SYSTEM_ID', '24680-com-test');
    }

    /**
     * 调用子API
     *
     * @param string $username
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function callSubApi($username, $request)
    {
        Util::WriteLog('evoplay', 'callsubapi');
        $apiurl = ServerService::GetApiByGUID($username);

        try {
            $postData = $request->post();

            $response = $this->client->post($apiurl . $_SERVER['REQUEST_URI'], [
                'verify' => false,
                'form_params' => $postData,
            ]);
            $res = json_decode($response->getBody(), true);
            Util::WriteLog('evoplay', $res);
            return $res;
        } catch (RequestException $e) {
            return $this->handleRequestException($e);
        }
    }

    /**
     * 处理请求异常
     *
     * @param \Exception $e
     * @return array
     */
    private function handleRequestException(\Exception $e)
    {
        Util::WriteLog('evoplay_error', $e->getMessage());
        return [
            'status' => 'error',
            'error' => [
                'code' => 'INTERNAL_ERROR',
                'message' => 'Internal server error'
            ]
        ];
    }

    /**
     * 生成签名
     *
     * @param array $data 请求数据
     * @return string 签名
     */
    public function generateSignature($data)
    {
        // 按字母顺序排序参数
        ksort($data);

        // 将参数转换为查询字符串
        $query = http_build_query($data);

        // 生成签名
        return hash_hmac('sha256', $query, $this->secretKey);
    }

    /**
     * 获取游戏列表
     *
     * @return array
     */
    public function getGamesList()
    {
        try {
            $data = [
                'project' => $this->projectId,
                'version' => $this->version,
                'need_extra_data' => 1,
            ];

            // 生成签名
            $data['signature'] = $this->generateSignature($data);

            // 调用游戏列表API
            $response = $this->client->post($this->apiUrl . '/Game/getList', [
                'verify' => false,
                'form_params' => $data
            ]);

            return json_decode($response->getBody(), true);
        } catch (\Exception $e) {
            Util::WriteLog('evoplay_error', $e->getMessage());
            return ['error' => $e->getMessage()];
        }
    }

    /**
     * 获取游戏启动URL
     *
     * @param string $gameId 游戏ID
     * @param string $userId 用户ID
     * @param string $language 语言
     * @param string $currency 货币
     * @param bool $demo 是否为试玩模式
     * @return string|null
     */
    public function getGameUrl($gameId, $userId, $language = 'en', $currency = null, $demo = false)
    {
        try {
            if (!$currency) {
                $currency = $this->currency;
            }

            $data = [
                'project_id' => $this->projectId,
                'version' => $this->version,
                'system_id' => $this->systemId,
                'user_id' => $userId,
                'game_id' => $gameId,
                'currency' => $currency,
                'language' => $language,
                'denomination' => 1,
                'return_url' => url('/'),
                'callback_url' => url('/api/callback/evoplay'),
                'callback_version' => 2,
                'signature' => ''
            ];

            if ($demo) {
                $data['demo'] = 1;
            }

            // 生成签名
            $data['signature'] = $this->generateSignature($data);

            // 调用游戏启动API
            $response = $this->client->post($this->apiUrl . '/game/geturl', [
                'verify' => false,
                'form_params' => $data
            ]);

            $result = json_decode($response->getBody(), true);

            if (isset($result['status']) && $result['status'] === 'ok' && isset($result['url'])) {
                return $result['url'];
            }

            Util::WriteLog('evoplay_error', 'Failed to get game URL: ' . json_encode($result));
            return null;
        } catch (\Exception $e) {
            Util::WriteLog('evoplay_error', $e->getMessage());
            return null;
        }
    }

    /**
     * 玩家验证
     *
     * @param string $userId 用户ID
     * @return array 用户信息
     */
    public function validateUser($userId)
    {
        try {
            // 获取用户信息
            $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $userId);
            if (!$user) {
                return [
                    'status' => 'error',
                    'error' => [
                        'code' => 'USER_NOT_FOUND',
                        'message' => 'User not found'
                    ]
                ];
            }

            // 获取用户余额
            $balance = GlobalUserInfo::getScoreByUserID($user->UserID);

            return [
                'status' => 'ok',
                'data' => [
                    'id' => $userId,
                    'name' => $user->NickName,
                    'balance' => $balance,
                    'currency' => $this->currency
                ]
            ];
        } catch (\Exception $e) {
            Util::WriteLog('evoplay_error', $e->getMessage());
            return [
                'status' => 'error',
                'error' => [
                    'code' => 'INTERNAL_ERROR',
                    'message' => 'Internal server error'
                ]
            ];
        }
    }

    /**
     * 处理余额查询
     *
     * @param string $userId 用户ID
     * @return array 余额信息
     */
    public function getBalance($userId)
    {
        try {
            // 获取用户信息
            $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $userId);
            if (!$user) {
                return [
                    'status' => 'error',
                    'error' => [
                        'code' => 'USER_NOT_FOUND',
                        'message' => 'User not found'
                    ]
                ];
            }

            // 获取用户余额
            $balance = GlobalUserInfo::getScoreByUserID($user->UserID);

            return [
                'status' => 'ok',
                'data' => [
                    'balance' => $balance,
                    'currency' => $this->currency
                ]
            ];
        } catch (\Exception $e) {
            Util::WriteLog('evoplay_error', $e->getMessage());
            return [
                'status' => 'error',
                'error' => [
                    'code' => 'INTERNAL_ERROR',
                    'message' => 'Internal server error'
                ]
            ];
        }
    }

    /**
     * 处理下注请求
     *
     * @param string $userId 用户ID
     * @param string $gameId 游戏ID
     * @param float $amount 金额
     * @param string $transactionId 交易ID
     * @param string $roundId 回合ID
     * @return array 处理结果
     */
    public function bet($userId, $gameId, $amount, $transactionId, $roundId)
    {
        try {
            // 获取用户信息
            $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $userId);
            if (!$user) {
                return [
                    'status' => 'error',
                    'error' => [
                        'code' => 'USER_NOT_FOUND',
                        'message' => 'User not found'
                    ]
                ];
            }

            $userId = $user->UserID;

            // 检查交易是否已处理
            $transactionKey = 'evoplay_tx_' . $transactionId;
            if (Redis::exists($transactionKey)) {
                // 交易已处理，返回上次的结果
                $previousResult = json_decode(Redis::get($transactionKey), true);
                return $previousResult;
            }

            // 获取当前余额
            $currentBalance = GlobalUserInfo::getScoreByUserID($userId) * NumConfig::NUM_VALUE;
            $amountInCents = intval($amount * NumConfig::NUM_VALUE);

            // 检查余额是否足够
            if ($currentBalance < $amountInCents) {
                $errorResponse = [
                    'status' => 'error',
                    'error' => [
                        'code' => 'INSUFFICIENT_FUNDS',
                        'message' => 'Insufficient funds'
                    ]
                ];
                return $errorResponse;
            }

            // 获取独占锁确保事务安全
            $res = SetNXLock::getExclusiveLock('evoplay_bet_' . $transactionId, 86400);
            if (!$res) {
                // 已经处理过，返回之前的结果
                return $this->getBalance($userId);
            }

            // 扣除余额
            DB::connection('write')->table('QPTreasureDB.dbo.GameScoreInfo')
                ->where('UserID', $userId)
                ->decrement('Score', $amountInCents);

            // 记录下注
            PlatformService::platformBet('evoplay', $gameId, $amountInCents, $userId);

            // 保存交易数据用于可能的取消
            Redis::set('evoplay_bet_' . $transactionId, $gameId . '_' . $amountInCents . '_' . $roundId);
            Redis::expire('evoplay_bet_' . $transactionId, 86400);

            // 更新当前余额
            $currentBalance -= $amountInCents;

            // 构造成功响应
            $response = [
                'status' => 'ok',
                'data' => [
                    'balance' => $currentBalance / NumConfig::NUM_VALUE,
                    'currency' => $this->currency,
                    'transaction_id' => $transactionId
                ]
            ];

            // 缓存交易结果
            Redis::set($transactionKey, json_encode($response));
            Redis::expire($transactionKey, 86400);

            return $response;
        } catch (\Exception $e) {
            Util::WriteLog('evoplay_error', $e->getMessage());
            return [
                'status' => 'error',
                'error' => [
                    'code' => 'INTERNAL_ERROR',
                    'message' => 'Internal server error'
                ]
            ];
        }
    }

    /**
     * 处理赢钱请求
     *
     * @param string $userId 用户ID
     * @param string $gameId 游戏ID
     * @param float $amount 金额
     * @param string $transactionId 交易ID
     * @param string $roundId 回合ID
     * @param string $betTransactionId 下注交易ID
     * @return array 处理结果
     */
    public function win($userId, $gameId, $amount, $transactionId, $roundId, $betTransactionId = null)
    {
        try {
            // 获取用户信息
            $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $userId);
            if (!$user) {
                return [
                    'status' => 'error',
                    'error' => [
                        'code' => 'USER_NOT_FOUND',
                        'message' => 'User not found'
                    ]
                ];
            }

            $userId = $user->UserID;

            // 检查交易是否已处理
            $transactionKey = 'evoplay_tx_' . $transactionId;
            if (Redis::exists($transactionKey)) {
                // 交易已处理，返回上次的结果
                $previousResult = json_decode(Redis::get($transactionKey), true);
                return $previousResult;
            }

            // 获取当前余额
            $currentBalance = GlobalUserInfo::getScoreByUserID($userId) * NumConfig::NUM_VALUE;
            $amountInCents = intval($amount * NumConfig::NUM_VALUE);

            // 获取独占锁确保事务安全
            $res = SetNXLock::getExclusiveLock('evoplay_win_' . $transactionId, 86400);
            if (!$res) {
                // 已经处理过，返回之前的结果
                return $this->getBalance($userId);
            }

            // 检查投注记录
            $originalBet = 0;
            if ($betTransactionId) {
                $betKey = 'evoplay_bet_' . $betTransactionId;
                if (Redis::exists($betKey)) {
                    $betInfo = Redis::get($betKey);
                    $parts = explode('_', $betInfo);
                    $originalBet = isset($parts[1]) ? intval($parts[1]) : 0;
                }
            }

            // 增加余额
            DB::connection('write')->table('QPTreasureDB.dbo.GameScoreInfo')
                ->where('UserID', $userId)
                ->increment('Score', $amountInCents);

            // 记录赢取
            PlatformService::platformWin(
                $userId,
                'evoplay',
                $gameId,
                $amountInCents,
                $originalBet,
                $currentBalance + $amountInCents
            );

            // 更新当前余额
            $currentBalance += $amountInCents;

            // 构造成功响应
            $response = [
                'status' => 'ok',
                'data' => [
                    'balance' => $currentBalance / NumConfig::NUM_VALUE,
                    'currency' => $this->currency,
                    'transaction_id' => $transactionId
                ]
            ];

            // 缓存交易结果
            Redis::set($transactionKey, json_encode($response));
            Redis::expire($transactionKey, 86400);

            return $response;
        } catch (\Exception $e) {
            Util::WriteLog('evoplay_error', $e->getMessage());
            return [
                'status' => 'error',
                'error' => [
                    'code' => 'INTERNAL_ERROR',
                    'message' => 'Internal server error'
                ]
            ];
        }
    }

    /**
     * 处理交易回滚请求
     *
     * @param string $userId 用户ID
     * @param string $transactionId 要回滚的交易ID
     * @param string $rollbackTransactionId 回滚交易ID
     * @return array 处理结果
     */
    public function rollback($userId, $transactionId, $rollbackTransactionId)
    {
        try {
            // 获取用户信息
            $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $userId);
            if (!$user) {
                return [
                    'status' => 'error',
                    'error' => [
                        'code' => 'USER_NOT_FOUND',
                        'message' => 'User not found'
                    ]
                ];
            }

            $userId = $user->UserID;

            // 检查回滚交易是否已处理
            $rollbackKey = 'evoplay_rollback_' . $rollbackTransactionId;
            if (Redis::exists($rollbackKey)) {
                // 回滚已处理，返回上次的结果
                $previousResult = json_decode(Redis::get($rollbackKey), true);
                return $previousResult;
            }

            // 检查原始交易
            $transactionKey = 'evoplay_tx_' . $transactionId;
            if (!Redis::exists($transactionKey)) {
                return [
                    'status' => 'error',
                    'error' => [
                        'code' => 'TRANSACTION_NOT_FOUND',
                        'message' => 'Original transaction not found'
                    ]
                ];
            }

            // 获取原始交易信息
            $originalTransaction = json_decode(Redis::get($transactionKey), true);

            // 检查是否是投注交易
            $betKey = 'evoplay_bet_' . $transactionId;
            if (Redis::exists($betKey)) {
                $betInfo = Redis::get($betKey);
                $parts = explode('_', $betInfo);
                $gameId = $parts[0] ?? '';
                $amount = isset($parts[1]) ? intval($parts[1]) : 0;

                // 获取独占锁确保事务安全
                $res = SetNXLock::getExclusiveLock($rollbackKey, 86400);
                if (!$res) {
                    // 已经处理过，返回之前的结果
                    return $this->getBalance($userId);
                }

                // 获取当前余额
                $currentBalance = GlobalUserInfo::getScoreByUserID($userId) * NumConfig::NUM_VALUE;

                // 退还金额
                DB::connection('write')->table('QPTreasureDB.dbo.GameScoreInfo')
                    ->where('UserID', $userId)
                    ->increment('Score', $amount);

                // 记录取消交易
                PlatformService::platformBet('evoplay', $gameId, -$amount, $userId);

                // 更新当前余额
                $currentBalance += $amount;

                // 构造成功响应
                $response = [
                    'status' => 'ok',
                    'data' => [
                        'balance' => $currentBalance / NumConfig::NUM_VALUE,
                        'currency' => $this->currency,
                        'transaction_id' => $rollbackTransactionId
                    ]
                ];

                // 缓存回滚结果
                Redis::set($rollbackKey, json_encode($response));
                Redis::expire($rollbackKey, 86400);

                return $response;
            } else {
                // 如果不是投注交易，则可能是赢钱交易，处理方式类似
                // 这里简化处理，实际应该根据Evoplay的具体要求实现
                return [
                    'status' => 'error',
                    'error' => [
                        'code' => 'UNSUPPORTED_OPERATION',
                        'message' => 'Only bet transactions can be rolled back'
                    ]
                ];
            }
        } catch (\Exception $e) {
            Util::WriteLog('evoplay_error', $e->getMessage());
            return [
                'status' => 'error',
                'error' => [
                    'code' => 'INTERNAL_ERROR',
                    'message' => 'Internal server error'
                ]
            ];
        }
    }
}
