<?php

declare(strict_types=1);

namespace App\Services\SupportCenter;

use DBCore\Setting\Contracts\SettingManagerInterface;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Crypt;

/**
 * 站点实例敏感凭证持久化（Laravel 加密，不向前台或 well-known 暴露明文）。
 */
final class HostInstanceCredentialStore
{
    public const SETTING_KEY = 'dberp.host.installation.signing_secret';

    public function __construct(
        private readonly SettingManagerInterface $settingManager,
    ) {}

    public function hasSigningSecret(): bool
    {
        return $this->readSigningSecret() !== null;
    }

    public function storeSigningSecret(string $plainSecret): void
    {
        $encrypted = Crypt::encryptString($plainSecret);

        try {
            $result = $this->settingManager->set(self::SETTING_KEY, $encrypted);

            if ($result->isSuccess()) {
                return;
            }
        } catch (\Throwable) {
            // Setting 不可用时回退本地加密文件。
        }

        $this->writeFallbackFile($encrypted);
    }

    public function readSigningSecret(): ?string
    {
        $encrypted = $this->readEncryptedPayload();

        if ($encrypted === null) {
            return null;
        }

        try {
            $plain = Crypt::decryptString($encrypted);

            return trim($plain) !== '' ? $plain : null;
        } catch (DecryptException) {
            return null;
        }
    }

    private function readEncryptedPayload(): ?string
    {
        $fromSettings = $this->readEncryptedFromSettings();

        if ($fromSettings !== null) {
            return $fromSettings;
        }

        return $this->readFromFallbackFile();
    }

    private function readEncryptedFromSettings(): ?string
    {
        try {
            $value = $this->settingManager->get(self::SETTING_KEY);
        } catch (\Throwable) {
            return $this->readFromFallbackFile();
        }

        if (! is_string($value) || trim($value) === '') {
            return null;
        }

        return $value;
    }

    private function fallbackFilePath(): string
    {
        return storage_path('app/dberp/host-installation-signing-secret');
    }

    private function readFromFallbackFile(): ?string
    {
        $path = $this->fallbackFilePath();

        if (! is_file($path)) {
            return null;
        }

        $contents = trim((string) @file_get_contents($path));

        return $contents !== '' ? $contents : null;
    }

    private function writeFallbackFile(string $encryptedPayload): void
    {
        $directory = dirname($this->fallbackFilePath());

        if (! is_dir($directory)) {
            @mkdir($directory, 0755, true);
        }

        @file_put_contents($this->fallbackFilePath(), $encryptedPayload, LOCK_EX);
    }
}
