<?php

namespace Bricksforge\ProForms\Actions;

if (!defined('ABSPATH')) exit; // Exit if accessed directly

// Include Mollie SDK
require_once BRICKSFORGE_PATH . '/includes/vendor/mollie/init.php';

// Include Payment Helper for common payment validation
require_once BRICKSFORGE_PATH . '/includes/elements/pro-forms/actions/PaymentHelper.php';

/**
 * Mollie Payment Action
 * 
 * Creates a Mollie payment and redirects the user to the payment page.
 * Supports all payment methods configured in the Mollie dashboard.
 * 
 * @since 3.1.8
 */
class Mollie
{
    public $name = "mollie";

    /**
     * Create Mollie payment and redirect user to payment page
     *
     * @param object $form Form object with access to form data and methods
     * @return array Result array with redirect URL or error
     * @since 3.1.8
     */
    public function run($form)
    {
        $form_settings = $form->get_settings();
        $form_fields   = $form->get_fields();
        $form_files    = $form->get_uploaded_files();
        $post_id       = $form->get_post_id();
        $form_id       = $form->get_form_id();

        try {
            // Get Mollie API key from element settings
            $activated_elements = get_option('brf_activated_elements');
            $mollie_settings = null;

            if (is_array($activated_elements)) {
                foreach ($activated_elements as $element) {
                    if (isset($element->id) && $element->id === 5) {
                        $mollie_settings = isset($element->settings) ? $element->settings : null;
                        break;
                    }
                }
            }

            if (empty($mollie_settings) || empty($mollie_settings->mollieApiKey)) {
                $form->set_result([
                    'action'  => $this->name,
                    'type'    => 'error',
                    'message' => __('Mollie is not configured. Please add your API key in the Pro Forms settings.', 'bricksforge'),
                ]);
                return ['mollie_redirect' => false];
            }

            $utils = new \Bricksforge\Api\Utils();

            // Decrypt API key
            $api_key = $utils->decrypt($mollie_settings->mollieApiKey);

            if (empty($api_key)) {
                $form->set_result([
                    'action'  => $this->name,
                    'type'    => 'error',
                    'message' => __('Mollie API key is missing. Please check your configuration.', 'bricksforge'),
                ]);
                return ['mollie_redirect' => false];
            }

            // Initialize Mollie client
            $mollie = new \Mollie\Api\MollieApiClient();
            $mollie->setApiKey($api_key);

            // Get payment amount - support dynamic values from form fields
            $amount_raw = isset($form_settings['mollieAmount']) ? $form->get_form_field_by_id($form_settings['mollieAmount']) : 0;

            // Validate and sanitize amount
            if (!is_numeric($amount_raw) || $amount_raw <= 0) {
                $form->set_result([
                    'action'  => $this->name,
                    'type'    => 'error',
                    'message' => isset($form_settings['mollieErrorMessage']) ? $form_settings['mollieErrorMessage'] : __('Invalid payment amount.', 'bricksforge'),
                ]);
                return ['mollie_redirect' => false];
            }

            // SECURITY: Validate calculation field to prevent price manipulation
            // If the amount comes from a calculation field, we MUST recalculate it server-side
            $price_field = isset($form_settings['mollieAmount']) ? $form_settings['mollieAmount'] : null;
            $is_calculation_valid = PaymentHelper::validate_payment_calculation($amount_raw, $price_field, $post_id, $form);

            if (!$is_calculation_valid) {
                error_log('Bricksforge Mollie Security: Calculation field validation failed. Possible price manipulation attempt.');

                $form->set_result([
                    'action'  => $this->name,
                    'type'    => 'error',
                    'message' => isset($form_settings['mollieErrorMessage']) ? $form_settings['mollieErrorMessage'] : __('Payment amount validation failed. Please try again.', 'bricksforge'),
                ]);
                return ['mollie_redirect' => false];
            }

            // Get currency (default to EUR for Mollie)
            $currency = isset($form_settings['mollieCurrency']) ? strtoupper(sanitize_text_field($form_settings['mollieCurrency'])) : 'EUR';

            // Format amount for Mollie (string with 2 decimals, e.g., "10.00")
            $amount_formatted = number_format(floatval($amount_raw), 2, '.', '');

            // Get description
            $description = isset($form_settings['mollieDescription']) ? $form->get_form_field_by_id($form_settings['mollieDescription']) : 'Payment';
            $description = sanitize_text_field($description);

            // Get form page URL
            $form_page_url = get_permalink($post_id);

            // If we have a referer header, use that as it's more accurate
            if (isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER'])) {
                $referer = esc_url_raw($_SERVER['HTTP_REFERER']);
                // Only use referer if it's from the same site
                if (strpos($referer, home_url()) === 0) {
                    $form_page_url = $referer;
                }
            }

            // IMPORTANT: Always redirect back to form page after payment
            // This ensures all frontend actions can be executed properly
            // The actual Thank You URL will be used for redirection AFTER webhook completion
            $redirect_url = add_query_arg([
                'payment_status' => 'success',
                'payment_provider' => 'mollie'
            ], $form_page_url);

            // Store the custom Thank You URL separately (if provided)
            // This will be used for final redirection after webhook completes
            $thank_you_url = null;
            if (isset($form_settings['mollieSuccessUrl']) && !empty($form_settings['mollieSuccessUrl'])) {
                $thank_you_url = $form->get_form_field_by_id($form_settings['mollieSuccessUrl']);
                $thank_you_url = esc_url_raw($thank_you_url);
            }

            // Generate unique session identifier
            $session_identifier = wp_generate_password(32, false);

            // Webhook URL - Mollie will call this when payment status changes
            // Check if custom webhook URL is set (for local development with tunnels)
            if (!empty($mollie_settings->mollieWebhookUrl)) {
                $webhook_url = rtrim($utils->decrypt($mollie_settings->mollieWebhookUrl), '/');
                // Ensure it ends with the correct endpoint
                if (strpos($webhook_url, '/mollie-webhook') === false) {
                    $webhook_url .= '/wp-json/bricksforge/v1/mollie-webhook';
                }
            } else {
                $webhook_url = rest_url('bricksforge/v1/mollie-webhook');
            }

            // Store form submission data temporarily (expires in 30 minutes)
            // This will be retrieved by the webhook handler
            $transient_key = 'brf_mollie_session_' . $session_identifier;
            $transient_data = [
                'form_id'       => $form_id,
                'post_id'       => $post_id,
                'form_data'     => $form_fields,
                'form_settings' => $form_settings,
                'form_files'    => $form_files,
                'thank_you_url' => $thank_you_url, // Store custom Thank You URL for final redirect
                'timestamp'     => time(),
            ];

            set_transient($transient_key, $transient_data, 30 * MINUTE_IN_SECONDS);

            // Get customer email if provided
            $customer_email = null;
            if (isset($form_settings['mollieCustomerEmail']) && !empty($form_settings['mollieCustomerEmail'])) {
                $customer_email = $form->get_form_field_by_id($form_settings['mollieCustomerEmail']);
                $customer_email = sanitize_email($customer_email);
                if (!is_email($customer_email)) {
                    $customer_email = null;
                }
            }

            // Prepare payment parameters
            $payment_params = [
                'amount' => [
                    'currency' => $currency,
                    'value' => $amount_formatted,
                ],
                'description' => $description,
                'redirectUrl' => add_query_arg('session_id', $session_identifier, $redirect_url),
                'webhookUrl' => $webhook_url,
                'metadata' => [
                    'brf_session_identifier' => $session_identifier,
                    'form_id' => $form_id,
                    'post_id' => $post_id,
                    'site_url' => home_url('/'),
                ],
            ];

            // Add customer email if provided
            if (!empty($customer_email)) {
                $payment_params['billingEmail'] = $customer_email;
            }

            // Create payment
            $payment = $mollie->payments->create($payment_params);

            // Store the payment ID in transient for additional verification
            set_transient('brf_mollie_payment_' . $payment->id, $session_identifier, 30 * MINUTE_IN_SECONDS);

            // Get checkout URL
            $checkout_url = $payment->getCheckoutUrl();

            if (empty($checkout_url)) {
                throw new \Exception('Failed to get Mollie checkout URL');
            }

            // Return success with redirect URL and session identifier
            $form->set_result([
                'action'  => $this->name,
                'type'    => 'success',
                'mollie_redirect' => true,
                'redirect_url' => $checkout_url,
                'payment_id' => $payment->id,
                'session_identifier' => $session_identifier, // Used to retrieve pending actions after payment
            ]);

            // Also return the result directly so init.php can access it
            return [
                'action'  => $this->name,
                'type'    => 'success',
                'mollie_redirect' => true,
                'redirect_url' => $checkout_url,
                'payment_id' => $payment->id,
                'session_identifier' => $session_identifier,
            ];
        } catch (\Mollie\Api\Exceptions\ApiException $e) {
            // Mollie API error
            error_log('Bricksforge Mollie Error: ' . $e->getMessage());

            $form->set_result([
                'action'  => $this->name,
                'type'    => 'error',
                'message' => isset($form_settings['mollieErrorMessage']) ? $form_settings['mollieErrorMessage'] : __('Payment processing error. Please try again.', 'bricksforge'),
            ]);

            return ['mollie_redirect' => false];
        } catch (\Exception $e) {
            // General error
            error_log('Bricksforge Mollie Error: ' . $e->getMessage());

            $form->set_result([
                'action'  => $this->name,
                'type'    => 'error',
                'message' => isset($form_settings['mollieErrorMessage']) ? $form_settings['mollieErrorMessage'] : __('An error occurred. Please try again.', 'bricksforge'),
            ]);

            return ['mollie_redirect' => false];
        }
    }
}

