<?php
declare(strict_types=1);

namespace App\Models;

use Throwable;

class Setting extends BaseModel
{
    protected string $table = 'settings';

    private const SHIELD_DEFAULTS = [
        'shield_enabled' => 1,
        'shield_link_scan_enabled' => 1,
        'shield_comment_scan_enabled' => 1,
        'shield_message_scan_enabled' => 1,
        'shield_content_scan_enabled' => 1,
        'shield_review_threshold' => 31,
        'shield_block_threshold' => 61,
        'shield_auto_pending' => 1,
        'shield_auto_block' => 1,
    ];

    private const FINANCIAL_DEFAULTS = [
        'site_commission_rate' => '0.10',
        'commission_rate' => '0.10',
        'tax_rate' => '0.20',
        'provider_fee_rate' => '0',
        'provider_fee_fixed' => '0',
        'minimum_withdrawal_amount' => '100',
        'payout_delay_minutes' => '20',
        'balance_hold_days' => '0',
        'currency' => 'TRY',
        'default_currency' => 'TRY',
        'tax_calc_type' => 'gross',
        'payout_mode' => 'manual',
    ];

    private const SITE_DEFAULTS = [
        'site_name' => 'Zalorox',
        'site_description' => 'Modlar, muzikler ve creator abonelikleri icin Zalorox platformu.',
        'site_logo' => '/assets/img/logo.gif',
        'music_logo' => '/assets/img/logo-music.png',
        'studio_logo' => '/assets/img/logo-studio.png',
        'zpanel_logo' => '/assets/img/logo-zpanel.png',
        'favicon' => '/assets/img/Fav-İcon.png',
        'logo_path' => '/assets/img/logo.gif',
        'zpanel_logo_path' => '/assets/img/logo-zpanel.png',
        'default_language' => 'tr',
        'default_theme' => 'system',
        'header_menu_enabled' => '1',
        'maintenance_mode' => '0',
        'registrations_enabled' => '1',
        'cookie_text' => 'Zalorox deneyimini iyilestirmek icin gerekli cerezleri kullanir.',
        'footer_description' => 'Modlar, muzikler ve creator abonelikleri icin Zalorox platformu.',
        'footer_copyright' => 'Zalorox Network',
        'social_x' => '',
        'social_youtube' => '',
        'social_instagram' => '',
        'social_discord' => '',
    ];

    public static function shieldDefaults(): array
    {
        return self::SHIELD_DEFAULTS;
    }

    public static function financialDefaults(): array
    {
        return self::FINANCIAL_DEFAULTS;
    }

    public static function siteDefaults(): array
    {
        return self::SITE_DEFAULTS;
    }

    public function getByKey(string $key, mixed $default = null): mixed
    {
        $statement = $this->db()->prepare('SELECT setting_value FROM settings WHERE setting_key = :setting_key LIMIT 1');
        $statement->execute(['setting_key' => $key]);
        $row = $statement->fetch();

        return $row ? $row['setting_value'] : $default;
    }

    public function set(string $key, mixed $value, string $type = 'string', int $isPublic = 0): void
    {
        $statement = $this->db()->prepare(
            'INSERT INTO settings (setting_key, setting_value, type, is_public, created_at, updated_at)
             VALUES (:setting_key, :setting_value, :type, :is_public, NOW(), NOW())
             ON DUPLICATE KEY UPDATE
                setting_value = VALUES(setting_value),
                type = VALUES(type),
                is_public = VALUES(is_public),
                updated_at = NOW()'
        );
        $statement->execute([
            'setting_key' => $key,
            'setting_value' => (string) $value,
            'type' => $type,
            'is_public' => $isPublic,
        ]);
    }

    public function getShieldSettings(): array
    {
        $settings = self::SHIELD_DEFAULTS;

        try {
            $keys = array_keys(self::SHIELD_DEFAULTS);
            $placeholders = implode(',', array_fill(0, count($keys), '?'));
            $statement = $this->db()->prepare("SELECT setting_key, setting_value FROM settings WHERE setting_key IN ({$placeholders})");
            $statement->execute($keys);

            foreach ($statement->fetchAll() as $row) {
                $key = (string) ($row['setting_key'] ?? '');
                if (array_key_exists($key, $settings)) {
                    $settings[$key] = $this->normalizeShieldValue($key, $row['setting_value']);
                }
            }
        } catch (Throwable) {
            return $settings;
        }

        return $settings;
    }

