<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Services\SupportCenter;

use App\Support\DberpProductCode;
use App\Support\DberpProductVersion;
use Illuminate\Http\Request;

/**
 * 集中构建 Support Center Open Host 请求所需的 DBErp 系统上下文字段。
 */
final class SupportCenterRequestContextBuilder
{
    public function __construct(
        private readonly HostInstallationIdentityService $identityService,
        private readonly DberpProductVersion $productVersion,
    ) {}

    /**
     * @return array<string, mixed>
     */
    public function baseContext(?Request $request = null): array
    {
        $productCode = $this->productCode();
        $validationBaseUrl = $this->validationBaseUrl($request);

        return [
            'product_code' => $productCode,
            'product' => $productCode,
            'domain' => $this->resolveDomain($request),
            'current_domain' => $this->resolveCurrentDomain($request),
            'instance_id' => $this->identityService->instanceId(),
            'site_no' => $this->optionalConfigString('dberp.support_center.site_no'),
            'license_no' => $this->optionalConfigString('dberp.support_center.license_no'),
            'host_version' => $this->productVersion->displayVersion(),
            'validation_base_url' => $validationBaseUrl,
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public function siteOnboardingConfirmBody(string $taskNo): array
    {
        return array_merge($this->baseContext(), [
            'task_no' => $taskNo,
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    public function siteOnboardingStatusQuery(?string $taskNo = null): array
    {
        $context = $this->baseContext();

        if ($taskNo !== null && $taskNo !== '') {
            $context['task_no'] = $taskNo;
        }

        return $context;
    }

    /**
     * @return array<string, mixed>
     */
    public function sitePresenceBody(string $message = 'ok', ?string $siteNo = null): array
    {
        $productCode = $this->productCode();
        $siteNo = $siteNo ?? $this->optionalConfigString('dberp.support_center.site_no');

        return array_filter([
            'site_no' => $siteNo,
            'product_code' => $productCode,
            'product' => $productCode,
            'current_domain' => $this->resolveCurrentDomain(null),
            'host_version' => $this->productVersion->displayVersion(),
            'message' => $message,
        ], static fn (mixed $value): bool => $value !== null && $value !== '');
    }

    /**
     * @return array<string, mixed>
     */
    public function authorizationSyncBody(?string $siteNo = null, ?string $licenseNo = null): array
    {
        return array_filter([
            'product_code' => $this->productCode(),
            'current_domain' => $this->resolveCurrentDomain(null),
            'current_version' => $this->productVersion->displayVersion(),
            'site_no' => $siteNo ?? $this->optionalConfigString('dberp.support_center.site_no'),
            'license_no' => $licenseNo ?? $this->optionalConfigString('dberp.support_center.license_no'),
        ], static fn (mixed $value): bool => $value !== null && $value !== '');
    }

    /**
     * @return array<string, mixed>
     */
    public function systemUpdateCheckBody(
        ?string $releaseChannel = null,
        ?string $siteNo = null,
        ?string $licenseNo = null,
    ): array {
        $body = array_merge($this->baseContext(), [
            'product_code' => $this->productCode(),
            'current_version' => $this->productVersion->displayVersion(),
            // Open Host 契约要求 string；勿传 PHP int，否则支撑中心校验返回「请求参数不符合约定」
            'current_update_version' => (string) $this->productVersion->updateVersion(),
        ]);

        if ($siteNo !== null && trim($siteNo) !== '') {
            $body['site_no'] = trim($siteNo);
        }

        if ($licenseNo !== null && trim($licenseNo) !== '') {
            $body['license_no'] = trim($licenseNo);
        }

        if ($releaseChannel !== null && $releaseChannel !== '') {
            $body['release_channel'] = $releaseChannel;
        }

        return $body;
    }

    /**
     * @return array<string, mixed>
     */
    public function systemUpdateDownloadTokenBody(
        string $packageId,
        ?string $releaseChannel = null,
        ?string $siteNo = null,
        ?string $licenseNo = null,
        ?string $currentVersion = null,
        ?string $currentUpdateVersion = null,
    ): array {
        $body = array_filter([
            'product_code' => $this->productCode(),
            'current_domain' => $this->resolveCurrentDomain(null),
            'package_id' => trim($packageId),
            'current_version' => $currentVersion ?? $this->productVersion->displayVersion(),
            // 与 systemUpdateCheckBody 一致：Open Host 要求 string，供支撑中心按 build 号比对
            'current_update_version' => $currentUpdateVersion ?? (string) $this->productVersion->updateVersion(),
            'release_channel' => $releaseChannel,
            'site_no' => $siteNo,
            'license_no' => $licenseNo,
        ], static fn (mixed $value): bool => $value !== null && $value !== '');

        return $body;
    }

    /**
     * @return array<string, mixed>
     */
    public function pluginCatalogQuery(?string $siteNo = null, ?string $licenseNo = null): array
    {
        return $this->pluginOpenHostBaseQuery($siteNo, $licenseNo);
    }

    /**
     * @return array<string, mixed>
     */
    public function pluginDetailQuery(
        ?string $siteNo = null,
        ?string $licenseNo = null,
        ?string $pluginVersion = null,
    ): array {
        $query = $this->pluginOpenHostBaseQuery($siteNo, $licenseNo);

        if ($pluginVersion !== null && trim($pluginVersion) !== '') {
            $query['plugin_version'] = trim($pluginVersion);
        }

        return $query;
    }

    /**
     * @return array<string, mixed>
     */
    public function pluginUpdateCheckBody(
        string $pluginCode,
        ?string $installedVersion = null,
        ?string $siteNo = null,
        ?string $licenseNo = null,
    ): array {
        return array_merge($this->pluginOpenHostBaseQuery($siteNo, $licenseNo), [
            'plugin_code' => trim($pluginCode),
            'current_installed_version' => trim((string) $installedVersion),
            'host_version' => $this->productVersion->displayVersion(),
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    public function pluginClaimCheckBody(
        string $version,
        ?string $siteNo = null,
        ?string $licenseNo = null,
    ): array {
        return array_merge($this->pluginOpenHostBaseQuery($siteNo, $licenseNo), [
            'plugin_version' => trim($version),
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    public function pluginDownloadTokenBody(
        string $version,
        ?string $siteNo = null,
        ?string $licenseNo = null,
    ): array {
        return array_merge($this->pluginOpenHostBaseQuery($siteNo, $licenseNo), [
            'plugin_version' => trim($version),
        ]);
    }

    /**
     * @return array<string, string>
     */
    public function pluginDownloadQuery(?string $siteNo = null): array
    {
        return array_filter([
            'product_code' => $this->productCode(),
            'site_no' => $siteNo ?? $this->optionalConfigString('dberp.support_center.site_no'),
            'current_domain' => $this->resolveCurrentDomain(null),
        ], static fn (mixed $value): bool => is_string($value) && trim($value) !== '');
    }

    /**
     * Open Host 插件接口约定的宿主上下文字段（query / JSON body 共用）。
     *
     * @return array<string, string>
     */
    private function pluginOpenHostBaseQuery(?string $siteNo = null, ?string $licenseNo = null): array
    {
        return array_filter([
            'product_code' => $this->productCode(),
            'current_domain' => $this->resolveCurrentDomain(null),
            'current_version' => $this->productVersion->displayVersion(),
            'site_no' => $siteNo ?? $this->optionalConfigString('dberp.support_center.site_no'),
            'license_no' => $licenseNo ?? $this->optionalConfigString('dberp.support_center.license_no'),
        ], static fn (mixed $value): bool => is_string($value) && trim($value) !== '');
    }

    public function validationBaseUrl(?Request $request = null): string
    {
        $configured = config('dberp.support_center.validation_base_url');

        if (is_string($configured) && trim($configured) !== '') {
            return rtrim(trim($configured), '/');
        }

        return $this->deriveSafeBaseUrl($request);
    }

    private function productCode(): string
    {
        return DberpProductCode::forSupportCenter();
    }

    private function resolveDomain(?Request $request): string
    {
        $validationBaseUrl = config('dberp.support_center.validation_base_url');

        if (is_string($validationBaseUrl) && trim($validationBaseUrl) !== '') {
            $host = parse_url($validationBaseUrl, PHP_URL_HOST);

            if (is_string($host) && $host !== '') {
                return $host;
            }
        }

        return $this->resolveCurrentDomain($request);
    }

    private function resolveCurrentDomain(?Request $request): string
    {
        $request ??= $this->safeRequest();

        if ($request instanceof Request) {
            return $request->getHost();
        }

        $appUrl = config('app.url');

        if (is_string($appUrl) && trim($appUrl) !== '') {
            $host = parse_url($appUrl, PHP_URL_HOST);

            if (is_string($host) && $host !== '') {
                return $host;
            }
        }

        return 'localhost';
    }

    private function deriveSafeBaseUrl(?Request $request): string
    {
        $request ??= $this->safeRequest();

        if ($request instanceof Request) {
            return rtrim($request->getSchemeAndHttpHost(), '/');
        }

        $appUrl = config('app.url');

        if (is_string($appUrl) && trim($appUrl) !== '') {
            return rtrim(trim($appUrl), '/');
        }

        return 'http://localhost';
    }

    private function safeRequest(): ?Request
    {
        if (! app()->bound('request')) {
            return null;
        }

        $request = request();

        return $request instanceof Request ? $request : null;
    }

    private function optionalConfigString(string $key): ?string
    {
        $value = config($key);

        if (! is_string($value)) {
            return null;
        }

        $trimmed = trim($value);

        return $trimmed === '' ? null : $trimmed;
    }
}
