<?php

namespace Modules\Setting\Services\Setting;

use Modules\Currency\Currency;
use Modules\Currency\Enums\ExchangeService;
use Modules\Setting\Enums\SettingSection;
use Modules\Setting\Models\Setting;
use Modules\Setting\Repositories\SettingRepository;
use Modules\Support\Country;
use Modules\Support\DateFormats;
use Modules\Support\Enums\Day;
use Modules\Support\Enums\FilesystemDisk;
use Modules\Support\Enums\Frequency;
use Modules\Support\Enums\MailEncryptionProtocol;
use Modules\Support\Enums\Mailer;
use Modules\Support\Locale;
use Modules\Support\RTLDetector;
use Modules\Support\TimeFormats;
use Modules\Support\TimeZone;

class SettingService implements SettingServiceInterface
{
    /** @inheritDoc */
    public function label(): string
    {
        return __("setting::settings.settings.setting");
    }

    /** @inheritDoc */
    public function getModel(): Setting
    {
        return new ($this->model());
    }

    /** @inheritDoc */
    public function model(): string
    {
        return Setting::class;
    }

    /** @inheritDoc */
    public function getAppSettings(bool $refresh = false): array
    {
        if ($refresh) {
            $this->refreshSettingBinding();
        }

        return [
            "supported_locales" => supportedLocaleKeys(),
            "supported_languages" => supportedLanguages(),
            "locale" => setting("default_locale"),
            "fallback_locale" => fallbackLocale(),
            "is_rtl" => RTLDetector::detect(),
            "timezone" => setting("default_timezone"),
            "currency" => setting("default_currency"),
            "app_name" => setting("app_name"),
        ];
    }

    /** @inheritDoc */
    public function refreshSettingBinding(): void
    {
        app()->forgetInstance('setting');
        app()->singleton('setting', fn() => new SettingRepository(Setting::allCached()));
    }

    /** @inheritDoc */
    public function getSettings(SettingSection $section): array
    {
        $settings = setting()->all();


        return match ($section) {
            SettingSection::General => [
                "supported_countries" => $settings['supported_countries'],
                "default_country" => $settings['default_country'],
                "supported_locales" => $settings['supported_locales'],
                "default_locale" => $settings['default_locale'],
                "default_timezone" => $settings['default_timezone'],
                "default_date_format" => $settings['default_date_format'],
                "default_time_format" => $settings['default_time_format'],
                "start_of_week" => $settings['start_of_week'],
                "end_of_week" => $settings['end_of_week'],
            ],
            SettingSection::Application => [
                "app_name" => unserialize(Setting::where('key', 'app_name')->first()->getRawOriginal('payload'))
            ],
            SettingSection::Currency => [
                "supported_currencies" => $settings['supported_currencies'],
                "default_currency" => $settings['default_currency'],
                "currency_rate_exchange_service" => $settings['currency_rate_exchange_service'] ?? null,
                "forge_api_key" => $settings['forge_api_key'] ?? null,
                "fixer_access_key" => $settings['fixer_access_key'] ?? null,
                "currency_data_feed_api_key" => $settings['currency_data_feed_api_key'] ?? null,
                "auto_refresh_currency_rates" => $settings['auto_refresh_currency_rates'] ?? false,
                "auto_refresh_currency_rate_frequency" => $settings['auto_refresh_currency_rate_frequency'] ?? null,
            ],
            SettingSection::Mail => [
                "mail_mailer" => $settings['mail_mailer'] ?? Mailer::Smtp->value,
                "mail_from_address" => $settings['mail_from_address'] ?? config('mail.from.address'),
                "mail_from_name" => $settings['mail_from_name'] ?? $settings['app_name'],
                "mail_host" => $settings['mail_host'] ?? config('mail.mailers.smtp.host'),
                "mail_port" => $settings['mail_port'] ?? config('mail.mailers.smtp.port'),
                "mail_username" => $settings['mail_username'] ?? config('mail.mailers.smtp.username'),
                "mail_password" => $settings['mail_password'] ?? config('mail.mailers.smtp.password'),
                "mail_encryption" => $settings['mail_encryption'] ?? config('mail.mailers.smtp.encryption'),
            ],
            SettingSection::Filesystem => [
                "default_filesystem_disk" => $settings['default_filesystem_disk'],
                "filesystem_s3_use_path_style_endpoint" => $settings['filesystem_s3_use_path_style_endpoint'] ?? null,
                "filesystem_s3_url" => $settings['filesystem_s3_url'] ?? null,
                "filesystem_s3_endpoint" => $settings['filesystem_s3_endpoint'] ?? null,
                "filesystem_s3_region" => $settings['filesystem_s3_region'] ?? null,
                "filesystem_s3_bucket" => $settings['filesystem_s3_bucket'] ?? null,
                "encryptable" => [
                    "filesystem_s3_key" => $settings['filesystem_s3_key'] ?? null,
                    "filesystem_s3_secret" => $settings['filesystem_s3_secret'] ?? null,
                ]
            ],
        };
    }

    /** @inheritDoc */
    public function getMeta(SettingSection $section): array
    {
        return match ($section) {
            SettingSection::General => [
                "countries" => Country::toList(),
                "locales" => Locale::toList(),
                "timezones" => TimeZone::toList(),
                "date_formats" => DateFormats::toList(),
                "time_formats" => TimeFormats::toList(),
                "days" => Day::toArrayTrans()
            ],
            SettingSection::Currency => [
                "currencies" => Currency::toList(),
                "frequencies" => Frequency::toArrayTrans(),
                "exchange_services" => ExchangeService::toArrayTrans()
            ],
            SettingSection::Mail => [
                "mailers" => Mailer::toArrayTrans(),
                "encryption_protocols" => MailEncryptionProtocol::toArrayTrans(),
            ],
            SettingSection::Filesystem => [
                "disks" => FilesystemDisk::toArrayTrans(),
            ],
            default => []
        };
    }

    /** @inheritDoc */
    public function update(SettingSection $section, array $data): void
    {
        setting($data);
    }
}
