<?php

namespace ArraySubs\Features\MainAdmin\REST;

use ArraySubs\Supports\BaseRestController;
use ArraySubs\Supports\Config;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

/**
 * Settings REST Controller
 *
 * Handles REST API endpoints for settings management.
 */
class SettingsController extends BaseRestController
{

    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Register REST API routes.
     *
     * @return void
     */
    public function registerRoutes(): void
    {
        // Get settings data
        \register_rest_route(
            $this->namespace,
            '/settings/data',
            [
                'methods' => 'GET',
                'callback' => [$this, 'getData'],
                'permission_callback' => [$this, 'checkAdminPermission'],
            ]
        );

        // Save settings
        \register_rest_route(
            $this->namespace,
            '/settings/save',
            [
                'methods' => 'POST',
                'callback' => [$this, 'saveSettings'],
                'permission_callback' => [$this, 'checkAdminPermission'],
                'args' => [
                    'settings' => [
                        'required' => true,
                        'type' => 'object',
                        'description' => \esc_html__('Settings data to save', 'arraysubs'),
                    ],
                ],
            ]
        );

        // Reset settings to defaults
        \register_rest_route(
            $this->namespace,
            '/settings/reset',
            [
                'methods' => 'POST',
                'callback' => [$this, 'resetSettings'],
                'permission_callback' => [$this, 'checkAdminPermission'],
            ]
        );
    }

    /**
     * Check admin permission for settings endpoints.
     *
     * @return bool
     */
    public function checkAdminPermission(): bool
    {
        return current_user_can('manage_woocommerce') || current_user_can('manage_options');
    }

    /**
     * Get settings data.
     *
     * @return WP_REST_Response|WP_Error
     */
    public function getData()
    {
        $settings = arraysubs_get_settings();

        return arraysubs_rest_response(
            ['values' => $settings],
            200,
            \esc_html__('Settings retrieved', 'arraysubs')
        );
    }

    /**
     * Save settings.
     *
     * @param WP_REST_Request $request Request object.
     * @return WP_REST_Response|WP_Error
     */
    public function saveSettings(WP_REST_Request $request)
    {
        $settings = $request->get_param('settings');

        if (!is_array($settings)) {
            return arraysubs_rest_response(
                [],
                400,
                \esc_html__('Invalid settings data', 'arraysubs')
            );
        }

        $sanitized = $this->filterSanitizedSettingsToPayloadShape(
            $this->sanitizeSettings($settings),
            $settings
        );

        // Merge sanitized partial payload with existing stored settings so
        // saving one page/field does not wipe sibling settings.
        $existing = get_option('arraysubs_settings', []);
        if (is_array($existing)) {
            $sanitized = arraysubs_merge_settings_recursive($existing, $sanitized);
        }

        // Detect invoice-lead-time changes BEFORE the option is updated so
        // we can re-anchor scheduled invoice generation jobs against the
        // new value. Live subscriptions have already-queued AS jobs at the
        // OLD offset; without rescheduling, the change only applies to
        // future renewals.
        $previous_invoice_value = isset($existing['renewals']['invoice_before_due_value']) ? (int) $existing['renewals']['invoice_before_due_value'] : null;
        $previous_invoice_unit  = $existing['renewals']['invoice_before_due_unit'] ?? null;
        $new_invoice_value      = isset($sanitized['renewals']['invoice_before_due_value']) ? (int) $sanitized['renewals']['invoice_before_due_value'] : null;
        $new_invoice_unit       = $sanitized['renewals']['invoice_before_due_unit'] ?? null;
        $invoice_lead_changed = (
            $new_invoice_value !== null
            && (
                $previous_invoice_value !== $new_invoice_value
                || $previous_invoice_unit !== $new_invoice_unit
            )
        );

        $saved = arraysubs_save_settings($sanitized);

        if (!$saved) {
            return arraysubs_rest_response(
                [],
                500,
                \esc_html__('Failed to save settings', 'arraysubs')
            );
        }

        // Update Config for current request
        Config::add('settings', arraysubs_get_settings());

        if ($invoice_lead_changed && class_exists(\ArraySubs\Features\RecurringBilling\Services\RenewalScheduler::class)) {
            \ArraySubs\Features\RecurringBilling\Services\RenewalScheduler::rescheduleAllInvoicesForSettingsChange();
        }

        return arraysubs_rest_response(
            ['values' => arraysubs_get_settings()],
            200,
            \esc_html__('Settings saved successfully', 'arraysubs')
        );
    }