    public function getFinancialSettings(): array
    {
        $settings = self::FINANCIAL_DEFAULTS;
        $keys = array_keys($settings);
        $placeholders = implode(',', array_fill(0, count($keys), '?'));
        $statement = $this->db()->prepare("SELECT setting_key, setting_value FROM settings WHERE setting_key IN ({$placeholders})");
        $statement->execute($keys);

        foreach ($statement->fetchAll() as $row) {
            $settings[(string) $row['setting_key']] = (string) $row['setting_value'];
        }

        if (isset($settings['site_commission_rate']) && $settings['site_commission_rate'] !== '') {
            $settings['commission_rate'] = $settings['site_commission_rate'];
        }

        if (isset($settings['currency']) && $settings['currency'] !== '') {
            $settings['default_currency'] = $settings['currency'];
        }

        return $this->normalizeFinancialSettings($settings);
    }

    public function saveFinancialSettings(array $input): array
    {
        $settings = $this->normalizeFinancialSettings($input + $this->getFinancialSettings());

        foreach ($settings as $key => $value) {
            $type = in_array($key, ['currency', 'default_currency', 'tax_calc_type', 'payout_mode'], true) ? 'string' : 'number';
            $this->set($key, $value, $type, 0);
        }

        $this->set('commission_rate', $settings['site_commission_rate'], 'number', 0);
        $this->set('default_currency', $settings['currency'], 'string', 0);

        return $settings;
    }

    public function saveShieldSettings(array $input): array
    {
        $settings = $this->normalizeShieldSettings($input);

        foreach ($settings as $key => $value) {
            $type = str_contains($key, 'threshold') ? 'number' : 'boolean';
            $this->set($key, $value, $type, 0);
        }

        return $settings;
    }

    public function getSiteSettings(): array
    {
        $settings = self::SITE_DEFAULTS;
        $keys = array_keys($settings);
        $placeholders = implode(',', array_fill(0, count($keys), '?'));
        $statement = $this->db()->prepare("SELECT setting_key, setting_value FROM settings WHERE setting_key IN ({$placeholders})");
        $statement->execute($keys);

        foreach ($statement->fetchAll() as $row) {
            $settings[(string) $row['setting_key']] = (string) $row['setting_value'];
        }

        return $settings;
    }

    public function saveSiteSettings(array $input): array
    {
        $settings = $this->normalizeSiteSettings($input + $this->getSiteSettings());

        foreach ($settings as $key => $value) {
            $type = in_array($key, ['maintenance_mode', 'registrations_enabled', 'header_menu_enabled'], true) ? 'boolean' : 'string';
            $publicKeys = [
                'site_name',
                'site_description',
                'site_logo',
                'music_logo',
                'studio_logo',
                'favicon',
                'logo_path',
                'default_language',
                'default_theme',
                'header_menu_enabled',
                'cookie_text',
                'footer_description',
                'footer_copyright',
                'social_x',
                'social_youtube',
                'social_instagram',
                'social_discord',
            ];
            $this->set($key, $value, $type, in_array($key, $publicKeys, true) ? 1 : 0);
        }

        return $settings;
    }

    private function normalizeShieldSettings(array $input): array
    {
        $settings = self::SHIELD_DEFAULTS;

        foreach ($settings as $key => $default) {
            if (str_contains($key, 'threshold')) {
                $settings[$key] = min(100, max(0, (int) ($input[$key] ?? $default)));
                continue;
            }

            $settings[$key] = $this->truthy($input[$key] ?? 0) ? 1 : 0;
        }

        if ($settings['shield_block_threshold'] < $settings['shield_review_threshold']) {
            $settings['shield_block_threshold'] = $settings['shield_review_threshold'];
        }

        return $settings;
    }

