<?php

namespace App\Services;

use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Crypt;

class MailSecretEncrypter
{
    public function __construct(
        protected ?string $key = null,
    ) {
        $this->key = $this->key ?? config('mail_profiles.key');
        if (empty($this->key)) {
            // Fall back to app key for now
            $this->key = config('app.key');
        }
    }

    public function encrypt(string $plain): string
    {
        // For simplicity use Crypt facade (already uses APP_KEY) unless a dedicated key is set.
        if ($this->usingAppKey()) {
            return Crypt::encryptString($plain);
        }

        return $this->encryptWithCustomKey($plain);
    }

    public function decrypt(string $cipher): string
    {
        if ($this->usingAppKey()) {
            return Crypt::decryptString($cipher);
        }

        return $this->decryptWithCustomKey($cipher);
    }

    protected function usingAppKey(): bool
    {
        return $this->key === config('app.key');
    }

    protected function encryptWithCustomKey(string $plain): string
    {
        $iv = random_bytes(openssl_cipher_iv_length('AES-256-CBC'));
        $cipher = openssl_encrypt($plain, 'AES-256-CBC', $this->normalizedKey(), 0, $iv);

        return base64_encode($iv.'::'.$cipher);
    }

    protected function decryptWithCustomKey(string $payload): string
    {
        $decoded = base64_decode($payload, true);
        if ($decoded === false || ! str_contains($decoded, '::')) {
            throw new DecryptException('Invalid encrypted payload');
        }
        [$iv, $cipher] = explode('::', $decoded, 2);
        $plain = openssl_decrypt($cipher, 'AES-256-CBC', $this->normalizedKey(), 0, $iv);
        if ($plain === false) {
            throw new DecryptException('Cannot decrypt payload');
        }

        return $plain;
    }

    protected function normalizedKey(): string
    {
        $raw = base64_decode($this->key, true);

        return $raw !== false ? $raw : $this->key; // support base64 or plain
    }
}