    /**
     * Reset settings to defaults.
     *
     * @return WP_REST_Response|WP_Error
     */
    public function resetSettings()
    {
        delete_option('arraysubs_settings');

        $defaults = arraysubs_get_default_settings();
        Config::add('settings', $defaults);

        return arraysubs_rest_response(
            ['values' => $defaults],
            200,
            \esc_html__('Settings reset to defaults', 'arraysubs')
        );
    }

    /**
     * Sanitize all settings
     *
     * @param array $settings Settings to sanitize
     * @return array Sanitized settings
     */
    private function sanitizeSettings(array $settings): array
    {
        $sanitized = [];

        // Defaults
        if (isset($settings['defaults'])) {
            $sanitized['defaults'] = [
                'billing_period' => $this->sanitizeEnum(
                    $settings['defaults']['billing_period'] ?? 'month',
                    ['day', 'week', 'month', 'year', 'lifetime'],
                    'month'
                ),
                'billing_interval' => $this->sanitizeInt($settings['defaults']['billing_interval'] ?? 1, 1, 365),
            ];
        }

        // Button text
        if (isset($settings['button_text'])) {
            $sanitized['button_text'] = [
                'add_to_cart' => sanitize_text_field($settings['button_text']['add_to_cart'] ?? ''),
                'place_order' => sanitize_text_field($settings['button_text']['place_order'] ?? ''),
            ];
        }

        // Multiple subscriptions
        if (isset($settings['multiple_subscriptions'])) {
            $sanitized['multiple_subscriptions'] = [
                'allow_multiple_in_cart' => (bool) ($settings['multiple_subscriptions']['allow_multiple_in_cart'] ?? true),
                'one_per_customer' => (bool) ($settings['multiple_subscriptions']['one_per_customer'] ?? false),
                'auto_migrate_on_checkout' => (bool) ($settings['multiple_subscriptions']['auto_migrate_on_checkout'] ?? false),
                'one_per_product' => (bool) ($settings['multiple_subscriptions']['one_per_product'] ?? false),
                'allow_mixed_cart' => (bool) ($settings['multiple_subscriptions']['allow_mixed_cart'] ?? true),
                'allow_different_cycles' => (bool) ($settings['multiple_subscriptions']['allow_different_cycles'] ?? true),
            ];
        }

        // Renewals
        if (isset($settings['renewals'])) {
            $unit = sanitize_text_field($settings['renewals']['invoice_before_due_unit'] ?? 'hours');
            $valid_units = ['hours', 'days'];
            $unit = in_array($unit, $valid_units, true) ? $unit : 'hours';
            $sync_first_charge_mode = $this->sanitizeEnum(
                $settings['renewals']['sync_first_charge_mode'] ?? 'prorate',
                ['prorate', 'full'],
                'prorate'
            );

            $sanitized['renewals'] = [
                'grace_days_before_on_hold' => $this->sanitizeInt($settings['renewals']['grace_days_before_on_hold'] ?? 3, 0, 30),
                'grace_days_before_cancel' => $this->sanitizeInt($settings['renewals']['grace_days_before_cancel'] ?? 7, 1, 60),
                'invoice_before_due_value' => $this->sanitizeInt($settings['renewals']['invoice_before_due_value'] ?? 6, 1, 30),
                'invoice_before_due_unit' => $unit,
                'sync_to_billing_cycle' => (bool) ($settings['renewals']['sync_to_billing_cycle'] ?? false),
                'sync_first_charge_mode' => $sync_first_charge_mode,
            ];
        }

        // Automatic Payments
        if (isset($settings['automatic_payments'])) {
            $sanitized['automatic_payments'] = [
                'allow_auto_renew_toggle' => (bool) ($settings['automatic_payments']['allow_auto_renew_toggle'] ?? false),
            ];
        }

        // Feature Manager
        if (isset($settings['feature_manager'])) {
            $sanitized['feature_manager'] = [
                'enabled' => (bool) ($settings['feature_manager']['enabled'] ?? true),
                'show_on_product_page' => (bool) ($settings['feature_manager']['show_on_product_page'] ?? true),
                'show_in_my_account' => (bool) ($settings['feature_manager']['show_in_my_account'] ?? true),
                'aggregation_mode' => arraysubs_sanitize_feature_manager_aggregation_mode(
                    $settings['feature_manager']['aggregation_mode'] ?? 'per_subscription'
                ),
                'show_comparison' => (bool) ($settings['feature_manager']['show_comparison'] ?? false),
                'my_account_page_title' => sanitize_text_field($settings['feature_manager']['my_account_page_title'] ?? ''),
                'show_usage_count_in_my_account' => (bool) ($settings['feature_manager']['show_usage_count_in_my_account'] ?? true),
                'show_usage_count_in_admin' => (bool) ($settings['feature_manager']['show_usage_count_in_admin'] ?? true),
            ];
        }

        // Checkout
        if (isset($settings['checkout'])) {
            $sanitized['checkout'] = [
                'auto_create_account' => (bool) ($settings['checkout']['auto_create_account'] ?? true),
                'one_click_mode' => $this->sanitizeEnum(
                    $settings['checkout']['one_click_mode'] ?? 'default',
                    ['default', 'subscription_items', 'all_items'],
                    'default'
                ),
                'disable_cart_page' => (bool) ($settings['checkout']['disable_cart_page'] ?? false),
                'non_subscription_button_text' => sanitize_text_field($settings['checkout']['non_subscription_button_text'] ?? ''),
            ];
        }

        // Trials
        if (isset($settings['trials'])) {
            $sanitized['trials'] = [
                'require_payment_method' => (bool) ($settings['trials']['require_payment_method'] ?? true),
                'one_trial_per_customer' => (bool) ($settings['trials']['one_trial_per_customer'] ?? true),
            ];
        }

        // Customer Actions
        if (isset($settings['customer_actions'])) {
            $sanitized['customer_actions'] = [
                'allow_cancellation' => (bool) ($settings['customer_actions']['allow_cancellation'] ?? true),
                'allow_reactivation' => (bool) ($settings['customer_actions']['allow_reactivation'] ?? true),
            ];
        }

        // Profile Builder
        if (isset($settings['profile_builder'])) {
            $sanitized['profile_builder'] = [
                'custom_profile_fields_enabled' => (bool) ($settings['profile_builder']['custom_profile_fields_enabled'] ?? true),
                'my_account_menu_items_enabled' => (bool) ($settings['profile_builder']['my_account_menu_items_enabled'] ?? true),
            ];
        }

        // Emails
        if (isset($settings['emails'])) {
            $sanitized['emails'] = $this->sanitizeEmailSettings($settings['emails']);
        }

        // Skip Renewal
        if (isset($settings['skip_renewal'])) {
            $sanitized['skip_renewal'] = [
                'enabled' => (bool) ($settings['skip_renewal']['enabled'] ?? true),
                'max_cycles' => $this->sanitizeInt($settings['skip_renewal']['max_cycles'] ?? 3, 1, 12),
                'cutoff_days' => $this->sanitizeInt($settings['skip_renewal']['cutoff_days'] ?? 2, 0, 30),
                'customer_can_skip' => (bool) ($settings['skip_renewal']['customer_can_skip'] ?? true),
            ];
        }

        // Pause Subscription
        if (isset($settings['pause_subscription'])) {
            $sanitized['pause_subscription'] = [
                'enabled' => (bool) ($settings['pause_subscription']['enabled'] ?? true),
                'max_duration_days' => $this->sanitizeInt($settings['pause_subscription']['max_duration_days'] ?? 30, 1, 365),
                'max_pauses_per_subscription' => $this->sanitizeInt($settings['pause_subscription']['max_pauses_per_subscription'] ?? 2, 1, 10),
                'min_days_between_pauses' => $this->sanitizeInt($settings['pause_subscription']['min_days_between_pauses'] ?? 30, 0, 365),
                'customer_can_pause' => (bool) ($settings['pause_subscription']['customer_can_pause'] ?? false),
                'require_reason' => (bool) ($settings['pause_subscription']['require_reason'] ?? false),
            ];
        }

        // Store Credit
        if (isset($settings['store_credit'])) {
            $sanitized['store_credit'] = [
                'enabled' => (bool) ($settings['store_credit']['enabled'] ?? true),
                'auto_apply_to_renewals' => (bool) ($settings['store_credit']['auto_apply_to_renewals'] ?? true),
                'apply_at_checkout' => (bool) ($settings['store_credit']['apply_at_checkout'] ?? false),
                'min_order_amount' => $this->sanitizeFloat($settings['store_credit']['min_order_amount'] ?? 0, 0, 100000),
                'expiration_days' => $this->sanitizeInt($settings['store_credit']['expiration_days'] ?? 0, 0, 3650),
                'enable_purchase' => (bool) ($settings['store_credit']['enable_purchase'] ?? false),
                'min_purchase_amount' => $this->sanitizeFloat($settings['store_credit']['min_purchase_amount'] ?? 10, 0, 100000),
                'max_purchase_amount' => $this->sanitizeFloat($settings['store_credit']['max_purchase_amount'] ?? 500, 0, 100000),
                'default_purchase_amount' => $this->sanitizeFloat($settings['store_credit']['default_purchase_amount'] ?? 50, 0, 100000),
            ];
        }

        // Cancellation
        if (isset($settings['cancellation'])) {
            // Sanitize custom reasons from repeater
            $reasons = [];
            $has_custom_reasons = isset($settings['cancellation']['reasons']) && is_array($settings['cancellation']['reasons']);

            if ($has_custom_reasons) {
                foreach ($settings['cancellation']['reasons'] as $reason) {
                    if (is_array($reason) && !empty($reason['key']) && !empty($reason['label'])) {
                        $reasons[] = [
                            'id' => sanitize_key($reason['id'] ?? ''),
                            'key' => sanitize_key($reason['key']),
                            'label' => sanitize_text_field($reason['label']),
                        ];
                    }
                }
            }

            // Default reasons only when the reasons payload is missing entirely.
            if (!$has_custom_reasons) {
                $reasons = [
                    ['id' => 'too_expensive', 'key' => 'too_expensive', 'label' => __('Too expensive', 'arraysubs')],
                    ['id' => 'not_using', 'key' => 'not_using', 'label' => __('Not using it enough', 'arraysubs')],
                    ['id' => 'found_alternative', 'key' => 'found_alternative', 'label' => __('Found a better alternative', 'arraysubs')],
                    ['id' => 'missing_features', 'key' => 'missing_features', 'label' => __('Missing features I need', 'arraysubs')],
                    ['id' => 'technical_issues', 'key' => 'technical_issues', 'label' => __('Technical issues', 'arraysubs')],
                    ['id' => 'temporary_pause', 'key' => 'temporary_pause', 'label' => __('Just need a temporary break', 'arraysubs')],
                    ['id' => 'other', 'key' => 'other', 'label' => __('Other', 'arraysubs')],
                ];
            }

            if (function_exists('arraysubs_normalize_cancellation_reasons')) {
                $reasons = arraysubs_normalize_cancellation_reasons($reasons);
            }

            $sanitized['cancellation'] = [
                'cancel_immediately' => (bool) ($settings['cancellation']['cancel_immediately'] ?? true),
                'require_reason' => (bool) ($settings['cancellation']['require_reason'] ?? true),
                'reasons' => $reasons,
                'retention_offers_enabled' => (bool) ($settings['cancellation']['retention_offers_enabled'] ?? false),
                'retention_offers' => $this->sanitizeRetentionOffers($settings['cancellation']['retention_offers'] ?? []),
            ];
        }

        // Plan Switching
        if (isset($settings['plan_switching'])) {
            $sanitized['plan_switching'] = [
                'enabled' => (bool) ($settings['plan_switching']['enabled'] ?? true),
                'allow_upgrades' => (bool) ($settings['plan_switching']['allow_upgrades'] ?? true),
                'allow_downgrades' => (bool) ($settings['plan_switching']['allow_downgrades'] ?? true),
                'allow_crossgrades' => (bool) ($settings['plan_switching']['allow_crossgrades'] ?? false),
                'allow_customer_switch' => (bool) ($settings['plan_switching']['allow_customer_switch'] ?? true),
                'auto_downgrade_timing' => $this->sanitizeEnum(
                    $settings['plan_switching']['auto_downgrade_timing'] ?? 'on_expire',
                    ['on_expire', 'on_cancel', 'on_trial_expire'],
                    'on_expire'
                ),
                'proration_type' => $this->sanitizeEnum(
                    $settings['plan_switching']['proration_type'] ?? 'prorate_immediately',
                    ['prorate_immediately', 'apply_at_renewal', 'no_proration'],
                    'prorate_immediately'
                ),
            ];
        }

        // Proration
        if (isset($settings['proration'])) {
            $switch_fees = $settings['proration']['switch_fees'] ?? [];
            $sanitized['proration'] = [
                'rounding_method' => $this->sanitizeEnum(
                    $settings['proration']['rounding_method'] ?? 'round',
                    ['round', 'round_up', 'round_down'],
                    'round'
                ),
                'minimum_charge' => $this->sanitizeFloat($settings['proration']['minimum_charge'] ?? 0.50, 0, 1000),
                'switch_fees' => [
                    'upgrade' => $this->sanitizeFloat($switch_fees['upgrade'] ?? 0, 0, 1000),
                    'downgrade' => $this->sanitizeFloat($switch_fees['downgrade'] ?? 0, 0, 1000),
                    'crossgrade' => $this->sanitizeFloat($switch_fees['crossgrade'] ?? 0, 0, 1000),
                ],
            ];
        }

        // Toolkit
        if (isset($settings['toolkit'])) {
            $allowed_roles = [];
            if (isset($settings['toolkit']['allowed_roles']) && is_array($settings['toolkit']['allowed_roles'])) {
                $allowed_roles = array_map('sanitize_key', $settings['toolkit']['allowed_roles']);
                $allowed_roles = array_values(array_filter($allowed_roles));
            }

            $sanitized['toolkit'] = [
                'hide_admin_bar'    => (bool) ($settings['toolkit']['hide_admin_bar'] ?? false),
                'restrict_wp_admin' => (bool) ($settings['toolkit']['restrict_wp_admin'] ?? false),
                'wp_admin_redirect' => $this->sanitizeEnum(
                    $settings['toolkit']['wp_admin_redirect'] ?? 'my_account',
                    ['my_account', 'not_found'],
                    'my_account'
                ),
                'allowed_roles'     => $allowed_roles,
                'hide_wp_login'     => (bool) ($settings['toolkit']['hide_wp_login'] ?? false),
                'wp_login_redirect' => $this->sanitizeEnum(
                    $settings['toolkit']['wp_login_redirect'] ?? 'my_account',
                    ['my_account', 'not_found'],
                    'my_account'
                ),
                'login_as_user'              => (bool) ($settings['toolkit']['login_as_user'] ?? true),
                'multi_login_prevention'     => (bool) ($settings['toolkit']['multi_login_prevention'] ?? false),
                'multi_login_max_sessions'   => $this->sanitizeInt($settings['toolkit']['multi_login_max_sessions'] ?? 1, 1, 100),
                'multi_login_include_admins' => (bool) ($settings['toolkit']['multi_login_include_admins'] ?? false),
            ];
        }

        // Refunds
        if (isset($settings['refunds'])) {
            $sanitized['refunds'] = [
                'cancellation_behavior' => $this->sanitizeEnum(
                    $settings['refunds']['cancellation_behavior'] ?? 'none',
                    ['immediate', 'end_of_period', 'none'],
                    'none'
                ),
                'auto_gateway_refund' => (bool) ($settings['refunds']['auto_gateway_refund'] ?? false),
                'allow_prorated_refunds' => (bool) ($settings['refunds']['allow_prorated_refunds'] ?? true),
                'minimum_amount' => $this->sanitizeFloat($settings['refunds']['minimum_amount'] ?? 1.00, 0, 10000),
            ];
        }

        /**
         * Filter sanitized settings before they are saved.
         *
         * Allows addon plugins to sanitize and persist their own settings
         * sections while reusing the shared core settings controller.
         *
         * @param array              $sanitized Sanitized settings ready to save.
         * @param array              $settings  Raw settings payload from the request.
         * @param SettingsController $controller Current settings controller instance.
         */
        return apply_filters('arraysubs_sanitize_settings', $sanitized, $settings, $this);
    }