    private function normalizeFinancialSettings(array $input): array
    {
        $rate = function (string $key, string $fallback) use ($input): string {
            $value = (float) str_replace(',', '.', (string) ($input[$key] ?? $fallback));
            if ($value > 1) {
                $value = $value / 100;
            }

            return (string) round(min(1, max(0, $value)), 4);
        };

        $number = function (string $key, string $fallback, float $min = 0) use ($input): string {
            $value = (float) str_replace(',', '.', (string) ($input[$key] ?? $fallback));

            return (string) round(max($min, $value), 2);
        };

        $currency = strtoupper(substr(preg_replace('/[^A-Za-z]/', '', (string) ($input['currency'] ?? $input['default_currency'] ?? 'TRY')) ?: 'TRY', 0, 3));
        $taxCalcType = in_array((string) ($input['tax_calc_type'] ?? 'gross'), ['gross', 'net'], true) ? (string) $input['tax_calc_type'] : 'gross';
        $payoutMode = in_array((string) ($input['payout_mode'] ?? 'manual'), ['manual', 'api'], true) ? (string) $input['payout_mode'] : 'manual';

        return [
            'site_commission_rate' => $rate('site_commission_rate', (string) ($input['commission_rate'] ?? '0.10')),
            'commission_rate' => $rate('site_commission_rate', (string) ($input['commission_rate'] ?? '0.10')),
            'tax_rate' => $rate('tax_rate', '0.20'),
            'provider_fee_rate' => $rate('provider_fee_rate', '0'),
            'provider_fee_fixed' => $number('provider_fee_fixed', '0'),
            'minimum_withdrawal_amount' => $number('minimum_withdrawal_amount', '100', 0.01),
            'payout_delay_minutes' => (string) max(0, (int) ($input['payout_delay_minutes'] ?? 20)),
            'balance_hold_days' => (string) max(0, (int) ($input['balance_hold_days'] ?? 0)),
            'currency' => $currency ?: 'TRY',
            'default_currency' => $currency ?: 'TRY',
            'tax_calc_type' => $taxCalcType,
            'payout_mode' => $payoutMode,
        ];
    }

    private function normalizeSiteSettings(array $input): array
    {
        $url = static function (string $value): string {
            $value = trim($value);
            if ($value === '') {
                return '';
            }

            return substr($value, 0, 500);
        };

        $language = substr(preg_replace('/[^a-z]/', '', strtolower((string) ($input['default_language'] ?? 'tr'))) ?: 'tr', 0, 2);
        $theme = (string) ($input['default_theme'] ?? 'system');
        if (!in_array($theme, ['dark', 'light', 'system'], true)) {
            $theme = 'system';
        }
        $siteLogo = $url((string) ($input['site_logo'] ?? $input['logo_path'] ?? ''));
        $zpanelLogo = $url((string) ($input['zpanel_logo'] ?? $input['zpanel_logo_path'] ?? ''));

        return [
            'site_name' => substr(trim((string) ($input['site_name'] ?? 'Zalorox')), 0, 120) ?: 'Zalorox',
            'site_description' => substr(trim((string) ($input['site_description'] ?? '')), 0, 255),
            'site_logo' => $siteLogo,
            'music_logo' => $url((string) ($input['music_logo'] ?? '')),
            'studio_logo' => $url((string) ($input['studio_logo'] ?? '')),
            'zpanel_logo' => $zpanelLogo,
            'favicon' => $url((string) ($input['favicon'] ?? '')),
            'logo_path' => $siteLogo,
            'zpanel_logo_path' => $zpanelLogo,
            'default_language' => $language ?: 'tr',
            'default_theme' => $theme,
            'header_menu_enabled' => $this->truthy($input['header_menu_enabled'] ?? 1) ? '1' : '0',
            'maintenance_mode' => $this->truthy($input['maintenance_mode'] ?? 0) ? '1' : '0',
            'registrations_enabled' => $this->truthy($input['registrations_enabled'] ?? 1) ? '1' : '0',
            'cookie_text' => trim((string) ($input['cookie_text'] ?? '')),
            'footer_description' => trim((string) ($input['footer_description'] ?? '')),
            'footer_copyright' => trim((string) ($input['footer_copyright'] ?? '')),
            'social_x' => $url((string) ($input['social_x'] ?? '')),
            'social_youtube' => $url((string) ($input['social_youtube'] ?? '')),
            'social_instagram' => $url((string) ($input['social_instagram'] ?? '')),
            'social_discord' => $url((string) ($input['social_discord'] ?? '')),
        ];
    }

    private function normalizeShieldValue(string $key, mixed $value): int
    {
        if (str_contains($key, 'threshold')) {
            return min(100, max(0, (int) $value));
        }

        return $this->truthy($value) ? 1 : 0;
    }

    private function truthy(mixed $value): bool
    {
        if (is_bool($value)) {
            return $value;
        }

        return in_array(strtolower((string) $value), ['1', 'true', 'on', 'yes'], true);
    }
}
