<?php

/**
 * Settings helper functions
 *
 * @package ArraySubs\Functions
 */

defined('ABSPATH') || exit;

/**
 * Get default settings
 *
 * @return array
 */
function arraysubs_get_default_settings(): array
{
    return [
        'defaults' => [
            'billing_period' => 'month',
            'billing_interval' => 1,
        ],
        'button_text' => [
            'add_to_cart' => '',
        ],
        'multiple_subscriptions' => [
            'allow_multiple_in_cart' => true,
            'one_per_customer' => false,
            'auto_migrate_on_checkout' => false,
            'one_per_product' => false,
            'allow_mixed_cart' => true,
            'allow_different_cycles' => true,
        ],
        'renewals' => [
            'grace_days_before_on_hold' => 3,
            'grace_days_before_cancel' => 7,
            'invoice_before_due_value' => 6,
            'invoice_before_due_unit' => 'hours',
            'sync_to_billing_cycle' => false,
            'sync_first_charge_mode' => 'prorate',
        ],
        'cancellation' => [
            'cancel_immediately' => true,
            'require_reason' => true,
            'reasons' => [
                ['id' => 'too_expensive', 'key' => 'too_expensive', 'label' => 'Too expensive'],
                ['id' => 'not_using', 'key' => 'not_using', 'label' => 'Not using it enough'],
                ['id' => 'found_alternative', 'key' => 'found_alternative', 'label' => 'Found a better alternative'],
                ['id' => 'missing_features', 'key' => 'missing_features', 'label' => 'Missing features I need'],
                ['id' => 'technical_issues', 'key' => 'technical_issues', 'label' => 'Technical issues'],
                ['id' => 'temporary_pause', 'key' => 'temporary_pause', 'label' => 'Just need a temporary break'],
                ['id' => 'other', 'key' => 'other', 'label' => 'Other'],
            ],
            'retention_offers_enabled' => true,
            'retention_offers' => [
                'discount' => [
                    'enabled' => true,
                    'trigger_reasons' => [],
                    'discount_percent' => 20,
                    'discount_cycles' => 3,       // Number of billing cycles discount applies
                    'headline' => '',
                    'description' => '',
                ],
                'pause' => [
                    'enabled' => true,
                    'trigger_reasons' => [],
                    'max_pause_days' => 30,
                    'headline' => '',
                    'description' => '',
                ],
                'downgrade' => [
                    'enabled' => true,
                    'trigger_reasons' => [],
                    'headline' => '',
                    'description' => '',
                ],
                'skip' => [
                    'enabled' => false,
                    'trigger_reasons' => [],
                    'headline' => '',
                    'description' => '',
                ],
                'contact_support' => [
                    'enabled' => false,
                    'trigger_reasons' => [],
                    'support_url' => '',
                    'headline' => '',
                    'description' => '',
                    'button_text' => '',
                ],
            ],
            'form_builder_enabled' => false,
            'form_config' => [],                  // FormBuilder JSON config for custom cancellation form
        ],
        'plan_switching' => [
            'enabled' => true,
            'allow_upgrades' => true,
            'allow_downgrades' => true,
            'allow_crossgrades' => true,
            'proration_type' => 'prorate_immediately',  // Options: prorate_immediately, apply_at_renewal, no_proration
            'allow_customer_switch' => true,            // Allow customers to initiate switches from portal
            'auto_downgrade_timing' => 'on_expire',     // Options: on_expire, on_cancel, on_trial_expire
        ],
        'proration' => [
            'rounding_method' => 'round',          // Options: round, round_up, round_down
            'switch_fees' => [
                'upgrade' => 0,
                'downgrade' => 0,
                'crossgrade' => 0,
            ],
            'minimum_charge' => 0,                 // Minimum proration charge amount
        ],
        'refunds' => [
            'cancellation_behavior' => 'immediate',  // Options: immediate, end_of_period, none
            'auto_gateway_refund' => true,           // Attempt automatic refund via payment gateway
            'allow_prorated_refunds' => true,        // Allow prorated refunds on cancellation
            'minimum_amount' => 0,                   // Minimum refund amount
        ],
        'feature_manager' => [
            'enabled' => true,                       // Enable Feature Manager
            'show_on_product_page' => true,          // Display features on frontend product page
            'show_in_my_account' => true,            // Display features in customer My Account
            'aggregation_mode' => 'per_subscription', // Options: per_subscription, combine
            'show_comparison' => false,              // Show comparison on upgrade pages
            'my_account_page_title' => '',
            'show_usage_count_in_my_account' => true,
            'show_usage_count_in_admin' => true,
        ],
        'checkout' => [
            'auto_create_account' => true,
            'one_click_mode' => 'default',
            'disable_cart_page' => false,
            'non_subscription_button_text' => '',
        ],
        'trials' => [
            'require_payment_method' => true,
            'one_trial_per_customer' => true,
        ],
        'customer_actions' => [
            'allow_cancellation' => true,
            'allow_reactivation' => true,
        ],
        'pause_subscription' => [
            'enabled' => true,
            'max_duration_days' => 30,
            'max_pauses_per_subscription' => 2,
            'min_days_between_pauses' => 30,
            'customer_can_pause' => false,
            'require_reason' => false,
        ],
        'profile_builder' => [
            'custom_profile_fields_enabled' => true,
            'my_account_menu_items_enabled' => true,
        ],
        'emails' => [
            'admin_email' => '',
            'admin_new_subscription' => true,
            'admin_cancelled' => true,
            'admin_pending_cancellation' => true,
            'admin_payment_failed' => true,
            // Customer emails
            'new_subscription' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'subscription_activated' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'subscription_on_hold' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'subscription_pending_cancellation' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'subscription_cancelled' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'subscription_expired' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'auto_downgrade' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'renewal_upcoming' => [
                'enabled' => true,
                'days_before' => 3,
                'subject' => '',
                'body' => '',
            ],
            'renewal_invoice' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'renewal_payment_received' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'payment_failed' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'trial_started' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'trial_ending' => [
                'enabled' => true,
                'days_before' => 3,
                'subject' => '',
                'body' => '',
            ],
            'trial_converted' => [
                'enabled' => true,
                'subject' => '',
                'body' => '',
            ],
            'expiring_soon' => [
                'enabled' => true,
                'days_before' => 7,
                'subject' => '',
                'body' => '',
            ],
        ],
        'automatic_payments' => [
            'allow_auto_renew_toggle' => false,
        ],
        'members_access' => [
            'enabled' => true,
            'default_redirect_url' => '/pricing',
            'default_message' => 'This content is restricted. Please subscribe to access.',
            'require_login' => true,
            'cache_compatibility' => true,
            'role_mapping_rules' => [],
            'url_rules' => [],
            'cpt_rules' => [],
            'download_rules' => [],
            'download_settings' => [
                'protected_directories' => [],
                'serve_via_php' => false,
                'signed_url_expiry' => 3600,
            ],
        ],
        'toolkit' => [
            'hide_admin_bar'              => false,
            'restrict_wp_admin'           => false,
            'wp_admin_redirect'           => 'my_account',
            'allowed_roles'               => [],
            'hide_wp_login'               => false,
            'wp_login_redirect'           => 'my_account',
            'login_as_user'               => true,
            'multi_login_prevention'      => false,
            'multi_login_max_sessions'    => 1,
            'multi_login_include_admins'  => false,
        ],
        'audit_logging' => [
            'product'  => true,
            'coupon'   => true,
            'email'    => true,
            'settings' => true,
        ],
    ];
}

