<?php
namespace Base\Service;

use Base\Model\PromoteModel;
use Base\Model\ApplyModel;
use Base\Facade\Request;

class ApplyService {

    const ENCRYPT_METHOD = 'AES-256-ECB';
    const ENCRYPT_KEY = 'WmtX1@#Landing&Download2048';
    const ENCRYPT_TYPE_DOWNLOAD = 1;
    const ENCRYPT_TYPE_LANDING_PAGE = 2;

    public static $enableStatusList = [
        '-1' => '打包失败',
        '0' => '打包失败',
        '1' => '打包成功 ',
        '2' => '准备打包 ',
        '3' => '打包中',
    ];

    public function __construct()
    {
    }

    public function checkApplyStatus($apply)
    {
        if ($apply['status'] == 0) {
            return [
                'status' => false,
                'message' => '游戏未审核',
            ];
        }
        if ($apply['offline_status'] == 1) {
            return [
                'status' => false,
                'message' => '游戏已下架',
            ];
        }
        if ($apply['enable_status'] != 1) {
            return [
                'status' => false,
                'message' => self::$enableStatusList[$apply['enable_status']] ?? '未知错误',
            ];
        }
        return [
            'status' => true,
            'message' => '游戏打包成功',
        ];
    }

    public function offlineGame($game, $promote = null)
    {
        $conditions = ['game_id' => $game['id']];
        if ($promote) {
            $promoteService = new PromoteService();
            $children = $promoteService->getAllChildren($promote, 0, ['id']);
            $promoteIds = [$promote['id']];
            $promoteIds = array_merge($promoteIds, array_column($children, 'id'));
            $conditions['promote_id'] = ['in', $promoteIds];
        }
        M('apply', 'tab_')->where($conditions)->save(['offline_status' => 1]);
    }

    public function updateAfterPack($apply, $packageUrl, $plistUrl)
    {
        $data = [];
        $data['id'] = $apply['id'];
        $data['pack_url'] = $packageUrl;
        $data['dow_url'] = '/index.php?s=/Home/Down/down_file/game_id/' . $apply['game_id'] . '/promote_id/' . $apply['promote_id'];
        $data['dow_status'] = 1;
        $data['enable_status'] = 1;
        $data['dispose_id'] = 0;
        $data['dispose_time'] = time();
        $data['plist_url'] = $plistUrl;
        return M('Apply', 'tab_')->save($data);
    }

    public function getDownloadUrl($apply)
    {
        $host = $this->getDownloadDomain();
        $host = $host ? $host : Request::getHost();
        $code = $this->encodeApplyCode($apply, self::ENCRYPT_TYPE_DOWNLOAD);
        return $host . '/index.php?s=/Home/Package/download/code/' . $code;
    }

    public function getLandingPageUrl($apply)
    {
        $host = $this->getDownloadDomain();
        $host = $host ? $host : Request::getHost();
        $code = $this->encodeApplyCode($apply, self::ENCRYPT_TYPE_LANDING_PAGE);
        return $host . '/index.php?s=/Home/Home/landingPage/code/' . $code;
    }

    public function getDownloadDomain()
    {
        if (C('APP_ENV') == 'prod') {
            if (empty(C('DOMAIN_DOWNLOAD_PROD'))) {
                return C('DOMAIN_DOWNLOAD');
            }
            return C('DOMAIN_DOWNLOAD_PROD');
        } else {
            return C('DOMAIN_DOWNLOAD');
        }
    }

    public function getApplyData($apply, $type, $version)
    {
        $data = null;
        $expiresIn = 0;
        if ($version == 1) {
            $data = [
                'promote_id' => $apply['promote_id'],
                'game_id' => $apply['game_id'],
                'expires_in' => $expiresIn,
                'created_at' => date('Y-m-d H:i:s'),
                'type' => $type
            ];
            $data = json_encode($data);
        } elseif ($version == 2) {
            $data = [
                $apply['promote_id'],
                $apply['game_id'],
                $expiresIn,
                time(),
                $type
            ];
            $data = implode('|', $data);
        }
        return $data;
    }

