<?php
/**
 * Guest payment settings, provider registry, and helpers.
 *
 * Guest payment flow (pay at table / Stripe Checkout) and provider configuration.
 *
 * @package Maca_Menu_List
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Whether the site uses online guest payments (Stripe and/or Swish).
 *
 * Master toggle under Payments → Payment flow. Legacy installs without the
 * option fall back to previous Stripe / pay-online checkboxes.
 *
 * @return bool
 */
function maca_menulist_payments_use_online() {
    $stored = get_option('maca_menulist_payments_use_online', null);

    if ($stored === null) {
        return (bool) get_option('maca_menulist_payments_enabled', false)
            || get_option('maca_menulist_payments_allow_online', '1') === '1';
    }

    return $stored === '1';
}

/**
 * Whether Stripe checkout is enabled for guests (requires use online payment).
 *
 * @return bool
 */
function maca_menulist_payments_enabled() {
    if (!maca_menulist_payments_use_online()) {
        return false;
    }

    return (bool) get_option('maca_menulist_payments_enabled', false);
}

require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/provider-stripe.php';
require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/provider-swish.php';
require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/tips.php';
require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/order-payments.php';
require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/bill-split.php';
require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/checkout.php';
require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/combined-checkout.php';
require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/stripe-checkout.php';
require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/order-confirmation-email.php';
require_once MACA_MENULIST_PLUGIN_DIR . 'includes/payments/ajax-guest.php';

/**
 * Whether guest Stripe checkout is available on this site.
 *
 * @return bool
 */
function maca_menulist_payments_checkout_available() {
    return (bool) apply_filters(
        'maca_menulist_payments_checkout_available',
        maca_menulist_payments_online_ready()
    );
}

/**
 * Primary provider id when payments are enabled: stripe, swish, or empty.
 *
 * @return string
 */
function maca_menulist_payments_primary_provider() {
    $id = sanitize_key((string) get_option('maca_menulist_payments_primary_provider', 'stripe'));

    if ($id === '' || !maca_menulist_payments_get_provider($id)) {
        return 'stripe';
    }

    return $id;
}

/**
 * @return array<string, Maca_Menulist_Payment_Provider>
 */
function maca_menulist_payments_get_providers() {
    $providers = array(
        'stripe' => new Maca_Menulist_Payment_Provider_Stripe(),
        'swish'  => new Maca_Menulist_Payment_Provider_Swish(),
    );

    /**
     * Register additional guest payment providers.
     *
     * @param array<string, Maca_Menulist_Payment_Provider> $providers Providers.
     */
    return apply_filters('maca_menulist_payment_providers', $providers);
}

/**
 * @param string $id Provider id.
 * @return Maca_Menulist_Payment_Provider|null
 */
function maca_menulist_payments_get_provider($id) {
    $id = sanitize_key($id);
    $all = maca_menulist_payments_get_providers();

    return isset($all[$id]) ? $all[$id] : null;
}

/**
 * Option name for a provider setting.
 *
 * @param string $provider_id Provider id.
 * @param string $key         Setting key.
 * @return string
 */
function maca_menulist_payments_option_name($provider_id, $key) {
    return 'maca_menulist_payment_' . sanitize_key($provider_id) . '_' . sanitize_key($key);
}

/**
 * @param string $provider_id Provider id.
 * @param string $key         Setting key.
 * @return string
 */
function maca_menulist_payments_get_setting($provider_id, $key) {
    $option = maca_menulist_payments_option_name($provider_id, $key);
    $value = get_option($option, '');

    if (!is_string($value)) {
        return '';
    }

    if (in_array($key, array('secret_key', 'webhook_secret'), true)) {
        return maca_menulist_payments_decrypt_secret($value);
    }

    return $value;
}

/**
 * @param string $provider_id Provider id.
 * @param string $key         Setting key.
 * @param string $value       Plain value.
 * @return void
 */
function maca_menulist_payments_update_setting($provider_id, $key, $value) {
    $option = maca_menulist_payments_option_name($provider_id, $key);

    if (in_array($key, array('secret_key', 'webhook_secret'), true)) {
        $value = maca_menulist_payments_encrypt_secret($value);
    }

    update_option($option, $value, false);
}

/**
 * @param string $plain Plain text.
 * @return string Encrypted base64 or empty.
 */
function maca_menulist_payments_encrypt_secret($plain) {
    $plain = (string) $plain;
    if ($plain === '') {
        return '';
    }

    if (!function_exists('openssl_encrypt')) {
        return base64_encode($plain);
    }

    $key = hash('sha256', wp_salt('maca_menulist_payments'), true);
    $iv = random_bytes(16);
    $encrypted = openssl_encrypt($plain, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);

    if ($encrypted === false) {
        return '';
    }

    return base64_encode($iv . $encrypted);
}

/**
 * @param string $stored Stored value.
 * @return string
 */