/**
 * Get all settings merged with defaults
 *
 * @return array
 */
function arraysubs_get_settings(): array
{
    $saved = get_option('arraysubs_settings', []);

    // Legacy 'cart' group migration: older builds stored the mixed-cart and
    // multiple-subscriptions toggles under 'cart', which nothing reads
    // anymore. Map any value into multiple_subscriptions.* when the modern
    // key was never saved, then drop the legacy keys so a stale group can
    // never contradict runtime behavior again.
    if (isset($saved['cart']) && is_array($saved['cart'])) {
        $legacy_map = [
            'allow_mixed_cart'             => 'allow_mixed_cart',
            'allow_multiple_subscriptions' => 'allow_multiple_in_cart',
        ];

        if (isset($saved['multiple_subscriptions']) && !is_array($saved['multiple_subscriptions'])) {
            unset($saved['multiple_subscriptions']);
        }

        foreach ($legacy_map as $legacy_key => $modern_key) {
            if (
                array_key_exists($legacy_key, $saved['cart'])
                && !isset($saved['multiple_subscriptions'][$modern_key])
            ) {
                $saved['multiple_subscriptions'][$modern_key] = (bool) $saved['cart'][$legacy_key];
            }

            unset($saved['cart'][$legacy_key]);
        }

        if (empty($saved['cart'])) {
            unset($saved['cart']);
        }
    }

    $defaults = arraysubs_get_default_settings();
    $settings = arraysubs_merge_settings_recursive($defaults, $saved);

    if (isset($settings['cancellation']['reasons']) && is_array($settings['cancellation']['reasons'])) {
        $settings['cancellation']['reasons'] = arraysubs_normalize_cancellation_reasons($settings['cancellation']['reasons']);
    }

    if (isset($settings['renewals']) && is_array($settings['renewals'])) {
        unset($settings['renewals']['sync_show_at_checkout']);
    }

    if (isset($settings['portal']) && is_array($settings['portal'])) {
        unset(
            $settings['portal']['menu_title'],
            $settings['portal']['menu_position'],
            $settings['portal']['allow_payment_method_change']
        );
    }

    if (isset($settings['feature_manager']) && is_array($settings['feature_manager'])) {
        $settings['feature_manager']['aggregation_mode'] = arraysubs_sanitize_feature_manager_aggregation_mode(
            $settings['feature_manager']['aggregation_mode'] ?? 'per_subscription'
        );
    }

    return $settings;
}

