<?php

declare(strict_types=1);

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

namespace App\Console\Commands;

use Illuminate\Console\Command;
use RuntimeException;
use Tools\InstallerBuild\InstallPackageBuilder;
use Tools\Release\ConsoleReleasePackageBuildProgress;

final class BuildInstallPackageCommand extends Command
{
    protected $signature = 'dberp:build-install-package
                            {version : 安装包版本号，例如 3.0.0}
                            {--edition=web : 安装包版本：web 或 dbpanel}
                            {--dbcore-path= : DBCore 源码路径，默认 ../DBCore}
                            {--skip-frontend-build : 跳过 npm ci / npm run build}
                            {--format=zip : 包格式（zip 或 tar.gz）}
                            {--archiver=auto : 压缩后端 auto（优先 7-Zip）、7z、phar}
                            {--7z-path= : 7-Zip 目录或 7z.exe 路径，默认尝试 D:\\7-Zip}
                            {--clean-temp : 构建完成后删除临时 workspace}
                            {--force : 覆盖 dist 下该版本目录已有输出}
                            {--release-credentials= : 覆盖当前 edition 的 Open Host 凭证源 JSON（默认见 tools/dberp/）}';

    protected $description = '构建 DBErp 安装包（Web 或 DBPanel 首次安装部署包）';

    public function handle(InstallPackageBuilder $builder): int
    {
        $version = trim((string) $this->argument('version'));

        if ($version === '') {
            $this->error('version 不能为空。');

            return self::FAILURE;
        }

        $editionOption = trim((string) $this->option('edition'));
        $dbcorePath = trim((string) $this->option('dbcore-path'));
        $skipFrontendBuild = (bool) $this->option('skip-frontend-build');
        $cleanTemp = (bool) $this->option('clean-temp');
        $force = (bool) $this->option('force');
        $format = trim((string) $this->option('format'));
        $archiver = trim((string) $this->option('archiver'));
        $sevenZipPath = trim((string) $this->option('7z-path'));
        $releaseCredentials = trim((string) $this->option('release-credentials'));

        try {
            $edition = $builder->resolveEdition($editionOption);
        } catch (RuntimeException $exception) {
            $this->error($exception->getMessage());

            return self::FAILURE;
        }

        $progress = new ConsoleReleasePackageBuildProgress($this->output);

        $this->newLine();
        $this->line('Building DBErp install package...');
        $this->line('Version: '.$version);
        $this->line('Edition: '.$edition->id());

        try {
            $result = $builder->build(
                projectRoot: base_path(),
                version: $version,
                edition: $edition,
                dbcorePath: $dbcorePath !== '' ? $dbcorePath : null,
                skipFrontendBuild: $skipFrontendBuild,
                cleanTemp: $cleanTemp,
                force: $force,
                format: $format,
                archiver: $archiver,
                sevenZipPath: $sevenZipPath !== '' ? $sevenZipPath : null,
                progress: $progress,
                releaseCredentialsSourcePath: $releaseCredentials !== '' ? $releaseCredentials : null,
            );
        } catch (RuntimeException $exception) {
            $this->newLine();
            $this->error($exception->getMessage());

            return self::FAILURE;
        }

        $this->newLine();
        $this->line('DBErp install package built successfully.');
        $this->line('Package format: '.$result['package_format']);
        $this->line('Package archiver: '.$result['package_archiver']);
        $this->line('Output directory: '.$this->relativePath($result['output_directory']));
        $this->line('Package path: '.$this->relativePath($result['package_path']));
        $this->line('Package size (bytes): '.$result['package_size_bytes']);

        if (! $cleanTemp) {
            $this->line('Build workspace retained: '.$this->relativePath($result['workspace']));
        }

        return self::SUCCESS;
    }

    private function relativePath(string $absolutePath): string
    {
        $base = rtrim(base_path(), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;

        if (str_starts_with($absolutePath, $base)) {
            return str_replace('\\', '/', substr($absolutePath, strlen($base)));
        }

        return str_replace('\\', '/', $absolutePath);
    }
}