function maca_menulist_payments_decrypt_secret($stored) {
    $stored = (string) $stored;
    if ($stored === '') {
        return '';
    }

    if (!function_exists('openssl_decrypt')) {
        $decoded = base64_decode($stored, true);
        return is_string($decoded) ? $decoded : '';
    }

    $raw = base64_decode($stored, true);
    if ($raw === false || strlen($raw) < 17) {
        return '';
    }

    $iv = substr($raw, 0, 16);
    $encrypted = substr($raw, 16);
    $key = hash('sha256', wp_salt('maca_menulist_payments'), true);
    $plain = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);

    return is_string($plain) ? $plain : '';
}

/**
 * REST webhook URL for a provider on this site.
 *
 * @param string $provider_id Provider id.
 * @return string
 */
function maca_menulist_payments_webhook_url($provider_id) {
    return rest_url('maca-menulist/v1/payments/' . sanitize_key($provider_id) . '/webhook');
}

/**
 * Path to the localized payments setup guide markdown file.
 *
 * @return string
 */
function maca_menulist_payments_guide_file() {
    $locale = get_locale();
    $lang = substr($locale, 0, 2);

    if ($lang === 'sv') {
        $file = MACA_MENULIST_PLUGIN_DIR . 'docs/PAYMENTS-GUIDE-sv.md';
    } else {
        $file = MACA_MENULIST_PLUGIN_DIR . 'docs/PAYMENTS-GUIDE-en.md';
    }

    if (!file_exists($file)) {
        $file = MACA_MENULIST_PLUGIN_DIR . 'docs/PAYMENTS-GUIDE-en.md';
    }

    return $file;
}

/**
 * Readiness checklist for admin UI.
 *
 * @return array<int, array{label: string, done: bool, hint: string}>
 */
function maca_menulist_payments_get_checklist() {
    $items = array();

    $items[] = array(
        'label' => __('Table ordering enabled', 'maca-restu-pro'),
        'done' => function_exists('maca_menulist_table_order_enabled') && maca_menulist_table_order_enabled(),
        'hint' => __('Settings → Table ordering', 'maca-restu-pro'),
    );

    $items[] = array(
        'label' => __('Use online payment', 'maca-restu-pro'),
        'done' => maca_menulist_payments_use_online(),
        'hint' => __('Payments → Payment flow', 'maca-restu-pro'),
    );

    $primary = maca_menulist_payments_get_provider(maca_menulist_payments_primary_provider());
    if ($primary) {
        $items[] = array(
            /* translators: %s: provider name */
            'label' => sprintf(__('Primary provider configured (%s)', 'maca-restu-pro'), $primary->get_label()),
            'done' => $primary->is_configured(),
            'hint' => __('Payments → Stripe & Swish', 'maca-restu-pro'),
        );
    }

    $stripe = maca_menulist_payments_get_provider('stripe');
    if ($stripe) {
        $items[] = array(
            'label' => __('Stripe webhook secret saved', 'maca-restu-pro'),
            'done' => maca_menulist_payments_get_setting('stripe', 'webhook_secret') !== '',
            'hint' => __('See setup guide → Stripe step 8', 'maca-restu-pro'),
        );
    }

    $items[] = array(
        'label' => __('Guest payment options active', 'maca-restu-pro'),
        'done' => maca_menulist_payments_guest_flow_enabled(),
        'hint' => __('Payments → Payment flow (timing & methods)', 'maca-restu-pro'),
    );

    $items[] = array(
        'label' => __('Stripe guest checkout ready', 'maca-restu-pro'),
        'done' => maca_menulist_payments_checkout_available(),
        'hint' => __('Stripe keys + webhook secret', 'maca-restu-pro'),
    );

    return $items;
}

/**
 * Whether saving the current POST enables online guest payments that were not active before.
 *
 * @return bool
 */
function maca_menulist_payments_online_pos_ack_required_from_request() {
    $was_use_online = maca_menulist_payments_use_online();
    $new_use_online = !empty($_POST['maca_menulist_payments_use_online']);

    return $new_use_online && !$was_use_online;
}

/**
 * Save payment settings from admin POST.
 *
 * @return true|WP_Error
 */
