<?php

namespace App\Services\Mail;

use App\Models\Setting;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Crypt;

class MailSettingsManager
{
    /**
     * @return array<string, mixed>
     */
    public function all(): array
    {
        return Setting::where('group', 'mail')
            ->get()
            ->mapWithKeys(function (Setting $setting) {
                $value = $setting->value;

                if ($setting->is_encrypted && $value !== null && $value !== '') {
                    try {
                        $value = Crypt::decryptString($value);
                    } catch (\Throwable) {
                        $value = null;
                    }
                }

                return [$setting->key => $value];
            })
            ->all();
    }

    /**
     * @param array<string, mixed> $data
     */
    public function save(array $data): void
    {
        $encryptedKeys = ['smtp_password'];

        foreach ($data as $key => $value) {
            if ($key === 'smtp_password' && ($value === null || $value === '')) {
                continue;
            }

            $isEncrypted = in_array($key, $encryptedKeys, true);
            $storedValue = $isEncrypted && $value !== null && $value !== ''
                ? Crypt::encryptString((string) $value)
                : $value;

            Setting::updateOrCreate(
                ['group' => 'mail', 'key' => $key],
                ['value' => $storedValue, 'is_encrypted' => $isEncrypted]
            );
        }
    }

    public function apply(): void
    {
        $settings = $this->all();

        $encryption = Arr::get($settings, 'smtp_encryption', 'tls');
        if ($encryption === 'none' || $encryption === '') {
            $encryption = null;
        }

        config([
            'mail.default' => 'smtp',
            'mail.mailers.smtp.transport' => 'smtp',
            'mail.mailers.smtp.host' => Arr::get($settings, 'smtp_host', config('mail.mailers.smtp.host')),
            'mail.mailers.smtp.port' => (int) Arr::get($settings, 'smtp_port', config('mail.mailers.smtp.port', 587)),
            'mail.mailers.smtp.encryption' => $encryption,
            'mail.mailers.smtp.username' => Arr::get($settings, 'smtp_username'),
            'mail.mailers.smtp.password' => Arr::get($settings, 'smtp_password'),
            'mail.from.address' => Arr::get($settings, 'from_email', config('mail.from.address')),
            'mail.from.name' => Arr::get($settings, 'from_name', config('mail.from.name')),
        ]);
    }

    public function hasSmtpConfig(): bool
    {
        $settings = $this->all();

        return filled($settings['smtp_host'] ?? null)
            && filled($settings['smtp_port'] ?? null)
            && filled($settings['from_email'] ?? null);
    }
}
