<?php

namespace App\Libraries;

use App\Libraries\Contracts\CredentialStoreInterface;
use App\Models\Control\PlatformSettingModel;
use CodeIgniter\Encryption\EncrypterInterface;

/**
 * Typed read/write access to the control DB's `platform_settings` table —
 * this is where the PLATFORM's own credentials live, most importantly its
 * Hubtel Checkout account for collecting subscription payments from
 * hotels. This is a distinct Hubtel merchant context from any tenant's
 * own App\Libraries\Settings (that's the hotel's account for collecting
 * from ITS guests) — same "never hardcoded, never in .env, DB-stored"
 * rule, just one level up. Encryption behavior (any key containing
 * "secret" or "token" is encrypted at rest) is identical to Settings —
 * see that class for the full reasoning — factored out only where the
 * storage model differs (control DB vs tenant DB).
 */
class PlatformSettings implements CredentialStoreInterface
{
    private const SENSITIVE_PATTERN = '/secret|token/i';

    public function __construct(
        private readonly PlatformSettingModel $model,
        private readonly EncrypterInterface $encrypter,
    ) {
    }

    public function get(string $key, ?string $default = null): ?string
    {
        $raw = $this->model->getValue($key);

        if ($raw === null) {
            return $default;
        }

        return $this->isSensitive($key) ? $this->decrypt($raw) : $raw;
    }

    public function set(string $key, ?string $value): void
    {
        if ($value === null || $value === '') {
            $this->model->setValue($key, null);

            return;
        }

        $this->model->setValue($key, $this->isSensitive($key) ? $this->encrypt($value) : $value);
    }

    /** @return array<string, string> */
    public function getGroupMasked(string $prefix): array
    {
        $rows   = $this->model->like('key', $prefix, 'after')->findAll();
        $result = [];

        foreach ($rows as $row) {
            $result[$row->key] = $this->isSensitive($row->key) && $row->value !== null
                ? str_repeat('•', 12)
                : $row->value;
        }

        return $result;
    }

    public function isConfigured(string $key): bool
    {
        return ($this->model->getValue($key) ?? '') !== '';
    }

    private function isSensitive(string $key): bool
    {
        return (bool) preg_match(self::SENSITIVE_PATTERN, $key);
    }

    private function encrypt(string $value): string
    {
        return base64_encode($this->encrypter->encrypt($value));
    }

    private function decrypt(string $stored): ?string
    {
        $decoded = base64_decode($stored, true);

        if ($decoded === false) {
            return null;
        }

        try {
            return $this->encrypter->decrypt($decoded);
        } catch (\Exception $e) {
            log_message('error', 'PlatformSettings: failed to decrypt value — ' . $e->getMessage());

            return null;
        }
    }
}