/**
 * Normalize legacy default cancellation reasons.
 *
 * Older stored defaults missed the temporary pause reason. Preserve custom
 * reason lists, but repair the old untouched six-row default list.
 *
 * @param array $reasons Cancellation reason rows.
 * @return array Normalized reason rows.
 */
function arraysubs_normalize_cancellation_reasons(array $reasons): array
{
    $keys = [];

    foreach ($reasons as $reason) {
        if (is_array($reason) && !empty($reason['key'])) {
            $keys[] = (string) $reason['key'];
        }
    }

    $legacy_default_keys = [
        'too_expensive',
        'not_using',
        'found_alternative',
        'missing_features',
        'technical_issues',
        'other',
    ];

    if ($keys !== $legacy_default_keys || in_array('temporary_pause', $keys, true)) {
        return $reasons;
    }

    $normalized = [];

    foreach ($reasons as $reason) {
        if (is_array($reason) && ($reason['key'] ?? '') === 'other') {
            $normalized[] = [
                'id' => 'temporary_pause',
                'key' => 'temporary_pause',
                'label' => 'Just need a temporary break',
            ];
        }

        $normalized[] = $reason;
    }

    return $normalized;
}

/**
 * Sanitize Feature Manager aggregation mode.
 *
 * Keeps older saved values backward-compatible while exposing only the
 * supported current contract to the rest of the codebase.
 *
 * @param mixed $mode Aggregation mode.
 * @return string
 */
function arraysubs_sanitize_feature_manager_aggregation_mode($mode): string
{
    $mode = sanitize_text_field((string) $mode);

    if ($mode === 'per_product') {
        return 'per_subscription';
    }

    if ($mode === 'highest') {
        return 'combine';
    }

    return in_array($mode, ['per_subscription', 'combine'], true)
        ? $mode
        : 'per_subscription';
}

/**
 * Save settings to database
 *
 * Note: update_option() returns false both on failure AND when the value
 * hasn't changed. We compare before saving so unchanged data is not
 * treated as an error.
 *
 * @param array $settings Settings to save
 * @return bool
 */
