<?php
/**
 * Stripe billing: in-admin plan upgrade (Checkout) and manage (Customer Portal).
 *
 * The WP admin posts to admin-post.php; these handlers call the AskAgento API with the
 * shop's site_id + api_key and 302-redirect the admin to the returned Stripe URL.
 *
 * No Stripe secret is ever handled here - the plugin only knows its own site_id/api_key.
 * The Stripe secret key lives server-side and is used only there.
 *
 * @package Askagento
 */

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

/**
 * Call an authenticated AskAgento billing endpoint.
 *
 * @param string $path    API path, e.g. '/billing/checkout'.
 * @param array  $payload JSON body.
 * @return array|WP_Error Parsed JSON body on success, WP_Error otherwise.
 */
function askagento_billing_request($path, array $payload) {
    if (!function_exists('askagento_get_install_settings') || !function_exists('askagento_get_install_site_id')) {
        return new WP_Error('not_configured', __('AskAgento is not initialised.', 'askagento'));
    }

    $settings = askagento_get_install_settings();
    $site_id  = askagento_get_install_site_id();
    $api_key  = isset($settings['api_key']) ? trim((string) $settings['api_key']) : '';
    $api_url  = rtrim((string) ($settings['api_url'] ?? ''), '/');

    if ($site_id === '' || $api_key === '' || $api_url === '') {
        return new WP_Error('not_configured', __('AskAgento is not connected yet. Finish installation first.', 'askagento'));
    }

    $response = wp_remote_post($api_url . $path, [
        'method'      => 'POST',
        'timeout'     => 30,
        'redirection' => 0,
        'httpversion' => '1.1',
        'blocking'    => true,
        'headers'     => [
            'Content-Type'        => 'application/json',
            'X-Askagento-Site-Id' => $site_id,
            'X-Askagento-Api-Key' => $api_key,
        ],
        'body'        => wp_json_encode($payload),
    ]);

    if (is_wp_error($response)) {
        return $response;
    }

    $code = (int) wp_remote_retrieve_response_code($response);
    $body = json_decode((string) wp_remote_retrieve_body($response), true);

    if ($code < 200 || $code >= 300 || !is_array($body)) {
        $msg = (is_array($body) && !empty($body['error']))
            ? (string) $body['error']
            : sprintf(/* translators: %d: HTTP status code */ __('Billing request failed (HTTP %d).', 'askagento'), $code);
        return new WP_Error('billing_failed', $msg);
    }

    return $body;
}

/**
 * Admin URL of the AskAgento Usage/Plans screen, optionally tagged with a status flag.
 *
 * @param string $flag One of '', 'success', 'cancelled', 'error'.
 * @return string
 */
function askagento_billing_return_url($flag = '') {
    $url = add_query_arg(
        [
            'post_type' => defined('ASKAGENTO_POST_TYPE') ? ASKAGENTO_POST_TYPE : 'product',
            'page'      => 'askagento-settings',
            'tab'       => 'plan',
        ],
        admin_url('edit.php')
    );
    if ($flag !== '') {
        $url = add_query_arg('askagento_billing', $flag, $url);
    }
    return $url;
}

/**
 * Redirect to an external Stripe URL.
 *
 * wp_safe_redirect() would reject the off-site host, so we use wp_redirect() with a
 * raw-escaped URL. The URL is produced by our own trusted API (a Stripe-hosted page).
 *
 * @param string $url
 */
function askagento_billing_redirect_external($url) {
    wp_redirect(esc_url_raw($url)); // phpcs:ignore WordPress.Security.SafeRedirect
    exit;
}

/**
 * admin-post: start a Stripe Checkout Session for the chosen plan sku.
 */
function askagento_billing_handle_checkout() {
    if (!current_user_can('manage_options')) {
        wp_die(esc_html__('You are not allowed to do this.', 'askagento'));
    }
    check_admin_referer('askagento_billing_checkout');

    $sku = isset($_POST['sku']) ? sanitize_text_field(wp_unslash($_POST['sku'])) : '';

    $result = askagento_billing_request('/billing/checkout', [
        'sku'         => $sku,
        'success_url' => askagento_billing_return_url('success'),
        'cancel_url'  => askagento_billing_return_url('cancelled'),
    ]);

    if (is_wp_error($result) || empty($result['url'])) {
        $msg = is_wp_error($result) ? $result->get_error_message() : __('Could not start checkout.', 'askagento');
        set_transient('askagento_billing_notice', ['type' => 'error', 'text' => $msg], 60);
        wp_safe_redirect(askagento_billing_return_url('error'));
        exit;
    }

    askagento_billing_redirect_external($result['url']);
}
add_action('admin_post_askagento_billing_checkout', 'askagento_billing_handle_checkout');

/**
 * admin-post: open the Stripe Customer Portal (switch or cancel a plan).
 */
function askagento_billing_handle_portal() {
    if (!current_user_can('manage_options')) {
        wp_die(esc_html__('You are not allowed to do this.', 'askagento'));
    }
    check_admin_referer('askagento_billing_portal');

    $result = askagento_billing_request('/billing/portal', [
        'return_url' => askagento_billing_return_url(),
    ]);

    if (is_wp_error($result) || empty($result['url'])) {
        $msg = is_wp_error($result) ? $result->get_error_message() : __('Could not open the billing portal.', 'askagento');
        set_transient('askagento_billing_notice', ['type' => 'error', 'text' => $msg], 60);
        wp_safe_redirect(askagento_billing_return_url('error'));
        exit;
    }

    askagento_billing_redirect_external($result['url']);
}
add_action('admin_post_askagento_billing_portal', 'askagento_billing_handle_portal');

/**
 * Render an admin notice for the billing flow (Stripe return flags + transient errors).
 *
 * Call inside the Usage/Plans screen. The plan itself updates asynchronously once the
 * Stripe webhook reaches the API, so "success" tells the user the change is processing.
 */
function askagento_billing_render_notice() {
    $error = get_transient('askagento_billing_notice');
    if (is_array($error) && !empty($error['text'])) {
        delete_transient('askagento_billing_notice');
        printf(
            '<div class="notice notice-error" style="margin:0 0 12px;"><p>%s</p></div>',
            esc_html((string) $error['text'])
        );
    }

    $flag = isset($_GET['askagento_billing']) ? sanitize_key(wp_unslash($_GET['askagento_billing'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    if ($flag === 'success') {
        printf(
            '<div class="notice notice-success is-dismissible" style="margin:0 0 12px;"><p>%s</p></div>',
            esc_html__('Thanks! Your plan change is being processed and will appear here shortly.', 'askagento')
        );
    } elseif ($flag === 'cancelled') {
        printf(
            '<div class="notice notice-warning is-dismissible" style="margin:0 0 12px;"><p>%s</p></div>',
            esc_html__('Checkout cancelled. Your plan was not changed.', 'askagento')
        );
    }
}
