<?php

declare(strict_types=1);

namespace App\Exceptions\SupportCenter;

use RuntimeException;

/**
 * 更新文件替换、删除或 vendor 处理失败（不含密钥与 .env 内容）。
 */
final class HostSystemUpdateFileExecutionException extends RuntimeException
{
    public function __construct(
        private readonly string $userFacingMessage,
        private readonly string $errorCode,
        private readonly bool $partialChangesApplied = false,
        ?\Throwable $previous = null,
    ) {
        parent::__construct($userFacingMessage, 0, $previous);
    }

    public function userFacingMessage(): string
    {
        return $this->userFacingMessage;
    }

    public function errorCode(): string
    {
        return $this->errorCode;
    }

    public function partialChangesApplied(): bool
    {
        return $this->partialChangesApplied;
    }

    public static function prerequisitesNotMet(string $reason): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.prerequisites_not_met', ['reason' => $reason]),
            errorCode: 'file_execution_prerequisites_not_met',
        );
    }

    public static function stagingMissing(): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.staging_missing'),
            errorCode: 'file_execution_staging_missing',
        );
    }

    public static function backupNotCompleted(): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.backup_not_completed'),
            errorCode: 'file_execution_backup_not_completed',
        );
    }

    public static function stagedSourceMissing(string $path): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.staged_source_missing', ['path' => $path]),
            errorCode: 'file_execution_staged_source_missing',
        );
    }

    public static function checksumMismatch(string $path, bool $partialChangesApplied = false): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.checksum_mismatch', ['path' => $path]),
            errorCode: 'file_execution_checksum_mismatch',
            partialChangesApplied: $partialChangesApplied,
        );
    }

    public static function copyFailed(string $path, bool $partialChangesApplied = false): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.copy_failed', ['path' => $path]),
            errorCode: 'file_execution_copy_failed',
            partialChangesApplied: $partialChangesApplied,
        );
    }

    public static function deleteNotBackedUp(string $path): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.delete_not_backed_up', ['path' => $path]),
            errorCode: 'file_execution_delete_not_backed_up',
        );
    }

    public static function deleteFailed(string $path, bool $partialChangesApplied = false): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.delete_failed', ['path' => $path]),
            errorCode: 'file_execution_delete_failed',
            partialChangesApplied: $partialChangesApplied,
        );
    }

    public static function vendorFileInvalid(string $path): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.vendor_file_invalid', ['path' => $path]),
            errorCode: 'file_execution_vendor_file_invalid',
        );
    }

    public static function vendorCopyFailed(string $path, bool $partialChangesApplied = false): self
    {
        return new self(
            userFacingMessage: (string) __('dberp.system_update.file_execution.vendor_copy_failed', ['path' => $path]),
            errorCode: 'file_execution_vendor_copy_failed',
            partialChangesApplied: $partialChangesApplied,
        );
    }
}