function arraysubs_save_settings(array $settings): bool
{
    $current = get_option('arraysubs_settings', []);

    // If the stored value already matches, nothing to update — not an error.
    if ($current === $settings) {
        return true;
    }

    $saved = update_option('arraysubs_settings', $settings);

    if ($saved) {
        $changed_keys = arraysubs_get_changed_setting_keys($current, $settings);
        $audit_changes = arraysubs_get_changed_setting_audit_entries($current, $settings);

        if (!empty($changed_keys) && function_exists('arraysubs_add_global_note')) {
            $visible_keys = array_slice($changed_keys, 0, 8);
            $summary      = implode(', ', $visible_keys);
            $actor_id     = get_current_user_id();

            if (count($changed_keys) > 8) {
                $summary .= sprintf(
                    /* translators: %d: number of additional changed settings keys. */
                    __(' and %d more', 'arraysubs'),
                    count($changed_keys) - 8
                );
            }

            arraysubs_add_global_note(
                sprintf(
                    /* translators: %s: comma-separated changed setting keys. */
                    __('Settings updated: %s.', 'arraysubs'),
                    esc_html($summary)
                ),
                'private',
                $actor_id > 0 ? $actor_id : 0,
                $audit_changes,
                'settings'
            );
        }

        do_action('arraysubs_settings_updated', $settings, $current, $changed_keys);
    }

    return $saved;
}

/**
 * Update a single setting using dot notation.
 *
 * @param string $key   Setting key in dot notation.
 * @param mixed  $value Setting value.
 * @return bool
 */
function arraysubs_update_setting(string $key, $value): bool
{
    $settings = arraysubs_get_settings();
    $keys     = array_filter(explode('.', $key), 'strlen');

    if (empty($keys)) {
        return false;
    }

    $cursor = &$settings;

    foreach ($keys as $index => $segment) {
        if ($index === count($keys) - 1) {
            $cursor[$segment] = $value;
            break;
        }

        if (!isset($cursor[$segment]) || !is_array($cursor[$segment])) {
            $cursor[$segment] = [];
        }

        $cursor = &$cursor[$segment];
    }

    return arraysubs_save_settings($settings);
}

/**
 * Recursively collect changed settings keys.
 *
 * @param array  $old    Previous settings.
 * @param array  $new    New settings.
 * @param string $prefix Current key prefix.
 * @return string[]
 */
function arraysubs_get_changed_setting_keys(array $old, array $new, string $prefix = ''): array
{
    $changed  = [];
    $all_keys = array_unique(array_merge(array_keys($old), array_keys($new)));

    foreach ($all_keys as $key) {
        $path      = $prefix === '' ? (string) $key : $prefix . '.' . $key;
        $old_value = $old[$key] ?? null;
        $new_value = $new[$key] ?? null;

        if (is_array($old_value) && is_array($new_value)) {
            if (arraysubs_is_list_array($old_value) || arraysubs_is_list_array($new_value)) {
                if ($old_value !== $new_value) {
                    $changed[] = $path;
                }

                continue;
            }

            $changed = array_merge(
                $changed,
                arraysubs_get_changed_setting_keys($old_value, $new_value, $path)
            );

            continue;
        }

        if ($old_value !== $new_value) {
            $changed[] = $path;
        }
    }

    return array_values(array_unique($changed));
}

/**
 * Recursively build structured setting audit changes.
 *
 * @param array  $old    Previous settings.
 * @param array  $new    New settings.
 * @param string $prefix Current key prefix.
 * @return array<int, array<string, string>>
 */
function arraysubs_get_changed_setting_audit_entries(array $old, array $new, string $prefix = ''): array
{
    $changes  = [];
    $all_keys = array_unique(array_merge(array_keys($old), array_keys($new)));

    foreach ($all_keys as $key) {
        $path      = $prefix === '' ? (string) $key : $prefix . '.' . $key;
        $old_value = $old[$key] ?? null;
        $new_value = $new[$key] ?? null;

        if (is_array($old_value) && is_array($new_value)) {
            if (arraysubs_is_list_array($old_value) || arraysubs_is_list_array($new_value)) {
                if ($old_value !== $new_value) {
                    $changes[] = arraysubs_create_audit_change_entry(
                        $path,
                        arraysubs_format_audit_value($old_value),
                        arraysubs_format_audit_value($new_value)
                    );
                }

                continue;
            }

            $changes = array_merge(
                $changes,
                arraysubs_get_changed_setting_audit_entries($old_value, $new_value, $path)
            );

            continue;
        }

        if ($old_value !== $new_value) {
            $changes[] = arraysubs_create_audit_change_entry(
                $path,
                arraysubs_format_audit_value($old_value),
                arraysubs_format_audit_value($new_value)
            );
        }
    }

    return $changes;
}