    /**
     * Keep only sanitized keys that were present in the incoming payload.
     *
     * Sanitizers provide defaults for full-form saves. REST callers can also
     * send partial payloads, so generated default siblings must not overwrite
     * existing stored settings.
     *
     * @param array $sanitized Sanitized settings.
     * @param array $payload   Raw incoming settings.
     * @return array
     */
    private function filterSanitizedSettingsToPayloadShape(array $sanitized, array $payload): array
    {
        $filtered = [];

        foreach ($sanitized as $key => $value) {
            if (!array_key_exists($key, $payload)) {
                continue;
            }

            $payload_value = $payload[$key];

            if (is_array($value) && is_array($payload_value) && !arraysubs_is_list_array($value) && !arraysubs_is_list_array($payload_value)) {
                $filtered[$key] = $this->filterSanitizedSettingsToPayloadShape($value, $payload_value);
                continue;
            }

            $filtered[$key] = $value;
        }

        return $filtered;
    }

    /**
     * Sanitize email settings section
     *
     * @param array $emails Email settings to sanitize
     * @return array Sanitized email settings
     */
    private function sanitizeEmailSettings(array $emails): array
    {
        $sanitized = [
            'admin_email' => sanitize_email($emails['admin_email'] ?? ''),
            'admin_new_subscription' => (bool) ($emails['admin_new_subscription'] ?? true),
            'admin_cancelled' => (bool) ($emails['admin_cancelled'] ?? true),
            'admin_payment_failed' => (bool) ($emails['admin_payment_failed'] ?? true),
        ];

        $email_types = [
            'new_subscription',
            'subscription_activated',
            'subscription_on_hold',
            'subscription_cancelled',
            'subscription_expired',
            'auto_downgrade',
            'renewal_upcoming',
            'renewal_invoice',
            'renewal_payment_received',
            'payment_failed',
            'trial_started',
            'trial_ending',
            'trial_converted',
            'expiring_soon',
            // Skip & Pause emails
            'subscription_skipped',
            'skip_undone',
            'subscription_paused',
            'subscription_resumed',
            // Store Credit emails
            'credit_added',
            'credit_used',
            'credit_expiring',
            'credit_expired',
        ];

        $emails_with_days = ['renewal_upcoming', 'trial_ending', 'expiring_soon', 'credit_expiring'];

        foreach ($email_types as $type) {
            if (isset($emails[$type])) {
                $sanitized[$type] = [
                    'enabled' => (bool) ($emails[$type]['enabled'] ?? true),
                    'subject' => sanitize_text_field($emails[$type]['subject'] ?? ''),
                    'body' => wp_kses_post($emails[$type]['body'] ?? ''),
                ];

                if (in_array($type, $emails_with_days, true)) {
                    $sanitized[$type]['days_before'] = $this->sanitizeInt($emails[$type]['days_before'] ?? 3, 1, 30);
                }
            }
        }

        return $sanitized;
    }