function maca_menulist_payments_save_settings_from_request() {
    if (!maca_menulist_user_can_manage_payments_settings()) {
        return new WP_Error('forbidden', __('You do not have permission to change payment settings.', 'maca-restu-pro'));
    }

    if (maca_menulist_payments_online_pos_ack_required_from_request()) {
        $ack = isset($_POST['maca_menulist_online_payment_pos_ack'])
            ? sanitize_text_field(wp_unslash($_POST['maca_menulist_online_payment_pos_ack']))
            : '';

        if ($ack !== '1') {
            return new WP_Error(
                'maca_pos_ack',
                __(
                    'You must read and confirm the cash register / online payment notice before enabling online guest payments.',
                    'maca-restu-pro'
                )
            );
        }
    }

    $use_online = !empty($_POST['maca_menulist_payments_use_online']);
    update_option('maca_menulist_payments_use_online', $use_online ? '1' : '0', false);

    if ($use_online) {
        $enabled = !empty($_POST['maca_menulist_payments_enabled']);
        update_option('maca_menulist_payments_enabled', $enabled, false);

        update_option(
            'maca_menulist_payments_allow_online',
            !empty($_POST['maca_menulist_payments_allow_online']) ? '1' : '0',
            false
        );

        $primary = isset($_POST['maca_menulist_payments_primary_provider'])
            ? sanitize_key(wp_unslash($_POST['maca_menulist_payments_primary_provider']))
            : 'stripe';

        if (!maca_menulist_payments_get_provider($primary)) {
            $primary = 'stripe';
        }

        update_option('maca_menulist_payments_primary_provider', $primary, false);
    } else {
        update_option('maca_menulist_payments_enabled', false, false);
        update_option('maca_menulist_payments_allow_online', '0', false);
    }

    $timing = isset($_POST['maca_menulist_payments_timing'])
        ? sanitize_key(wp_unslash($_POST['maca_menulist_payments_timing']))
        : 'after_meal';
    if (!in_array($timing, array('at_order', 'after_meal'), true)) {
        $timing = 'after_meal';
    }
    update_option('maca_menulist_payments_timing', $timing, false);

    update_option(
        'maca_menulist_payments_allow_manual',
        !empty($_POST['maca_menulist_payments_allow_manual']) ? '1' : '0',
        false
    );
    update_option(
        'maca_menulist_payments_allow_bill_split',
        !empty($_POST['maca_menulist_payments_allow_bill_split']) ? '1' : '0',
        false
    );

    if ($use_online) {
        update_option('maca_menulist_tips_enabled', !empty($_POST['maca_menulist_tips_enabled']) ? '1' : '0', false);

        $tips_mode = isset($_POST['maca_menulist_tips_mode'])
            ? sanitize_key(wp_unslash($_POST['maca_menulist_tips_mode']))
            : 'percent';
        if (!in_array($tips_mode, array('percent', 'fixed'), true)) {
            $tips_mode = 'percent';
        }
        update_option('maca_menulist_tips_mode', $tips_mode, false);

        $tips_presets = isset($_POST['maca_menulist_tips_presets'])
            ? sanitize_text_field(wp_unslash($_POST['maca_menulist_tips_presets']))
            : '';
        update_option('maca_menulist_tips_presets', $tips_presets, false);

        update_option('maca_menulist_tips_allow_custom', !empty($_POST['maca_menulist_tips_allow_custom']) ? '1' : '0', false);
        update_option('maca_menulist_tips_allow_none', !empty($_POST['maca_menulist_tips_allow_none']) ? '1' : '0', false);
    }

    $staff_visibility = isset($_POST['maca_menulist_staff_payment_visibility'])
        ? sanitize_key(wp_unslash($_POST['maca_menulist_staff_payment_visibility']))
        : 'waiter';
    if (!in_array($staff_visibility, array('waiter', 'kitchen', 'both'), true)) {
        $staff_visibility = 'waiter';
    }
    update_option('maca_menulist_staff_payment_visibility', $staff_visibility, false);

    if (!$use_online) {
        return true;
    }

    foreach (maca_menulist_payments_get_providers() as $provider) {
        $values = array();

        foreach ($provider->get_setting_keys() as $key) {
            $field = 'maca_payment_' . $provider->get_id() . '_' . $key;

            if (!isset($_POST[$field])) {
                if ($key === 'test_mode' || $key === 'callback_url_verified') {
                    $values[$key] = '0';
                }
                continue;
            }

            $raw = wp_unslash($_POST[$field]);
            if (is_array($raw)) {
                continue;
            }

            $values[$key] = sanitize_text_field($raw);
        }

        if (isset($values['test_mode'])) {
            $values['test_mode'] = $values['test_mode'] === '1' ? '1' : '0';
        }
        if (isset($values['callback_url_verified'])) {
            $values['callback_url_verified'] = $values['callback_url_verified'] === '1' ? '1' : '0';
        }

        $valid = $provider->validate_settings($values);
        if (is_wp_error($valid)) {
            return $valid;
        }

        foreach ($provider->get_setting_keys() as $key) {
            if (!array_key_exists($key, $values)) {
                continue;
            }

            if (
                in_array($key, array('secret_key', 'webhook_secret'), true)
                && !maca_menulist_admin_secret_should_update($values[$key])
            ) {
                continue;
            }

            maca_menulist_payments_update_setting($provider->get_id(), $key, $values[$key]);
        }
    }

    return true;
}

/**
 * Valid payment_status values for orders.
 *
 * @return array<int, string>
 */
function maca_menulist_payment_statuses() {
    return array('none', 'pending', 'partial', 'paid', 'failed', 'refunded', 'cancelled');
}
