namespace Application.Abstractions.Crypto;

/// <summary>
/// Config 문자열 컬럼에 키 버전을 함께 담아 암호화 저장하는 헬퍼.
/// 별도 KeyVersion 컬럼이 없는 Config 특성상 "enc:v{version}:{Base64}" 자체 포맷을 사용한다.
/// 접두사가 없는 값은 레거시 평문으로 간주해 그대로 반환한다 (하위호환).
/// </summary>
public static class EncryptedConfigValue
{
    private const string Prefix = "enc:v";

    /// <summary>평문을 현재 키 버전으로 암호화해 버전 접두사 포맷으로 반환</summary>
    public static string Protect(IFieldEncryptor encryptor, string plaintext)
    {
        ArgumentNullException.ThrowIfNull(encryptor);

        return $"{Prefix}{encryptor.CurrentKeyVersion}:{encryptor.Encrypt(plaintext)}";
    }

    /// <summary>버전 접두사 포맷 여부</summary>
    public static bool IsProtected(string? value)
    {
        return value is not null && value.StartsWith(Prefix, StringComparison.Ordinal);
    }

    /// <summary>버전 접두사 포맷이면 복호화, 아니면(레거시 평문) 그대로 반환</summary>
    public static string Unprotect(IFieldEncryptor encryptor, string value)
    {
        ArgumentNullException.ThrowIfNull(encryptor);
        ArgumentNullException.ThrowIfNull(value);

        if (!IsProtected(value))
        {
            return value;
        }

        var rest = value.AsSpan(Prefix.Length);
        var separator = rest.IndexOf(':');

        if (separator <= 0 || !int.TryParse(rest[..separator], out var version))
        {
            throw new InvalidOperationException("암호화된 설정 값의 키 버전 형식이 올바르지 않습니다.");
        }

        return encryptor.Decrypt(rest[(separator + 1)..].ToString(), version);
    }
}