    /**
     * Sanitize integer within range
     *
     * @param mixed $value Value to sanitize
     * @param int   $min   Minimum value
     * @param int   $max   Maximum value
     * @return int Sanitized integer
     */
    private function sanitizeInt($value, int $min, int $max): int
    {
        return max($min, min($max, absint($value)));
    }

    /**
     * Sanitize enum value
     *
     * @param mixed  $value   Value to sanitize
     * @param array  $allowed Allowed values
     * @param string $default Default value
     * @return string Sanitized enum value
     */
    private function sanitizeEnum($value, array $allowed, string $default): string
    {
        $value = sanitize_text_field($value);
        return in_array($value, $allowed, true) ? $value : $default;
    }

    /**
     * Sanitize float within range
     *
     * @param mixed $value Value to sanitize
     * @param float $min   Minimum value
     * @param float $max   Maximum value
     * @return float Sanitized float
     */
    private function sanitizeFloat($value, float $min, float $max): float
    {
        $value = floatval($value);
        return max($min, min($max, $value));
    }

    /**
     * Sanitize retention offers settings
     *
     * @param array $offers Retention offers settings
     * @return array Sanitized retention offers
     */
    private function sanitizeRetentionOffers(array $offers): array
    {
        $sanitized = [];

        // Discount offer
        if (isset($offers['discount'])) {
            $trigger_reasons = [];
            if (isset($offers['discount']['trigger_reasons']) && is_array($offers['discount']['trigger_reasons'])) {
                $trigger_reasons = array_map('sanitize_key', $offers['discount']['trigger_reasons']);
            }

            $sanitized['discount'] = [
                'enabled' => (bool) ($offers['discount']['enabled'] ?? false),
                'trigger_reasons' => $trigger_reasons,
                'discount_percent' => $this->sanitizeInt($offers['discount']['discount_percent'] ?? 20, 1, 100),
                'discount_cycles' => $this->sanitizeInt($offers['discount']['discount_cycles'] ?? 2, 1, 12),
                'headline' => sanitize_text_field($offers['discount']['headline'] ?? ''),
                'description' => sanitize_textarea_field($offers['discount']['description'] ?? ''),
            ];
        }

        // Pause offer
        if (isset($offers['pause'])) {
            $trigger_reasons = [];
            if (isset($offers['pause']['trigger_reasons']) && is_array($offers['pause']['trigger_reasons'])) {
                $trigger_reasons = array_map('sanitize_key', $offers['pause']['trigger_reasons']);
            }

            $sanitized['pause'] = [
                'enabled' => (bool) ($offers['pause']['enabled'] ?? false),
                'trigger_reasons' => $trigger_reasons,
                'max_pause_days' => $this->sanitizeInt($offers['pause']['max_pause_days'] ?? 30, 7, 90),
                'headline' => sanitize_text_field($offers['pause']['headline'] ?? ''),
                'description' => sanitize_textarea_field($offers['pause']['description'] ?? ''),
            ];
        }

        // Downgrade offer
        if (isset($offers['downgrade'])) {
            $trigger_reasons = [];
            if (isset($offers['downgrade']['trigger_reasons']) && is_array($offers['downgrade']['trigger_reasons'])) {
                $trigger_reasons = array_map('sanitize_key', $offers['downgrade']['trigger_reasons']);
            }

            $sanitized['downgrade'] = [
                'enabled' => (bool) ($offers['downgrade']['enabled'] ?? false),
                'trigger_reasons' => $trigger_reasons,
                'headline' => sanitize_text_field($offers['downgrade']['headline'] ?? ''),
                'description' => sanitize_textarea_field($offers['downgrade']['description'] ?? ''),
            ];
        }

        // Contact Support offer
        if (isset($offers['contact_support'])) {
            $trigger_reasons = [];
            if (isset($offers['contact_support']['trigger_reasons']) && is_array($offers['contact_support']['trigger_reasons'])) {
                $trigger_reasons = array_map('sanitize_key', $offers['contact_support']['trigger_reasons']);
            }

            $sanitized['contact_support'] = [
                'enabled' => (bool) ($offers['contact_support']['enabled'] ?? false),
                'trigger_reasons' => $trigger_reasons,
                'support_url' => esc_url_raw($offers['contact_support']['support_url'] ?? ''),
                'headline' => sanitize_text_field($offers['contact_support']['headline'] ?? ''),
                'description' => sanitize_textarea_field($offers['contact_support']['description'] ?? ''),
                'button_text' => sanitize_text_field($offers['contact_support']['button_text'] ?? ''),
            ];
        }

        return $sanitized;
    }
}
