<?php

namespace App\Http\Requests\Admin;

use Illuminate\Foundation\Http\FormRequest;

class SettingsUpdateRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()->can('manage settings');
    }

    /**
     * PRC-833: En az bir iptal iade tipi (anında / dönem sonu) açık olmalı.
     * İkisi birden kapatılırsa iptal formu seçeneksiz kalır → engelle.
     * Ayarlar tek formda gönderildiği için bu kontrol her kayıtta geçerli.
     */
    public function withValidator($validator): void
    {
        $validator->after(function ($validator) {
            if (! $this->boolean('cancellation_allow_immediate')
                && ! $this->boolean('cancellation_allow_end_of_period')) {
                $validator->errors()->add(
                    'cancellation_allow_immediate',
                    __('admin/settings.cancellation_refund_types_min_one')
                );
            }
        });
    }

    /**
     * Validation öncesi boş string'leri null'a çevir
     */
    protected function prepareForValidation(): void
    {
        $input = $this->all();

        foreach ($input as $key => $value) {
            // Boş string'leri null'a çevir
            if ($value === '') {
                $input[$key] = null;
            }
        }

        // PRC-556 — Organization sameAs: boş satırları at + yalnız http/https URL'leri sakla.
        if (isset($input['seo_org_sameas']) && is_array($input['seo_org_sameas'])) {
            $input['seo_org_sameas'] = array_values(array_filter(
                array_map('trim', $input['seo_org_sameas']),
                fn ($u) => $u !== '' && preg_match('#^https?://#i', $u) === 1
            ));
        }

        $this->replace($input);
    }

    public function rules(): array
    {
        return [
            // General Settings
            'company_name' => 'nullable|string|max:255',
            'company_email' => 'nullable|string|email|max:255',
            'company_phone' => 'nullable|string|max:50',
            'company_website' => 'nullable|string|max:255',
            'company_address' => 'nullable|string|max:500',
            'company_tax_number' => 'nullable|string|max:50',
            'maintenance_mode' => 'nullable|boolean',
            'maintenance_mode_message' => 'nullable|string',
            'maintenance_mode_redirect_url' => 'nullable',
            'company_city' => 'nullable|string|max:255',
            'company_state' => 'nullable|string|max:255',
            'company_postal_code' => 'nullable|string|max:20',
            'company_country' => 'nullable|string|max:2',
            'server_ip' => 'nullable|string|max:45',
            'app_domain' => 'nullable|string|max:255',

            // Localisation Settings
            'global_date_format' => 'nullable|in:DD/MM/YYYY,DD.MM.YYYY,DD-MM-YYYY,MM/DD/YYYY,YYYY/MM/DD,YYYY-MM-DD',
            'client_date_format' => 'nullable|in:use_global,1st_january_2000,1st_jan_2000,monday_january_1st_2000',
            'default_country' => 'nullable|string|max:2',
            'default_language' => 'nullable|string|max:5',
            'enable_language_menu' => 'nullable|boolean',
            'fiscal_year_start_month' => 'nullable|integer|min:1|max:12',
            // PRC-306: default_currency + FX provider settings /admin/settings/currencies sayfasına taşındı.
            // SETTINGS_DEFINITIONS korunur (defaults).
            'dns_default_provider' => 'nullable|string|in:cloudflare,powerdns',
            'dns_auto_setup_on_co_order' => 'nullable|boolean',
            'provisioning_queue_max_retries' => 'nullable|integer|min:0|max:50',
            'provisioning_queue_retry_intervals' => 'nullable|string|max:255',
            'provisioning_queue_admin_alert_enabled' => 'nullable|boolean',
            'provisioning_queue_retention_days' => 'nullable|integer|min:1|max:3650',
            'client_activity_log_retention_days' => 'nullable|integer|min:0|max:3650',

            // PRC-1138 — Storage disk backend (Local ↔ S3/MinIO)
            'storage_s3_endpoint' => 'nullable|string|max:255',
            'storage_s3_region' => 'nullable|string|max:64',
            'storage_s3_bucket' => 'nullable|string|max:255',
            'storage_s3_key' => 'nullable|string|max:255',
            'storage_s3_secret' => 'nullable|string|max:255',
            'storage_s3_path_style' => 'nullable|boolean',
            'storage_public_url' => 'nullable|string|max:255',
            'storage_driver_attachments' => 'nullable|in:local,s3',
            'storage_driver_public' => 'nullable|in:local,s3',
            'storage_driver_private' => 'nullable|in:local,s3',
            'storage_prefix_attachments' => 'nullable|string|max:128',
            'storage_prefix_public' => 'nullable|string|max:128',
            'storage_prefix_private' => 'nullable|string|max:128',

            // Order Settings
            'order_days_grace' => 'nullable|integer|min:0|max:365',
            'allow_notes_on_checkout' => 'nullable|boolean',
            'one_page_checkout' => 'nullable|boolean',
            'hide_out_of_stock_products' => 'nullable|boolean',
            'block_existing_domains' => 'nullable|boolean',
            'order_number_prefix' => 'nullable|string|max:20',
            'order_number_counter' => 'nullable|integer|min:1',
            // PRC-795 — sipariş tamamlandı içeriği (per-locale Quill HTML)
            'thank_you_content_translations' => 'nullable|array',
            'thank_you_content_translations.*' => 'nullable|string|max:65535',

            // Domain Settings
            'allow_domain_registration' => 'nullable|boolean',
            'allow_domain_transfer' => 'nullable|boolean',
            'allow_own_domain' => 'nullable|boolean',
            'enable_renewal_orders' => 'nullable|boolean',
            'allow_idn_domains' => 'nullable|boolean',
            // PRC-550 — Domain search frontend paralellik kontrolü
            'domain_search_batch_size' => 'nullable|integer|min:1|max:50',
            'domain_search_log_retention_days' => 'nullable|integer|min:0|max:3650',
            // PRC-319 / A-8 — domain_blocked_pattern_enforcement moved out
            // of /admin/settings; owned by BlockedDomainPatternController::saveSettings.
            // PRC-317 C-9 — premium domain pricing redesign
            'premium_domains_enabled' => 'nullable|boolean',
            'premium_domain_markup_pct' => 'nullable|numeric|min:0|max:1000',
            'default_nameserver_1' =>'nullable|string|max:255',
            'default_nameserver_2' => 'nullable|string|max:255',
            'default_nameserver_3' => 'nullable|string|max:255',
            'default_nameserver_4' => 'nullable|string|max:255',
            'default_nameserver_5' => 'nullable|string|max:255',
            'use_clients_details' => 'nullable|boolean',
            'default_billing_first_name' => 'nullable|string|max:255',
            'default_billing_last_name' => 'nullable|string|max:255',
            'default_billing_company_name' => 'nullable|string|max:255',
            'default_billing_email_address' => 'nullable',
            'default_billing_address_1' => 'nullable|string|max:500',
            'default_billing_address_2' => 'nullable|string|max:500',
            'default_billing_city' => 'nullable|string|max:255',
            'default_billing_state' => 'nullable|string|max:255',
            'default_billing_postcode' => 'nullable|string|max:20',
            'default_billing_country' => 'nullable|string|max:2',
            'default_billing_phone_number' => 'nullable|string|max:50',

            // Domain Sync Settings
            'domain_sync_enabled' => 'nullable|boolean',
            // PRC-318 / D-11 — cycle period semantic (1/3/7/14 day full-list sync).
            // Legacy `domain_*_sync_frequency` enum keys dropped by migration.
            'domain_sync_cycle_days' => 'nullable|integer|in:1,3,7,14',
            'domain_expiring_sync_cycle_days' => 'nullable|integer|in:1,3,7,14',
            'domain_transfer_sync_cycle_days' => 'nullable|integer|in:1,3,7,14',
            // PRC-318 / D-12 — bound to 90 days (was 365). 90+ gün üstü
            // pratikte "expiring" sayılmaz; ayrı uzun-vade reminder kanalı.
            'domain_expiring_sync_days' => 'nullable|integer|min:1|max:90',
            'domain_sync_batch_limit' => 'nullable|integer|min:1|max:1000',
            'domain_sync_notify_client' => 'nullable|boolean',
            'domain_sync_notify_admin' => 'nullable|boolean',
            'dummy_registrar_email_notifications_enabled' => 'nullable|boolean',

            // Domain Renewal Reminder Settings
            'domain_reminder_first_days' => 'nullable|integer|min:0|max:365',
            'domain_reminder_second_days' => 'nullable|integer|min:0|max:365',
            'domain_reminder_third_days' => 'nullable|integer|min:0|max:365',
            'domain_reminder_final_days' => 'nullable|integer|min:0|max:365',
            'transferred_invoice_action' => 'nullable|in:cancel,credit_note',

            // Email Settings
            'mail_provider' => 'nullable|string|max:100',

            // SMS Settings (PRC-623)
            'sms_default_provider' => 'nullable|string|max:100',
            'sms_test_mode' => 'nullable|boolean',
            'sms_from_number' => 'nullable|string|max:32',
            'disable_email_sending' => 'nullable|boolean',
            'enable_welcome_emails' => 'nullable|boolean',
            'enable_order_confirmation_emails' => 'nullable|boolean',
            'enable_payment_confirmation_emails' => 'nullable|boolean',
            'enable_service_activation_emails' => 'nullable|boolean',
            'enable_admin_order_notifications' => 'nullable|boolean',
            'notify_product_provisioning_success_admin' => 'nullable|boolean',
            'global_email_signature' => 'nullable|string',
            'global_email_css_styling' => 'nullable|string',
            'client_email_header_content' => 'nullable|string',
            'client_email_footer_content' => 'nullable|string',
            'system_emails_from_name' => 'nullable|string|max:255',
            'system_emails_from_email' => 'nullable|email',
            'bcc_messages' => 'nullable|email',
            'presales_contact_form_email' => 'nullable|email',

            // PRC-623 — email/sms provider parametre validation'ları kaldırıldı
            // (parametreler module_settings'te, modül edit sayfasından yönetilir).

            // Billing Settings
            // PRC-304: E-Billing operasyonel settings /admin/billing/rules üst kartına taşındı.
            // SETTINGS_DEFINITIONS korunur (defaults).

            // Support Settings
            // Support — Notifications
            'notify_client_on_ticket_reply' => 'nullable|boolean',
            'notify_client_on_status_change' => 'nullable|boolean',
            'notify_staff_on_new_ticket' => 'nullable|boolean',
            'notify_staff_on_client_reply' => 'nullable|boolean',
            // Support — Auto-Close & Auto-Response
            'auto_close_inactive_tickets' => 'nullable|boolean',
            'auto_close_inactive_days' => 'nullable|integer|min:0|max:365',
            'auto_response_on_new_ticket' => 'nullable|boolean',
            'auto_response_on_ticket_close' => 'nullable|boolean',
            // Support — Ticket Rating
            'ticket_rating_reminder_days' => 'nullable|integer|min:0|max:30',
            // Support — SLA
            'sla_enabled' => 'nullable|boolean',
            'sla_default_response_hours' => 'nullable|integer|min:1|max:720',
            'sla_default_resolution_hours' => 'nullable|integer|min:1|max:720',
            'sla_business_hours_only' => 'nullable|boolean',
            // Support — Working Hours
            'business_hours_enabled' => 'nullable|boolean',
            'business_hours_work_days' => 'nullable|array',
            'business_hours_work_days.*' => 'string|in:monday,tuesday,wednesday,thursday,friday,saturday,sunday',
            'business_hours_start' => 'nullable|date_format:H:i',
            'business_hours_end' => 'nullable|date_format:H:i',
            'support_timezone' => 'nullable|string|max:100',
            // Support — Client Permissions
            'allow_client_ticket_attachments' => 'nullable|boolean',
            // PRC-335 — client_tickets_require_login removed (login always required).
            // TODO(unified-posts Phase 12): rewire to posts module after PostController + TagController land.
            'knowledgebase_suggestions' => 'nullable|boolean',
            'ticket_client_priority_mode' => 'nullable|in:required,optional,hidden', // PRC-788
            'attachment_thumbnail_previews' => 'nullable|boolean',
            'support_ticket_rating' => 'nullable|boolean',
            'auto_add_carbon_copy_recipients' => 'nullable|boolean',
            'prevent_email_reopening' => 'nullable|boolean',
            'prevent_client_panel_reopen' => 'nullable|boolean',
            'reply_email_logging_enabled' => 'nullable|boolean',
            // PRC-683 — ham .eml retention ayarları.
            'ticket_store_original_eml' => 'nullable|boolean',
            'ticket_eml_retention_days' => 'nullable|integer|min:0|max:3650',
            'allowed_file_attachment_types' => 'nullable',
            'ticket_attachment_max_size' => 'nullable|integer|min:512|max:51200',
            'allow_insecure_imports' => 'nullable|boolean',
            'email_pipe_accept_policy' => 'nullable|in:all,registered_only',
            'antivirus_enabled' => 'nullable|boolean', // PRC-360

            // Invoice Settings
            'continuous_invoice_generation' => 'nullable|boolean',
            'show_zero_tax_line' => 'nullable|boolean', // PRC-672
            'enable_pdf_invoices' => 'nullable|boolean',
            'pdf_paper_size' => 'nullable|string|max:50',
            'pdf_font_family' => 'nullable|string|max:100',
            'store_client_data_snapshot' => 'nullable|boolean',
            'enable_mass_payment' => 'nullable|boolean',
            'clients_choose_gateway' => 'nullable|boolean',
            'cancellation_request_handling' => 'nullable|boolean',
            'enable_proforma_invoicing' => 'nullable|boolean',
            'sequential_paid_invoice_numbering' => 'nullable|boolean',
            'sequential_invoice_number_format' => 'nullable|string|max:255',
            'invoice_number_format' => 'nullable|string|max:255',
            'proforma_invoice_number_format' => 'nullable|string|max:255',
            'tax_invoice_number_format' => 'nullable|string|max:255',
            'invoice_number_yearly_reset' => 'nullable|boolean',
            'auto_dispatch_legal_invoice_on_payment' => 'nullable|boolean',
            'auto_dispatch_legal_invoice_on_refund' => 'nullable|boolean',
            'auto_dispatch_legal_invoice_on_cancel' => 'nullable|boolean',
            'legal_invoice_email_send_to_client' => 'nullable|boolean',
            'allow_prepayment_legal_invoice' => 'nullable|boolean',
            'exclude_zero_total_from_einvoice' => 'nullable|boolean',
            'late_fee_type' => 'nullable|string|in:fixed,percentage',
            'late_fee_amount' => 'nullable|numeric|min:0',
            'late_fee_minimum' => 'nullable|numeric|min:0',
            'late_fees_enabled' => 'nullable|boolean',
            'late_fee_grace_days' => 'nullable|integer|min:0|max:365',
            'late_fee_apply_schedule' => 'nullable|date_format:H:i',
            'invoice_incrementation' => 'nullable|integer|min:1',

            // Invoice Overdue Reminders
            'enable_invoice_reminder_emails' => 'nullable|boolean',
            'invoice_reminder_first_days' => 'nullable|integer|min:0|max:90',
            'invoice_reminder_second_days' => 'nullable|integer|min:0|max:90',
            'invoice_reminder_third_days' => 'nullable|integer|min:0|max:90',
            'invoice_reminder_final_days' => 'nullable|integer|min:0|max:90',
            'notify_admin_on_invoice_created' => 'nullable|boolean',
            'notify_admin_on_invoice_paid' => 'nullable|boolean',
            'notify_admin_on_payment_received' => 'nullable|boolean',
            'notify_admin_on_invoice_cancelled' => 'nullable|boolean',
            'allow_billing_address_change_on_unpaid' => 'nullable|boolean',
            // PRC-882 — Otomatik tahsilat global toggle
            'auto_pay_global_enabled' => 'nullable|boolean',
            'invoice_starting_number' => 'nullable|integer|min:1',
            'invoice_number_prefix' => 'nullable|string|max:20',
            'invoice_number_counter' => 'nullable|integer|min:1',
            // PRC-369 — per-cycle table validated as an associative
            // array; each cycle value must be a non-negative integer up
            // to 365. Missing cycles fall back to PaymentTermsResolver
            // defaults at read time.
            'payment_terms_per_cycle' => 'nullable|array',
            'payment_terms_per_cycle.monthly' => 'nullable|integer|min:0|max:365',
            'payment_terms_per_cycle.quarterly' => 'nullable|integer|min:0|max:365',
            'payment_terms_per_cycle.semi_annually' => 'nullable|integer|min:0|max:365',
            'payment_terms_per_cycle.annually' => 'nullable|integer|min:0|max:365',
            'payment_terms_per_cycle.biennially' => 'nullable|integer|min:0|max:365',
            'payment_terms_per_cycle.domain' => 'nullable|integer|min:0|max:365',
            'invoice_footer_text' => 'nullable|string|max:2000',
            'invoice_terms_text' => 'nullable|string|max:2000',
            'invoice_notes_text' => 'nullable|string|max:2000',

            // Credit Settings
            'enable_credit' => 'nullable|boolean',
            'minimum_deposit' => 'nullable|numeric|min:0',
            'maximum_deposit' => 'nullable|numeric|min:0',
            'maximum_balance' => 'nullable|numeric|min:0',
            'automatic_credit_use' => 'nullable|boolean',
            'credit_on_downgrade' => 'nullable|boolean',

            // Affiliate Settings
            'enable_affiliate' => 'nullable|boolean',
            'affiliate_earning_percentage' => 'nullable|numeric|min:0|max:100',
            'affiliate_bonus_deposit' => 'nullable|numeric|min:0',
            'affiliate_payout_amount' => 'nullable|numeric|min:0',
            'affiliate_commission_delay' => 'nullable|integer|min:0',
            'payout_request_department' => 'nullable|string|max:255',
            'affiliate_links' => 'nullable|string',

            // Security Settings
            'email_verification' => 'nullable|boolean',
            'sms_verification' => 'nullable|boolean',
            'citizenship_verification' => 'nullable|boolean',
            'captcha_form_protection' => 'nullable|string|in:always_on,off_when_logged_in,always_off',
            'captcha_type' => 'nullable|string|in:recaptcha_v2,invisible_recaptcha,recaptcha_v3,cloudflare_turnstile,hcaptcha',
            'captcha_for_select_forms' => 'nullable|array',
            'captcha_for_select_forms.*' => 'string|in:shopping_cart_checkout,domain_checker,client_registration,contact_form,ticket_submission,login_forms,admin_login',
            'two_factor_client_allowed_channels' => 'nullable|array',
            'two_factor_client_allowed_channels.*' => 'string|in:totp,email,sms',
            'two_factor_admin_allowed_channels' => 'nullable|array',
            'two_factor_admin_allowed_channels.*' => 'string|in:totp,email,sms',
            'captcha_site_key' => 'nullable|string',
            'captcha_secret_key' => 'nullable|string',
            'recaptcha_v3_threshold' => 'nullable|numeric|min:0|max:1',
            'auto_generated_password_format' => 'nullable|string|in:default,letters_numbers_only',
            'password_history_depth' => 'nullable|integer|min:0|max:50',
            'password_rotation_days' => 'nullable|integer|min:0|max:3650',
            'password_history_apply_to' => 'nullable|string|in:admins_only,clients_only,both',
            'minimum_user_password_strength' => 'nullable|integer|min:0|max:100',
            // PRC-513 — password policy rules
            'password_min_length' => 'nullable|integer|min:5|max:128',
            'password_require_mixedcase' => 'nullable|boolean',
            'password_require_numbers' => 'nullable|boolean',
            'password_require_symbols' => 'nullable|boolean',
            'failed_admin_login_ban_time' => 'nullable|integer|min:0',
            'whitelisted_ips' => 'nullable|string',
            'whitelisted_ip_login_failure_notices' => 'nullable|boolean',
            'delete_encrypted_credit_card_data' => 'nullable|boolean',
            'delete_encrypted_bank_account_data' => 'nullable|boolean',
            'allow_client_pay_method_removal' => 'nullable|boolean',
            'disable_session_ip_check' => 'nullable|boolean',
            'login_new_location_notification_enabled' => 'nullable|boolean',
            'allow_smarty_php_tags' => 'nullable|boolean',
            // PRC-193 — proxy_ip_header restricted to known provider headers.
            // Custom values would let the client supply that header and
            // override X-Forwarded-For with an attacker-chosen IP.
            'proxy_ip_header' => 'nullable|string|in:cf-connecting-ip,true-client-ip,x-real-ip,x-forwarded-for,forwarded',
            // PRC-189 — wildcard '*' rejected; admin must enumerate proxy
            // IPs/CIDRs explicitly. Each entry validated as IP or CIDR-ish.
            'trusted_proxies' => ['nullable', 'string', 'not_in:*', function ($attribute, $value, $fail) {
                if ($value === null || $value === '') return;
                foreach (preg_split('/[,\n]+/', (string) $value) as $entry) {
                    $entry = trim($entry);
                    if ($entry === '' || $entry === '*') {
                        $fail('Wildcard "*" is not allowed in trusted_proxies — list explicit IPs or CIDRs.');
                        return;
                    }
                    // Accept IPv4/IPv6 or CIDR notation
                    [$ip] = array_pad(explode('/', $entry, 2), 2, null);
                    if (filter_var($ip, FILTER_VALIDATE_IP) === false) {
                        $fail("Invalid IP or CIDR in trusted_proxies: {$entry}");
                        return;
                    }
                }
            }],
            'api_ip_access_restriction' => 'nullable|string',
            'log_api_authentication' => 'nullable|boolean',
            'admin_ip_whitelist' => 'nullable|string',
            'whitelisted_ips' => 'nullable|string',
            'whitelisted_ip_login_failure_notices' => 'nullable|boolean',
            'delete_encrypted_credit_card_data' => 'nullable|boolean',
            'delete_encrypted_bank_account_data' => 'nullable|boolean',
            'allow_client_pay_method_removal' => 'nullable|boolean',
            'disable_session_ip_check' => 'nullable|boolean',
            'login_new_location_notification_enabled' => 'nullable|boolean',
            'allow_smarty_php_tags' => 'nullable|boolean',
            // PRC-193 — proxy_ip_header restricted to known provider headers.
            // Custom values would let the client supply that header and
            // override X-Forwarded-For with an attacker-chosen IP.
            'proxy_ip_header' => 'nullable|string|in:cf-connecting-ip,true-client-ip,x-real-ip,x-forwarded-for,forwarded',
            // PRC-189 — wildcard '*' rejected; admin must enumerate proxy
            // IPs/CIDRs explicitly. Each entry validated as IP or CIDR-ish.
            'trusted_proxies' => ['nullable', 'string', 'not_in:*', function ($attribute, $value, $fail) {
                if ($value === null || $value === '') return;
                foreach (preg_split('/[,\n]+/', (string) $value) as $entry) {
                    $entry = trim($entry);
                    if ($entry === '' || $entry === '*') {
                        $fail('Wildcard "*" is not allowed in trusted_proxies — list explicit IPs or CIDRs.');
                        return;
                    }
                    // Accept IPv4/IPv6 or CIDR notation
                    [$ip] = array_pad(explode('/', $entry, 2), 2, null);
                    if (filter_var($ip, FILTER_VALIDATE_IP) === false) {
                        $fail("Invalid IP or CIDR in trusted_proxies: {$entry}");
                        return;
                    }
                }
            }],
            'api_ip_access_restriction' => 'nullable|string',
            'log_api_authentication' => 'nullable|boolean',
            'csrf_tokens_general' => 'nullable|boolean',
            'csrf_tokens_domain_checker' => 'nullable|boolean',

            // Other Settings
            // NOTE: marketing_emails / require_user_opt_in / marketing_email_opt_in_messaging
            // moved to /admin/email-marketing settings card (PRC-305).
            'admin_client_display_format' => 'nullable|string|in:firstname_lastname,company_or_name,full_name_and_company',
            'allow_client_registration' => 'nullable|boolean',
            'client_email_preferences' => 'nullable|boolean',
            'optional_client_profile_fields' => 'nullable|array',
            'optional_client_profile_fields.*' => 'string|in:firstname,lastname,company,address1,city,state,postcode,phone',
            'locked_client_user_profile_fields' => 'nullable|array',
            'locked_client_user_profile_fields.*' => 'string|in:firstname,lastname,company,email,address1,address2,city,state,postcode,country,phone,tax_id',
            // PRC-309: client_details_change_notify removed (template-status routing)
            'show_cancellation_link' => 'nullable|boolean',
            'cancellation_reason_required' => 'nullable|boolean',
            'cancellation_allow_immediate' => 'nullable|boolean',
            'cancellation_allow_end_of_period' => 'nullable|boolean',

            // Social Media Authentication Settings
            'social_facebook_enabled' => 'nullable|boolean',
            'social_facebook_client_id' => 'nullable|string|max:255',
            'social_facebook_client_secret' => 'nullable|string|max:255',
            'social_google_enabled' => 'nullable|boolean',
            'social_google_client_id' => 'nullable|string|max:255',
            'social_google_client_secret' => 'nullable|string|max:255',
            'social_twitter_enabled' => 'nullable|boolean',
            'social_twitter_client_id' => 'nullable|string|max:255',
            'social_twitter_client_secret' => 'nullable|string|max:255',
            'social_linkedin_enabled' => 'nullable|boolean',
            'social_linkedin_client_id' => 'nullable|string|max:255',
            'social_linkedin_client_secret' => 'nullable|string|max:255',
            'social_bitbucket_enabled' => 'nullable|boolean',
            'social_bitbucket_client_id' => 'nullable|string|max:255',
            'social_bitbucket_client_secret' => 'nullable|string|max:255',
            // PRC-780 — Microsoft (Azure AD)
            'social_microsoft_enabled' => 'nullable|boolean',
            'social_microsoft_client_id' => 'nullable|string|max:255',
            'social_microsoft_client_secret' => 'nullable|string|max:255',
            'social_microsoft_tenant' => 'nullable|string|max:255',

            // Integration Settings
            'slack_bot_token' => 'nullable|string|max:255',
            'slack_signing_secret' => 'nullable|string|max:255',
            'slack_admin_channel' => 'nullable|string|max:255',
            'telegram_bot_token' => 'nullable|string|max:255',
            'telegram_bot_username' => 'nullable|string|max:64|regex:/^[A-Za-z0-9_]+$/',
            'telegram_admin_chat_id' => 'nullable|string|max:255',
            'discord_admin_webhook' => 'nullable|string|max:500',
            'teams_admin_webhook' => 'nullable|string|max:2048', // PRC-782 — Workflows SAS URL 1000+ char; host hard-validate yok
            'pushover_app_token' => 'nullable|string|max:255',
            'pushover_admin_user_key' => 'nullable|string|max:255',

            // Tracking & Analytics Integrations
            'gtm_container_id' => ['nullable', 'string', 'max:50', 'regex:/^GTM-[A-Z0-9]+$/'],
            'ga4_measurement_id' => ['nullable', 'string', 'max:50', 'regex:/^G-[A-Z0-9]+$/'],
            'ga4_api_secret' => ['nullable', 'string', 'max:255'],
            'google_ads_conversion_id' => ['nullable', 'string', 'max:50', 'regex:/^AW-[0-9]+$/'],
            'google_ads_purchase_label' => ['nullable', 'string', 'max:100'],
            'meta_pixel_id' => ['nullable', 'string', 'max:50', 'regex:/^[0-9]+$/'],
            'meta_capi_access_token' => ['nullable', 'string', 'max:500'],
            'meta_capi_test_event_code' => ['nullable', 'string', 'max:50'],
            'tiktok_pixel_id' => ['nullable', 'string', 'max:100'],
            'tiktok_events_api_token' => ['nullable', 'string', 'max:500'],
            'tiktok_events_test_event_code' => ['nullable', 'string', 'max:50'],

            // PRC-1098 — product-analytics SDK integrations. Without these rules
            // validated() strips the keys before persistence (they were also
            // missing from $settingsDefinition) → integrations un-saveable.
            'amplitude_api_key' => ['nullable', 'string', 'max:255'],
            'amplitude_server_zone' => ['nullable', 'string', 'max:10'],
            'firebase_api_key' => ['nullable', 'string', 'max:255'],
            'firebase_api_secret' => ['nullable', 'string', 'max:255'],
            'firebase_app_id' => ['nullable', 'string', 'max:255'],
            'firebase_measurement_id' => ['nullable', 'string', 'max:100'],
            'firebase_project_id' => ['nullable', 'string', 'max:255'],
            'mixpanel_project_token' => ['nullable', 'string', 'max:255'],
            'mixpanel_api_host' => ['nullable', 'string', 'max:255'],
            'posthog_project_api_key' => ['nullable', 'string', 'max:255'],
            'posthog_host' => ['nullable', 'string', 'max:255'],
            'segment_write_key' => ['nullable', 'string', 'max:255'],

            // PRC-624 — anahtarlar prefKey(Title Case ad) formundadır.
            'notification_channels_provisioning_failed' => 'nullable|array',
            'notification_channels_provisioning_failed.*' => 'string',
            'notification_channels_admin_domain_status_critical' => 'nullable|array',
            'notification_channels_admin_domain_status_critical.*' => 'string',
            'notification_channels_admin_domain_status_summary' => 'nullable|array',
            'notification_channels_admin_domain_status_summary.*' => 'string',
            'notification_channels_admin_ticket_created_notification' => 'nullable|array',
            'notification_channels_admin_ticket_created_notification.*' => 'string',
            'notification_channels_admin_payment_received_notification' => 'nullable|array',
            'notification_channels_admin_payment_received_notification.*' => 'string',
            'notification_channels_admin_domain_expiring_notification' => 'nullable|array',
            'notification_channels_admin_domain_expiring_notification.*' => 'string',
            'notification_channels_admin_service_suspended_notification' => 'nullable|array',
            'notification_channels_admin_service_suspended_notification.*' => 'string',
            // PRC-404 / D-002 — PRC-376 registered the 3 invoice settings in
            // SettingsController but missed adding validation here, so the
            // controller's "reset missing notification_channels_* to []" loop
            // wiped any seeded value on save. Falls back to email-only.
            'notification_channels_admin_invoice_created_notification' => 'nullable|array',
            'notification_channels_admin_invoice_created_notification.*' => 'string',
            'notification_channels_admin_invoice_paid_notification' => 'nullable|array',
            'notification_channels_admin_invoice_paid_notification.*' => 'string',
            'notification_channels_invoice_cancelled' => 'nullable|array',
            'notification_channels_invoice_cancelled.*' => 'string',

            'monthly_affiliate_reports' => 'nullable|boolean',
            'banned_subdomain_prefixes' => 'nullable|string',
            'encoded_file_loading' => 'nullable|boolean',
            'event_handling' => 'nullable|boolean',
            'display_errors' => 'nullable|boolean',
            'log_errors' => 'nullable|boolean',
            'sql_debug_mode' => 'nullable|boolean',
            'hooks_debug_mode' => 'nullable|boolean',
            'seo_title_template' => 'nullable|string|max:255',
            'seo_default_description' => 'nullable|string|max:500',
            'seo_default_og_image' => 'nullable|string|max:500',
            'seo_robots_txt' => 'nullable|string|max:5000',

            // SEO — Global (PRC-556)
            'seo_google_verification' => 'nullable|string|max:255',
            'seo_bing_verification' => 'nullable|string|max:255',
            'seo_pinterest_verification' => 'nullable|string|max:255',
            'seo_twitter_site' => 'nullable|string|max:100',
            'seo_twitter_creator' => 'nullable|string|max:100',
            'seo_fb_app_id' => 'nullable|string|max:100',
            'seo_theme_color' => 'nullable|string|max:32',
            'seo_apple_touch_icon' => 'nullable|string|max:500',
            'seo_org_name' => 'nullable|string|max:255',
            'seo_org_url' => 'nullable|string|max:500',
            'seo_org_logo' => 'nullable|string|max:500',
            'seo_org_contact_phone' => 'nullable|string|max:50',
            'seo_org_sameas' => 'nullable|array',
            'seo_org_sameas.*' => 'nullable|string|max:500',
            'seo_searchaction_enabled' => 'nullable|boolean',
            'seo_searchaction_target' => 'nullable|string|max:500',

            // Consent
            'consent_enabled' => 'nullable|boolean',
            'consent_cookie_lifetime_days' => 'nullable|integer|min:1|max:3650',
            'consent_banner_position' => 'nullable|in:bottom,top',
            // PRC-303: artık content-link-picker, 3 format kabul eder (contract:N / page:N / https://...).
            'consent_policy_url' => 'nullable|string|max:2048',
            'consent_banner_text_tr' => 'nullable|string|max:2000',
            'consent_banner_text_en' => 'nullable|string|max:2000',
            'consent_reject_implicit_expiry_days' => 'nullable|integer|min:0|max:3650',

            // PRC-827 — Remote Backup
            'backup_enabled' => 'nullable|boolean',
            'backup_frequency' => 'nullable|string|in:daily,weekly',
            'backup_time' => 'nullable|string|regex:/^([01]\d|2[0-3]):[0-5]\d$/',
            'backup_retention_days' => 'nullable|integer|min:1|max:3650',
            'backup_include_db' => 'nullable|boolean',
            'backup_include_files' => 'nullable|boolean',
            'backup_notify' => 'nullable|boolean',
        ];
    }

    public function messages(): array
    {
        return [
            'company_name.max' => 'Şirket adı en fazla 255 karakter olabilir.',
            'email_address.email' => 'Geçerli bir e-posta adresi giriniz.',
            'maintenance_mode_redirect_url.url' => 'Geçerli bir URL giriniz.',
            'global_date_format.in' => 'Geçersiz tarih formatı seçildi.',
            'client_date_format.in' => 'Geçersiz müşteri tarih formatı seçildi.',
            'default_country.max' => 'Varsayılan ülke kodu en fazla 2 karakter olabilir.',
            'default_language.max' => 'Varsayılan dil kodu en fazla 5 karakter olabilir.',
            'order_days_grace.integer' => 'Sipariş gün sayısı tam sayı olmalıdır.',
            'order_days_grace.min' => 'Sipariş gün sayısı en az 0 olmalıdır.',
            'order_days_grace.max' => 'Sipariş gün sayısı en fazla 365 olmalıdır.',
            'default_nameserver_1.max' => 'Varsayılan nameserver 1 en fazla 255 karakter olabilir.',
            'default_nameserver_2.max' => 'Varsayılan nameserver 2 en fazla 255 karakter olabilir.',
            'default_nameserver_3.max' => 'Varsayılan nameserver 3 en fazla 255 karakter olabilir.',
            'default_nameserver_4.max' => 'Varsayılan nameserver 4 en fazla 255 karakter olabilir.',
            'default_nameserver_5.max' => 'Varsayılan nameserver 5 en fazla 255 karakter olabilir.',
            'default_billing_first_name.max' => 'Varsayılan fatura adı en fazla 255 karakter olabilir.',
            'default_billing_last_name.max' => 'Varsayılan fatura soyadı en fazla 255 karakter olabilir.',
            'default_billing_company_name.max' => 'Varsayılan fatura şirket adı en fazla 255 karakter olabilir.',
            'default_billing_email_address.email' => 'Geçerli bir e-posta adresi giriniz.',
            'default_billing_address_1.max' => 'Varsayılan fatura adresi 1 en fazla 500 karakter olabilir.',
            'default_billing_address_2.max' => 'Varsayılan fatura adresi 2 en fazla 500 karakter olabilir.',
            'default_billing_city.max' => 'Varsayılan fatura şehri en fazla 255 karakter olabilir.',
            'default_billing_state.max' => 'Varsayılan fatura eyaleti en fazla 255 karakter olabilir.',
            'default_billing_postcode.max' => 'Varsayılan fatura posta kodu en fazla 20 karakter olabilir.',
            'default_billing_country.max' => 'Varsayılan fatura ülkesi en fazla 2 karakter olabilir.',
            'default_billing_phone_number.max' => 'Varsayılan fatura telefon numarası en fazla 50 karakter olabilir.',
            'mail_provider.max' => 'E-posta sağlayıcısı en fazla 100 karakter olabilir.',
            'system_emails_from_name.max' => 'Sistem e-postaları gönderen adı en fazla 255 karakter olabilir.',
            'system_emails_from_email.email' => 'Geçerli bir e-posta adresi giriniz.',
            'bcc_messages.email' => 'Geçerli bir e-posta adresi giriniz.',
            'presales_contact_form_email.email' => 'Geçerli bir e-posta adresi giriniz.',
            'allowed_file_attachment_types.string' => 'İzin verilen dosya ek türleri metin olmalıdır.',
            'pdf_paper_size.max' => 'PDF kağıt boyutu en fazla 50 karakter olabilir.',
            'pdf_font_family.max' => 'PDF font ailesi en fazla 100 karakter olabilir.',
            'cancellation_request_handling.boolean' => 'İptal talebi işleme boolean olmalıdır.',
            'sequential_invoice_number_format.max' => 'Sıralı fatura numarası formatı en fazla 255 karakter olabilir.',
            'late_fee_type.in' => 'Gecikme ücreti türü sabit veya yüzde olmalıdır.',
            'late_fee_amount.numeric' => 'Gecikme ücreti tutarı sayısal olmalıdır.',
            'late_fee_amount.min' => 'Gecikme ücreti tutarı en az 0 olmalıdır.',
            'late_fee_minimum.numeric' => 'Gecikme ücreti minimum tutarı sayısal olmalıdır.',
            'late_fee_minimum.min' => 'Gecikme ücreti minimum tutarı en az 0 olmalıdır.',
            'invoice_incrementation.integer' => 'Fatura artırımı tam sayı olmalıdır.',
            'invoice_incrementation.min' => 'Fatura artırımı en az 1 olmalıdır.',
            'invoice_starting_number.integer' => 'Fatura başlangıç numarası tam sayı olmalıdır.',
            'invoice_starting_number.min' => 'Fatura başlangıç numarası en az 1 olmalıdır.',
            'minimum_deposit.numeric' => 'Minimum depozito sayısal olmalıdır.',
            'minimum_deposit.min' => 'Minimum depozito en az 0 olmalıdır.',
            'maximum_deposit.numeric' => 'Maksimum depozito sayısal olmalıdır.',
            'maximum_deposit.min' => 'Maksimum depozito en az 0 olmalıdır.',
            'maximum_balance.numeric' => 'Maksimum bakiye sayısal olmalıdır.',
            'maximum_balance.min' => 'Maksimum bakiye en az 0 olmalıdır.',
            'affiliate_earning_percentage.numeric' => 'Ortaklık kazanç yüzdesi sayısal olmalıdır.',
            'affiliate_earning_percentage.min' => 'Ortaklık kazanç yüzdesi en az 0 olmalıdır.',
            'affiliate_earning_percentage.max' => 'Ortaklık kazanç yüzdesi en fazla 100 olmalıdır.',
            'affiliate_bonus_deposit.numeric' => 'Ortaklık bonus depozitosu sayısal olmalıdır.',
            'affiliate_bonus_deposit.min' => 'Ortaklık bonus depozitosu en az 0 olmalıdır.',
            'affiliate_payout_amount.numeric' => 'Ortaklık ödeme tutarı sayısal olmalıdır.',
            'affiliate_payout_amount.min' => 'Ortaklık ödeme tutarı en az 0 olmalıdır.',
            'affiliate_commission_delay.integer' => 'Ortaklık komisyon gecikmesi tam sayı olmalıdır.',
            'affiliate_commission_delay.min' => 'Ortaklık komisyon gecikmesi en az 0 olmalıdır.',
            'payout_request_department.max' => 'Ödeme talebi departmanı en fazla 255 karakter olabilir.',
            'captcha_type.max' => 'Captcha türü en fazla 50 karakter olabilir.',
            'recaptcha_site_key.max' => 'reCAPTCHA site anahtarı en fazla 255 karakter olabilir.',
            'recaptcha_secret_key.max' => 'reCAPTCHA gizli anahtarı en fazla 255 karakter olabilir.',
            'auto_generated_password_format.max' => 'Otomatik oluşturulan şifre formatı en fazla 100 karakter olabilir.',
            'minimum_user_password_strength.integer' => 'Minimum kullanıcı şifre gücü tam sayı olmalıdır.',
            'minimum_user_password_strength.min' => 'Minimum kullanıcı şifre gücü en az 1 olmalıdır.',
            'minimum_user_password_strength.max' => 'Minimum kullanıcı şifre gücü en fazla 100 olmalıdır.',
            'password_min_length.integer' => 'Minimum şifre uzunluğu tam sayı olmalıdır.',
            'password_min_length.min' => 'Minimum şifre uzunluğu en az 5 olmalıdır.',
            'password_min_length.max' => 'Minimum şifre uzunluğu en fazla 128 olmalıdır.',
            'password_require_mixedcase.boolean' => 'Büyük + küçük harf zorunlu ayarı boolean olmalıdır.',
            'password_require_numbers.boolean' => 'Rakam zorunlu ayarı boolean olmalıdır.',
            'password_require_symbols.boolean' => 'Özel karakter zorunlu ayarı boolean olmalıdır.',
            'failed_admin_login_ban_time.integer' => 'Başarısız admin giriş yasaklama süresi tam sayı olmalıdır.',
            'failed_admin_login_ban_time.min' => 'Başarısız admin giriş yasaklama süresi en az 0 olmalıdır.',
            'proxy_ip_header.in' => 'Proxy IP başlığı yalnızca şu değerlerden biri olabilir: cf-connecting-ip, true-client-ip, x-real-ip, x-forwarded-for, forwarded.',
            'trusted_proxies.not_in' => 'Trusted proxies için "*" değeri kabul edilmiyor — proxy IP/CIDR listesini açıkça yazın.',
            'admin_client_display_format.in' => 'Geçersiz admin müşteri görüntüleme formatı seçildi.',

            // Social Media Authentication validation messages
            'social_facebook_client_id.max' => 'Facebook Client ID en fazla 255 karakter olabilir.',
            'social_facebook_client_secret.max' => 'Facebook Client Secret en fazla 255 karakter olabilir.',
            'social_google_client_id.max' => 'Google Client ID en fazla 255 karakter olabilir.',
            'social_google_client_secret.max' => 'Google Client Secret en fazla 255 karakter olabilir.',
            'social_twitter_client_id.max' => 'Twitter Client ID en fazla 255 karakter olabilir.',
            'social_twitter_client_secret.max' => 'Twitter Client Secret en fazla 255 karakter olabilir.',
            'social_linkedin_client_id.max' => 'LinkedIn Client ID en fazla 255 karakter olabilir.',
            'social_linkedin_client_secret.max' => 'LinkedIn Client Secret en fazla 255 karakter olabilir.',
            'social_bitbucket_client_id.max' => 'Bitbucket Client ID en fazla 255 karakter olabilir.',
            'social_bitbucket_client_secret.max' => 'Bitbucket Client Secret en fazla 255 karakter olabilir.',
        ];
    }
}