    public function encodeApplyCode($apply, $type, $version = 2)
    {
        $data = $this->getApplyData($apply, $type, $version);
        return base64_encode(openssl_encrypt($data, self::ENCRYPT_METHOD, self::ENCRYPT_KEY));
    }

    public function decodeApplyCode($code)
    {
        $decryptStr = openssl_decrypt(base64_decode($code), self::ENCRYPT_METHOD, self::ENCRYPT_KEY);
        $result = json_decode($decryptStr, true);
        if (is_null($result)) {
            $items = explode('|', $decryptStr);
            if (count($items) != 5) {
                return null;
            }
            return [
                'promote_id' => $items[0],
                'game_id' => $items[1],
                'expires_in' => $items[2],
                'created_at' => date('Y-m-d H:i:s', $items[3]),
                'type' => $items[4],
            ];
        }
        return $result;
    }

    public function checkApplyCode($data, $type)
    {
        if (
            !isset($data['promote_id']) ||
            !isset($data['game_id']) ||
            !isset($data['expires_in']) ||
            !isset($data['created_at']) ||
            !isset($data['type'])
        ) {
            return [
                'status' => false,
                'message' => '参数异常',
            ];
        }
        if ($data['type'] != $type) {
            return [
                'status' => false,
                'message' => '参数异常',
            ];
        }
        if ($data['expires_in'] > 0 && time() > (strtotime($data['created_at']) + $data['expires_in'])) {
            return [
                'status' => false,
                'message' => '链接已过期',
            ];
        }
        return [
            'status' => true,
            'message' => '验证成功',
        ];
    }

    public  function getPageIdentifier($url)
    {
        $params = $this->getUrlParams($url);
        $sValue = isset($params['s']) ? $params['s'] : '';
        $code = $this->getSParam($sValue, 'code');
        if ($code === null) {
            $gid = $this->getSParam($sValue, 'game_id');
            $pid = $this->getSParam($sValue, 'promote_id');
            $type = 0;
            if ($gid && $pid) {
                $type = 1;
            } else {
                $gid = $this->getSParam($sValue, 'gid');
                $pid = $this->getSParam($sValue, 'pid');
                $type = 2;
            }
            if ($gid === null || $gid === null) {
                return null;
            } else {
                return [
                    'game_id' => $gid,
                    'promote_id' => $pid,
                    'type' => $type,
                ];
            }
        }
        return ['code' => $code];
    }

    public function getSParam($sValue, $name)
    {
        $sValue = ltrim($sValue, '/');
        $sValue = rtrim($sValue, '.html');
        $rows = explode('/', $sValue);
        $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 getUrlParams($url)
    {
        $items = parse_url($url);
        $queryParts = explode('&', $items['query']);
        parse_str($items['query'], $params);
        return $params;
    }

    public function checkSociatyPerm($promote, $game)
    {
        if ($game['apply_auth'] == 1) {
            return true;
        }
        $promoteService = new PromoteService();
        $topPromote = $promoteService->getTopPromote($promote);
        $record = M('sociaty_games', 'tab_')->where(['game_id' => $game['id'], 'promote_id' => $topPromote['id']])->find();
        if ($record['status'] == 1) {
            return true;
        } else {
            return false;
        }
    }

    public function getSociatyGameIds($promote)
    {
        $promoteService = new PromoteService();
        $topPromote = $promoteService->getTopPromote($promote);
        $tempIds = M('sociaty_games', 'tab_')->where(['promote_id' => $topPromote['id']])->getField('game_id', true);
        $tempIds = $tempIds ?? [];
        $ids = M('game', 'tab_')->where(['apply_auth' => 1])->getField('id', true);
        $ids = $ids ?? [];
        return array_merge($tempIds, $ids);
    }
}