<?php

namespace App\Http\Controllers\Game;

use App\Facade\TableName;
use App\Game\GameCard;
use App\Game\GlobalUserInfo;
use App\Game\LogGamecardClick;
use App\Game\Services\OuroGameService;
use App\Game\Services\PlatformService;
use App\Game\Services\ServerService;
use App\Game\Services\LuckyStreakService;
use App\Http\helper\NumConfig;
use App\Models\AccountsInfo;
use App\Notification\TelegramBot;
use App\Util;
use App\Utility\SetNXLock;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Log;

class LuckyStreakController extends Controller
{
    protected $client;
    protected $currency;
    protected $operatorId;
    protected $operatorName;
    protected $clientId;
    protected $clientSecret;
    protected $apiUrl;
    protected $luckyStreakService;

    private $hmacData=['path' => '',
                       'method' => '',
                       'timestamp' => '',
                       'nonce' => ''];

    public function __construct(LuckyStreakService $luckyStreakService)
    {
        $this->client = new Client();
        $this->currency = env('CONFIG_24680_CURRENCY');
        $this->operatorId = env('LUCKYSTREAK_OPERATOR_ID', '526');
        $this->operatorName = env('LUCKYSTREAK_OPERATOR_NAME', 'AEG');
        $this->clientId = env('LUCKYSTREAK_CLIENT_ID', 'AEG_operator');
        $this->clientSecret = env('LUCKYSTREAK_CLIENT_SECRET', 'X6vuibvYJI2Z9NglbzZE');
        $this->apiUrl = env('LUCKYSTREAK_API_URL', 'https://integ.livepbt.com');
        $this->luckyStreakService = $luckyStreakService;
    }