/**
 * Determine whether an array is a sequential list.
 *
 * PHP 8.0 compatibility helper for list-style arrays that should be replaced
 * instead of recursively merged with defaults.
 *
 * @param array $array Array to inspect.
 * @return bool
 */
function arraysubs_is_list_array(array $array): bool
{
    if ([] === $array) {
        return true;
    }

    return array_keys($array) === range(0, count($array) - 1);
}

/**
 * Deep merge settings with defaults (recursive)
 *
 * @param array $defaults Default values
 * @param array $saved    Saved values
 * @return array Merged array
 */
function arraysubs_merge_settings_recursive(array $defaults, array $saved): array
{
    if (arraysubs_is_list_array($defaults) && arraysubs_is_list_array($saved)) {
        return $saved;
    }

    $result = $defaults;

    foreach ($saved as $key => $value) {
        if (is_array($value) && isset($result[$key]) && is_array($result[$key])) {
            $result[$key] = arraysubs_merge_settings_recursive($result[$key], $value);
        } else {
            $result[$key] = $value;
        }
    }

    return $result;
}

/**
 * Get a specific setting value using dot notation
 *
 * @param string $key     Setting key in dot notation (e.g., 'renewals.grace_days_before_on_hold')
 * @param mixed  $default Default value if setting not found
 * @return mixed
 */
function arraysubs_get_setting(string $key, $default = null)
{
    $settings = arraysubs_get_settings();
    $keys = explode('.', $key);
    $value = $settings;

    foreach ($keys as $k) {
        if (!isset($value[$k])) {
            return $default;
        }
        $value = $value[$k];
    }

    return $value;
}

// =====================================================
// Convenience Functions for Common Settings Access
// =====================================================

/**
 * Get grace days before subscription goes on-hold
 *
 * @return int
 */
function arraysubs_get_grace_days_before_on_hold(): int
{
    return (int) arraysubs_get_setting('renewals.grace_days_before_on_hold', 3);
}

/**
 * Get grace days before subscription is cancelled
 *
 * @return int
 */
function arraysubs_get_grace_days_before_cancel(): int
{
    return (int) arraysubs_get_setting('renewals.grace_days_before_cancel', 7);
}

/**
 * Get hours before due date to generate invoice
 * Converts the value+unit setting to hours
 *
 * @return int Hours before due date
 */
function arraysubs_get_invoice_hours_before_due(): int
{
    $value = (int) arraysubs_get_setting('renewals.invoice_before_due_value', 6);
    $unit = arraysubs_get_setting('renewals.invoice_before_due_unit', 'hours');

    if ($unit === 'days') {
        return $value * 24;
    }

    return $value;
}

/**
 * Get invoice before due raw settings (value and unit)
 *
 * @return array ['value' => int, 'unit' => string]
 */
function arraysubs_get_invoice_before_due_settings(): array
{
    return [
        'value' => (int) arraysubs_get_setting('renewals.invoice_before_due_value', 6),
        'unit' => arraysubs_get_setting('renewals.invoice_before_due_unit', 'hours'),
    ];
}

/**
 * Check if one subscription per customer is enforced
 *
 * @return bool
 */
function arraysubs_is_one_subscription_per_customer(): bool
{
    return (bool) arraysubs_get_setting('multiple_subscriptions.one_per_customer', false);
}

/**
 * Check if checkout should auto-migrate an existing subscription instead of blocking checkout.
 *
 * This setting only takes effect when one subscription per customer is enabled.
 *
 * @return bool
 */
function arraysubs_can_auto_migrate_subscription_on_checkout(): bool
{
    if (!arraysubs_is_one_subscription_per_customer()) {
        return false;
    }

    return (bool) arraysubs_get_setting('multiple_subscriptions.auto_migrate_on_checkout', false);
}

/**
 * Check if one subscription per product per customer is enforced
 *
 * @return bool
 */
function arraysubs_is_one_subscription_per_product(): bool
{
    return (bool) arraysubs_get_setting('multiple_subscriptions.one_per_product', false);
}

