<?php
// +----------------------------------------------------------------------
// | onezan-admin 快速开发的管理平台
// +----------------------------------------------------------------------
// | 官方网址：https://www.onezan.cn
// +----------------------------------------------------------------------
// | onezan团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: 543885307@qq.com
// +----------------------------------------------------------------------
namespace app\service\domain\upgrade;

use Core\service\BaseCoreService;
use GuzzleHttp\Client;
use think\facade\Log;

/**
 * 升级下载器
 * @package app\service\domain\upgrade
 */
class UpgradeDownloader extends BaseCoreService
{
    private UpgradeTokenService $tokenService;

    /**
     * Constructor
     * @param \think\App $app
     * @param UpgradeTokenService $tokenService
     */
    public function __construct(\think\App $app, UpgradeTokenService $tokenService)
    {
        parent::__construct($app);
        $this->tokenService = $tokenService;
    }

    /**
     * 下载升级包
     * @param string $type framework|application
     * @param string $version 版本号
     * @param string $appCode type=application
     * @param string $code ?
     * @return array{file_path:string, hash:string, size:int}
     */
    public function download(string $type, string $version, string $appCode = '', string $code = ''): array
    {
        $config = $this->tokenService->remoteConfig();
        $apiUrl = $config['api_url'];

        if ($apiUrl === '') {
            throw new \RuntimeException('');
        }

        $tempDir = $this->app->getRuntimePath() . 'upgrade' . DIRECTORY_SEPARATOR;
        if (!is_dir($tempDir)) {
            mkdir($tempDir, 0755, true);
        }

        $tempFile = $tempDir . $type . '_' . $version . '.zip';

        //
        $domain = $_SERVER['HTTP_HOST'] ?? 'localhost';
        $sign = md5($code . $domain . $config['secret']);

        $params = [
            'action' => 'download',
            'code' => $code,
            'type' => $type,
            'version' => $version,
            'industry_code' => $appCode,
            'domain' => $domain,
            'sign' => $sign,
        ];

        $url = rtrim($apiUrl, '/') . '?' . http_build_query($params);

        $client = new Client(['timeout' => 300]);
        $response = $client->get($url, [
            'sink' => $tempFile,
            'progress' => function ($downloadTotal, $downloaded) {
            },
        ]);

        if ($response->getStatusCode() !== 200) {
            @unlink($tempFile);
            throw new \RuntimeException('TTP: ' . $response->getStatusCode());
        }

        $remoteHash = $response->getHeaderLine('X-Upgrade-Hash');
        $localHash = md5_file($tempFile);

        if ($remoteHash && $localHash !== $remoteHash) {
            @unlink($tempFile);
            throw new \RuntimeException('Hash mismatch');
        }

        $fileSize = filesize($tempFile);

        return [
            'file_path' => $tempFile,
            'hash' => $localHash,
            'size' => $fileSize,
        ];
    }

    /**
     * 获取服务器的IP地址
     * @return string IP地址
     */
    private function getServerIp(): string
    {
        return $_SERVER['SERVER_ADDR'] ?? '0.0.0.0';
    }
}