    /**
     * 验证请求的真实性
     *
     * @param Request $request
     * @return bool
     */
    private function verifyRequest(Request $request)
    {
        // 获取Authorization头
        $authHeader = $request->header('Authorization');

        // 如果没有Authorization头，拒绝请求
        if (empty($authHeader)) {
            Util::WriteLog('luckystreak_hmac', 'No Authorization header found');
            return true;
        }

        // 检查是否是Hawk认证格式
        if (strpos($authHeader, 'hawk ') !== 0) {
            Util::WriteLog('luckystreak_hmac', 'Not a Hawk authentication format');
            return false;
        }

        // 解析Hawk头信息
        $matches = [];
        preg_match('/id="([^"]+)"/', $authHeader, $matches);
        $id = $matches[1] ?? '';

        preg_match('/ts="([^"]+)"/', $authHeader, $matches);
        $timestamp = $matches[1] ?? '';

        preg_match('/nonce="([^"]+)"/', $authHeader, $matches);
        $nonce = $matches[1] ?? '';

        preg_match('/mac="([^"]+)"/', $authHeader, $matches);
        $mac = $matches[1] ?? '';

        preg_match('/hash="([^"]+)"/', $authHeader, $matches);
        $hash = $matches[1] ?? '';

        preg_match('/ext="([^"]+)"/', $authHeader, $matches);
        $ext = $matches[1] ?? '';

        // 如果缺少必要参数，拒绝请求
        if (empty($id) || empty($timestamp) || empty($nonce) || empty($mac)) {
            Util::WriteLog('luckystreak_hmac', 'Missing required Hawk parameters');
            return false;
        }
//        Util::WriteLog('luckystreak_hmac', $authHeader);

        // 获取请求方法和路径
        $method = $request->method();
        $path = '/'.$request->path();

        // 获取请求体
        $body = $request->getContent();

        // 构建验证数据
        $data = [
            'path' => $path,
            'method' => $method,
            'timestamp' => $timestamp,
            'nonce' => $nonce
        ];

        if (!empty($body)) {
            $data['body'] = $body;
        }

        if (!empty($ext)) {
            $data['ext'] = $ext;
        }

        if (!empty($hash)) {
            $data['hash'] = $hash;
        }

        $this->hmacData=$data;
        // 使用LuckyStreakService验证签名
        $isValid = $this->luckyStreakService->verifyHmacSignature($data, $mac);

//        Util::WriteLog('luckystreak_hmac', compact('isValid', 'data','hash','mac','ext'));

        return $isValid;
    }
    public function reponseHeader($request,$responseData,$status=200)
    {
        // 生成响应对象
        $response = response()->json($responseData,$status);


        // 获取响应内容
        $responseContent = json_encode($responseData);

        // 生成HMAC头
        $hmacHeaders = $this->luckyStreakService->generateHmacSignature($this->hmacData, $responseContent);

        // 添加HMAC头到响应
        foreach ($hmacHeaders as $header => $value) {
            $response->header($header, str_replace("\n", " ", $value));
        }

        return $response;

    }
    /**
     * 验证玩家身份
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function validate(Request $request)
    {
        $requestData = $request->all();
        Util::WriteLog('luckystreak_validate', [$requestData,$request->header()]);

        // 验证请求的真实性
        if (!$this->verifyRequest($request)) {
            return response()->json([
                'errors' => [
                    ['code' => 'AUTH_001', 'message' => 'Unauthorized request']
                ]
            ], 401);
        }

        // 按照LuckyStreak API格式获取请求数据
        if (isset($requestData['data'])) {
            $data = $requestData['data'];
        } else {
            $data = $requestData;
        }

        $authCode = $data['AuthorizationCode'] ?? null;
        $operatorName = $data['OperatorName'] ?? $this->operatorName;

        if (!$authCode) {
            return $this->reponseHeader($request,[
                'errors' => [
                    ['code' => 'AUTH_002', 'message' => 'Authorization code is required']
                ]
            ], 400);
        }

        // 在这里我们用authCode作为用户名，因为LuckyStreak使用它来标识玩家
        $username = $authCode;

        if(!ServerService::IsLocalUser($username)) {
            $data=$this->luckyStreakService->callSubApi($username, $request);
            return $this->reponseHeader($request,$data);
        }

        // 尝试查找用户
        $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $username);
        if (!$user) {
            return response()->json([
                'errors' => [
                    ['code' => 'AUTH_003', 'message' => 'Player not found']
                ]
            ], 404);
        }

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

        // 获取当前时间，格式化为UTC格式
        $currentTimeUtc = gmdate('Y-m-d\TH:i:s.u\Z');

        // 准备响应数据
        $responseData = [
            'data' => [
                'userName' => $username,
                'currency' => $this->currency,
                'language' => GlobalUserInfo::getLocale() . 'US', // 例如：enUS, esUS等
                'timeZone' => null,
                'nickname' => strlen($user->NickName)<6?$user->NickName.$user->NickName:$user->NickName,
                'balance' => $balance,
                'type' => null,
                'subOperator' => null,
                'balanceTimestamp' => $currentTimeUtc,
                'lastUpdateDate' => $currentTimeUtc,
                'additionalFields' => null,
                'errorMessage' => null,
                'isError' => false
            ],
            'errors' => null
        ];
        return $this->reponseHeader($request,$responseData);
    }

    /**
     * 获取玩家余额
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getBalance(Request $request)
    {
        $data = $request->all();
        Util::WriteLog('luckystreak_validate', [$data,$request->header()]);

        // 验证请求的真实性
        if (!$this->verifyRequest($request)) {
            return response()->json([
                'errors' => [
                    ['code' => 'AUTH_001', 'message' => 'Unauthorized request']
                ]
            ], 401);
        }

        $data=$data['data'];
        $username = $data['username'] ?? null;
        if (!$username) {
            return response()->json([
                'errors' => [
                    ['code' => 'AUTH_002', 'message' => 'Username is required']
                ]
            ], 400);
        }
        if(!ServerService::IsLocalUser($username)) {
             $data=$this->luckyStreakService->callSubApi($username, $request);
            return $this->reponseHeader($request,$data);
        }
        // 获取用户信息
        $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $username);
        if (!$user) {
            return response()->json([
                'errors' => [
                    ['code' => 'AUTH_003', 'message' => 'Player not found']
                ]
            ], 404);
        }

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

        // 准备响应数据
        $responseData = [
            'data' => [
                'errorCode' => 0,
                'balance' => $balance,
                'balanceTimestamp' => gmdate('Y-m-d\TH:i:s.u\Z'),
                'currency' => $this->currency,
                'refTransactionId' => $data['transactionRequestId'] ?? null,
            ]
        ];

        return $this->reponseHeader($request,$responseData);
    }

    /**
     * 处理资金移动请求（投注和赢取）
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function moveFunds(Request $request)
    {
        $data = $request->all();
        Util::WriteLog('luckystreak_validate', $data);

        // 验证请求的真实性
        if (!$this->verifyRequest($request)) {
            return response()->json([
                'errors' => [
                    ['code' => 'AUTH_001', 'message' => 'Unauthorized request']
                ]
            ], 401);
        }

        $data=$data['data'];

        // 获取请求参数
        $username = $data['username'] ?? null;

        if(!ServerService::IsLocalUser($username)) {
             $data=$this->luckyStreakService->callSubApi($username, $request);
            return $this->reponseHeader($request,$data);
        }
        // 验证请求的真实性
        if ($data['operatorId']!=$this->operatorId||$data['currency']!=$this->currency) {
            return response()->json([
                'errors' => [
                    ['code' => 'AUTH_001', 'message' => 'Unauthorized request']
                ]
            ], 401);
        }
        $amount = isset($data['amount']) ? floatval($data['amount']) : 0;
        $transactionRequestId = $data['transactionRequestId'] ?? null;
        $direction = $data['direction'] ?? null; // Debit(投注) 或 Credit(赢取)
        $eventType = $data['eventType'] ?? null; // Bet, Win, Loss 等
        $gameId = $data['gameId'] ?? null;
        $gameType = $data['gameType'] ?? null;
        $roundId = $data['roundId'] ?? null;
        $eventId = $data['eventId'] ?? null;

        // 验证必须的参数
        if (!$username || !$transactionRequestId || !$direction || $amount === 0) {
            return response()->json([
                'errors' => [
                    ['code' => 'REQ_001', 'message' => 'Missing required parameters']
                ]
            ], 400);
        }

        // 获取用户信息
        $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $username);
        if (!$user) {
            return response()->json([
                'errors' => [
                    ['code' => 'AUTH_003', 'message' => 'Player not found']
                ]
            ], 404);
        }

        $userId = $user->UserID;

        // 检查是否已经处理过这个交易
        $transactionKey = 'luckystreak_tx_' . $transactionRequestId;
        if (Redis::exists($transactionKey)) {
            // 交易已处理，返回上次的结果
            $previousResult = json_decode(Redis::get($transactionKey), true);

            // 生成响应对象，添加Hawk头
            return $this->reponseHeader($request,$previousResult);
        }

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

        // 处理不同方向的资金移动
        if ($direction === 'Debit') {
            // 检查余额是否足够
            if ($currentBalance < $amountInCents) {
                $errorResponse = [
                    'errors' => [
                        ['code' => 'ERR-FUND-001', 'message' => 'Insufficient funds']
                    ]
                ];

                return $this->reponseHeader($request,$errorResponse,400);

            }

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

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

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

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

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

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

            // 原始下注金额，如果有的话
            $originalBetKey = 'luckystreak_bet_amount_' . $eventId;
            $originalBet = Redis::exists($originalBetKey) ? intval(Redis::get($originalBetKey)) : 0;

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

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

            // 更新当前余额
            $currentBalance += $amountInCents;
        } else {
            $errorResponse = [
                'errors' => [
                    ['code' => 'DIR_001', 'message' => 'Invalid direction']
                ]
            ];

            return $this->reponseHeader($request,$errorResponse,400);
        }

        // 构造成功响应
        $responseData = [
            'data' => [
                'refTransactionId' => $transactionRequestId,
                'balanceTimestamp' => gmdate('Y-m-d\TH:i:s.u\Z'),
                'balance' => $currentBalance/NumConfig::NUM_VALUE,
                'currency' => $this->currency
            ]
        ];

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

        return $this->reponseHeader($request,$responseData);
    }

    /**
     * 处理资金移动中止请求
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function abortMoveFunds(Request $request)
    {
        $data = $request->all();
        Util::WriteLog('luckystreak_validate', $data);

        // 验证请求的真实性
        if (!$this->verifyRequest($request)) {
            return response()->json([
                'errors' => [
                    ['code' => 'AUTH_001', 'message' => 'Unauthorized request']
                ]
            ], 401);
        }

        $data=$data['data'];
        // 获取请求参数
        $username = $data['username'] ?? null;

        if(!ServerService::IsLocalUser($username)) {
             $data=$this->luckyStreakService->callSubApi($username, $request);
            return $this->reponseHeader($request,$data);
        }

        $transactionRequestId = $data['transactionRequestId'] ?? null;
        $originalTransactionRequestId = $data['abortedTransactionRequestId'] ?? null;

        // 验证必须的参数
        if (!$username || !$transactionRequestId || !$originalTransactionRequestId) {
            $errorResponse = [
                'errors' => [
                    ['code' => 'REQ_001', 'message' => 'Missing required parameters']
                ]
            ];

            return $this->reponseHeader($request,$errorResponse,400);
        }

        // 获取用户信息
        $user = GlobalUserInfo::getGameUserInfo('GlobalUID', $username);
        if (!$user) {
            $errorResponse = [
                'errors' => [
                    ['code' => 'AUTH_003', 'message' => 'Player not found']
                ]
            ];

            return $this->reponseHeader($request,$errorResponse,404);
        }

        $userId = $user->UserID;

        // 检查是否已经处理过这个中止请求
        $abortKey = 'luckystreak_abort_' . $transactionRequestId;
        if (Redis::exists($abortKey)) {
            // 中止请求已处理，返回上次的结果
            $previousResult = json_decode(Redis::get($abortKey), true);

            return $this->reponseHeader($request,$previousResult);
        }

        // 获取原始交易金额
        $originalBetKey = 'luckystreak_bet_amount_' . $originalTransactionRequestId;
        if (!Redis::exists($originalBetKey)) {
            // 找不到原始交易，返回错误
            $errorResponse = [
                'errors' => [
                    ['code' => 'ABORT_001', 'message' => 'Original transaction not found']
                ]
            ];

            // 生成错误响应，添加Hawk头
            return $this->reponseHeader($request,$errorResponse,404);
        }
        $originalBetKey=Redis::get($originalBetKey);
        $originalBetKey=explode('_',$originalBetKey);
        $gameId = $originalBetKey[0];
        $originalAmount = intval($originalBetKey[1]);

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

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

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

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

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

        // 构造成功响应
        $responseData = [
            'data' => [
                'refTransactionId' => $transactionRequestId,
                'balance' => $currentBalance / NumConfig::NUM_VALUE,
                'currency' => $this->currency
            ]
        ];

        // 缓存中止请求结果
        Redis::set($abortKey, json_encode($responseData));
        Redis::expire($abortKey, 86400);

        return $this->reponseHeader($request,$responseData);
    }

    /**
     * 游戏启动页面
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function gameLunch(Request $request)
    {
        // 获取请求参数
        $gid = $request->input('gid');
        $user = $request->user();
        $userId = $user->UserID;
        $globalUID = $user->GlobalUID;

        // 检查用户渠道权限 (如果需要)
        if ($user->Channel != 99 && $user->Channel != 44) {
            http_response_code(404);
            exit();
        }

        // 找到游戏卡片
        GameCard::$enableStateCheck = false;

        // 记录游戏点击
        $gamecard = GameCard::where('gid', $gid)->where('brand', 'LuckyStreak')->first();
        $gamecard->increment('play_num', 1);
        LogGamecardClick::recordClick($gamecard->id, $userId);

        // 检查用户当前游戏状态
        $inGameId = OuroGameService::getUserInGame($userId, $globalUID);
        if ($inGameId != intval($gamecard->id)) {
            Util::WriteLog('24680game', compact('inGameId', 'gamecard', 'user'));
        }


        // 获取用户语言
        $lang = GlobalUserInfo::getLocale();
        $supportedLangs = ['en', 'da', 'de', 'es', 'fi', 'fr', 'it', 'pt', 'ru', 'zh','ar','ur'];
        if (!in_array($lang, $supportedLangs)) {
            $lang = 'en';
        }

        // 关闭加载动画
        echo "<script>
parent.postMessage({cmd:\"closeLoading\"},\"*\");
</script>";

        // 设置缓存控制头
        header("Cache-Control: no-cache, no-store, must-revalidate");
        header("Expires: 0");

        try {
            // 使用服务获取游戏启动URL
            $htmlContent = $this->luckyStreakService->getLaunchURLHTML($gid, $globalUID, $request->ip(), $lang);
            echo $htmlContent;
            exit();

        } catch (\Exception $e) {
            Util::WriteLog('luckystreak_error', $e->getMessage());
            echo "<script>alert('System error: " . $e->getMessage() . "');</script>";
            exit();
        }
    }

    /**
     * 获取游戏列表
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function gameList(Request $request)
    {
        try {
            // 使用服务获取游戏列表
            $result = $this->luckyStreakService->getGamesList();
            return response()->json($result);

        } catch (\Exception $e) {
            Util::WriteLog('luckystreak_error', $e->getMessage());
            return response()->json([
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * 获取游戏列表
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function jackpot(Request $request)
    {
        try {
            // 使用服务获取游戏列表
            $result = $this->luckyStreakService->getJackpot();
            return response()->json($result);

        } catch (\Exception $e) {
            Util::WriteLog('luckystreak_error', $e->getMessage());
            return response()->json([
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * 获取第三方游戏提供商游戏列表
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function providerGameList(Request $request)
    {
        dd($this->luckyStreakService->getCachedAuthToken());
        try {
            // 使用服务获取提供商游戏列表
            $result = $this->luckyStreakService->getProviderGamesList();
            return response()->json($result);

        } catch (\Exception $e) {
            Util::WriteLog('luckystreak_provider_error', $e->getMessage());
            return response()->json([
                'error' => $e->getMessage()
            ], 500);
        }
    }
}