/**
 * Get admin email for notifications
 *
 * @return string
 */
function arraysubs_get_admin_email(): string
{
    $email = arraysubs_get_setting('emails.admin_email', '');
    return !empty($email) ? $email : get_option('admin_email');
}

/**
 * Get add to cart button text
 *
 * @return string
 */
function arraysubs_get_add_to_cart_text(): string
{
    $text = arraysubs_get_setting('button_text.add_to_cart', '');
    return !empty($text) ? $text : __('Subscribe Now', 'arraysubs');
}

/**
 * Check if customer can suspend (pause) a subscription.
 *
 * @return bool
 */
function arraysubs_can_customer_suspend(): bool
{
    if (!(bool) arraysubs_get_setting('pause_subscription.enabled', false)) {
        return false;
    }

    return (bool) arraysubs_get_setting('pause_subscription.customer_can_pause', false);
}

/**
 * Check if customer can change payment method
 *
 * Payment method changes are controlled by gateway capabilities instead of
 * a General Settings toggle. This helper remains for backward compatibility.
 *
 * @return bool
 */
function arraysubs_can_customer_change_payment_method(): bool
{
    return true;
}

/**
 * Check whether custom profile fields are enabled.
 *
 * @return bool
 */
function arraysubs_is_custom_profile_fields_enabled(): bool
{
    return (bool) arraysubs_get_setting('profile_builder.custom_profile_fields_enabled', true);
}

/**
 * Check whether custom My Account menu items are enabled.
 *
 * @return bool
 */
function arraysubs_is_myaccount_menu_items_enabled(): bool
{
    return (bool) arraysubs_get_setting('profile_builder.my_account_menu_items_enabled', true);
}

/**
 * Check if payment method is required for trials
 *
 * @return bool
 */
function arraysubs_trial_requires_payment_method(): bool
{
    return (bool) arraysubs_get_setting('trials.require_payment_method', true);
}

/**
 * Check if one trial per customer is enforced
 *
 * @return bool
 */
function arraysubs_is_one_trial_per_customer(): bool
{
    return (bool) arraysubs_get_setting('trials.one_trial_per_customer', true);
}

/**
 * Get default billing period
 *
 * @return string
 */
function arraysubs_get_default_billing_period(): string
{
    return (string) arraysubs_get_setting('defaults.billing_period', 'month');
}

/**
 * Get default billing interval
 *
 * @return int
 */
function arraysubs_get_default_billing_interval(): int
{
    return (int) arraysubs_get_setting('defaults.billing_interval', 1);
}

/**
 * Check if auto account creation is enabled
 *
 * @return bool
 */
function arraysubs_is_auto_create_account_enabled(): bool
{
    return (bool) arraysubs_get_setting('checkout.auto_create_account', true);
}

/**
 * Get one-click checkout mode.
 *
 * @return string
 */
function arraysubs_get_one_click_checkout_mode(): string
{
    return (string) arraysubs_get_setting('checkout.one_click_mode', 'default');
}

/**
 * Check if one-click checkout is enabled.
 *
 * @return bool
 */
function arraysubs_is_one_click_checkout_enabled(): bool
{
    return arraysubs_get_one_click_checkout_mode() !== 'default';
}

/**
 * Check if one-click checkout is enabled for all items.
 *
 * @return bool
 */
function arraysubs_is_one_click_checkout_for_all_items(): bool
{
    return arraysubs_get_one_click_checkout_mode() === 'all_items';
}

/**
 * Check if the cart page should redirect to checkout.
 *
 * @return bool
 */
function arraysubs_is_cart_page_disabled_for_one_click(): bool
{
    if (!arraysubs_is_one_click_checkout_enabled()) {
        return false;
    }

    return (bool) arraysubs_get_setting('checkout.disable_cart_page', false);
}

/**
 * Get one-click button text for non-subscription items.
 *
 * @return string
 */
function arraysubs_get_one_click_non_subscription_button_text(): string
{
    return (string) arraysubs_get_setting('checkout.non_subscription_button_text', '');
}

/**
 * Check whether a product should be treated like a subscription item for checkout behavior.
 *
 * @param int $product_id Product or variation ID.
 * @return bool
 */
function arraysubs_is_subscription_checkout_product(int $product_id): bool
{
    if ($product_id <= 0) {
        return false;
    }

    $is_subscription = function_exists('arraysubs_is_subscription_product')
        && arraysubs_is_subscription_product($product_id);

    /**
     * Filter whether a product should use subscription-style checkout behavior.
     *
     * This allows addon features like store credit purchases to reuse the same
     * one-click checkout rules without duplicating core checkout logic.
     *
     * @param bool $is_subscription Whether the product already qualifies.
     * @param int  $product_id       Product or variation ID.
     */
    return (bool) apply_filters('arraysubs_is_subscription_checkout_product', $is_subscription, $product_id);
}

/**
 * Check whether a product should use one-click checkout behavior.
 *
 * @param int $product_id Product or variation ID.
 * @return bool
 */
function arraysubs_is_one_click_checkout_product(int $product_id): bool
{
    $mode = arraysubs_get_one_click_checkout_mode();

    if ($mode === 'all_items') {
        return $product_id > 0;
    }

    if ($mode !== 'subscription_items') {
        return false;
    }

    return arraysubs_is_subscription_checkout_product($product_id);
}

/**
 * Check if cancellation should be immediate (vs end of billing period)
 *
 * @return bool True for immediate cancellation, false for end of billing period
 */
function arraysubs_cancel_immediately(): bool
{
    return (bool) arraysubs_get_setting('cancellation.cancel_immediately', true);
}

/**
 * Check if cancellation reason is required
 *
 * @return bool
 */
function arraysubs_require_cancel_reason(): bool
{
    return (bool) arraysubs_get_setting('cancellation.require_reason', true);
}

// =====================================================
// Cancellation Flow & Retention Offers Settings
// =====================================================

/**
 * Check if retention offers are enabled
 *
 * @return bool
 */
function arraysubs_is_retention_offers_enabled(): bool
{
    return (bool) arraysubs_get_setting('cancellation.retention_offers_enabled', true);
}

/**
 * Get enabled retention offer types
 *
 * @return array Array of enabled offer type IDs
 */
function arraysubs_get_enabled_retention_offers(): array
{
    $offers = arraysubs_get_setting('cancellation.retention_offers', []);
    $enabled = [];

    foreach ($offers as $offer_id => $offer_config) {
        if (isset($offer_config['enabled']) && $offer_config['enabled']) {
            $enabled[] = $offer_id;
        }
    }

    return $enabled;
}

/**
 * Check if customer-initiated plan switching is allowed
 *
 * @return bool
 */
function arraysubs_is_customer_switch_allowed(): bool
{
    if (!arraysubs_get_setting('plan_switching.enabled', true)) {
        return false;
    }
    return (bool) arraysubs_get_setting('plan_switching.allow_customer_switch', true);
}

/**
 * Check if prorated refunds are allowed
 *
 * @return bool
 */
function arraysubs_is_prorated_refund_allowed(): bool
{
    return (bool) arraysubs_get_setting('refunds.allow_prorated_refunds', true);
}

/**
 * Get the normalized Feature Manager aggregation mode.
 *
 * @return string
 */
function arraysubs_get_feature_manager_aggregation_mode(): string
{
    return arraysubs_sanitize_feature_manager_aggregation_mode(
        arraysubs_get_setting('feature_manager.aggregation_mode', 'per_subscription')
    );
}

/**
 * Get the My Account page title for Feature Manager.
 *
 * @return string
 */
function arraysubs_get_feature_manager_my_account_page_title(): string
{
    $title = arraysubs_get_setting('feature_manager.my_account_page_title', '');

    return !empty($title) ? (string) $title : __('My Features', 'arraysubs');
}

/**
 * Check whether usage counts should be shown in My Account.
 *
 * @return bool
 */
function arraysubs_show_feature_usage_in_my_account(): bool
{
    return (bool) arraysubs_get_setting('feature_manager.show_usage_count_in_my_account', true);
}

/**
 * Check whether usage counts should be shown in admin feature views.
 *
 * @return bool
 */
function arraysubs_show_feature_usage_in_admin(): bool
{
    return (bool) arraysubs_get_setting('feature_manager.show_usage_count_in_admin', true);
}
