<?php

defined('ABSPATH') || exit;

class Stitch_Express_Payment_Gateway extends WC_Payment_Gateway {
    private object $logger;

    private $valid_refund_reasons = ['Requested by user', 'Fraud', 'Duplicate'];

    public function __construct() {
        $this->id = 'stitch-express';
        $this->icon = STITCH_EXPRESS_PLUGIN_URL.'/assets/wc-logo-v2.svg';
        $this->has_fields = false;
        $this->title = 'Pay with Apple | Google | Capitec | Card | BNPL';
        $this->description = 'Secure payments powered by Stitch Express';
        $this->method_title = 'Stitch Express';
        $this->method_description = 'Pay with Stitch Express';
        $this->countries = ['ZA'];
        $this->supports = [
            'products',
            'refunds',
        ];
        $this->includes();
        $this->init_form_fields();
        $this->init_settings();
        $this->logger = wc_get_logger();

        add_action('woocommerce_update_options_payment_gateways_'.$this->id, [$this, 'process_admin_options']);
        add_action('wp_ajax_stitch_express_dismiss_webhook_notice', [$this, 'dismiss_webhook_notice']);
    }

    public function needs_setup(): bool {
        return !$this->get_option('client_id') || !$this->get_option('client_secret');
    }

    public function get_option($key, $empty_value = '') {
        if ($key === 'auto_update') {
            $plugin_file = plugin_basename(STITCH_EXPRESS_PLUGIN_PATH.'/stitch-express.php');
            $auto_updates = (array) get_site_option('auto_update_plugins', []);

            return in_array($plugin_file, $auto_updates, true) ? 'yes' : 'no';
        }

        return parent::get_option($key, $empty_value);
    }

    public function process_admin_options(): bool {
        $field_key = $this->get_field_key('auto_update');
        $is_enabled = isset($_POST[$field_key]) && $_POST[$field_key] === '1';
        $plugin_file = plugin_basename(STITCH_EXPRESS_PLUGIN_PATH.'/stitch-express.php');
        $auto_updates = (array) get_site_option('auto_update_plugins', []);
        $currently_enabled = in_array($plugin_file, $auto_updates, true);

        if ($is_enabled && !$currently_enabled) {
            $auto_updates[] = $plugin_file;
            update_site_option('auto_update_plugins', $auto_updates);
        } elseif (!$is_enabled && $currently_enabled) {
            $auto_updates = array_values(array_diff($auto_updates, [$plugin_file]));
            update_site_option('auto_update_plugins', $auto_updates);
        }

        $old_client_id = $this->get_option('client_id');
        $old_client_secret = $this->get_option('client_secret');

        $result = parent::process_admin_options();

        $client_id = $this->get_option('client_id');
        $client_secret = $this->get_option('client_secret');

        $credentials_changed = $client_id !== $old_client_id || $client_secret !== $old_client_secret;

        if ($result && $credentials_changed && $client_id && $client_secret) {
            try {
                $client = new Stitch_Express_Client($client_id, $client_secret);
                $client->register_domain(site_url('/index.php'));
            } catch (Exception $e) {
                $this->logger->error(
                    'Domain registration failed: '.$e->getMessage(),
                    ['source' => 'stitch-express']
                );
            }
        }

        return $result;
    }

    public function includes(): void {
        require_once plugin_dir_path(__FILE__).'stitch-express-client.php';
    }

    public function dismiss_webhook_notice(): void {
        check_ajax_referer('stitch_express_dismiss_webhook_notice', 'nonce');
        update_user_meta(get_current_user_id(), '_stitch_express_webhook_notice_dismissed', '1');
        wp_send_json_success();
    }

    public function admin_options(): void {
        $webhook_url = rest_url('stitch-express/v1/webhook');
        $is_dismissed = get_user_meta(get_current_user_id(), '_stitch_express_webhook_notice_dismissed', true) === '1';

        if (!$is_dismissed) {
            ?>
            <div id="stitch-express-webhook-notice" style="
                background: linear-gradient(135deg, #FFF7ED 0%, #FFFBF5 100%);
                border: 1px solid #F59E0B;
                border-left: 4px solid #F59E0B;
                border-radius: 6px;
                padding: 16px 20px;
                margin: 20px 0;
                display: flex;
                align-items: flex-start;
                gap: 14px;
                max-width: 800px;
                position: relative;
                transition: opacity 0.3s ease, max-height 0.3s ease;
                overflow: hidden;
            ">
                <span style="font-size: 22px; line-height: 1; flex-shrink: 0; margin-top: 1px;">&#9888;</span>
                <div style="flex: 1;">
                    <p style="margin: 0 0 6px; font-weight: 600; font-size: 14px; color: #92400E;">
                        Webhook Firewall Notice
                    </p>
                    <p style="margin: 0 0 10px; color: #78350F; font-size: 13px; line-height: 1.5;">
                        Stitch Express sends payment confirmations to your site via webhooks. If your hosting provider
                        or security plugin (e.g. Cloudflare, Sucuri, Wordfence) blocks incoming POST requests,
                        orders may not update automatically. Please ensure the following URL is allowlisted:
                    </p>
                    <code style="
                        display: inline-block;
                        background: #FFFFFF;
                        border: 1px solid #E5E7EB;
                        border-radius: 4px;
                        padding: 8px 12px;
                        font-size: 12.5px;
                        color: #1F2937;
                        word-break: break-all;
                        line-height: 1.4;
                    "><?php echo esc_html($webhook_url); ?></code>
                </div>
                <button
                    type="button"
                    id="stitch-express-dismiss-webhook-notice"
                    style="
                        background: none;
                        border: none;
                        cursor: pointer;
                        color: #92400E;
                        font-size: 20px;
                        line-height: 1;
                        padding: 0 2px;
                        flex-shrink: 0;
                        opacity: 0.6;
                        transition: opacity 0.15s ease;
                    "
                    onmouseover="this.style.opacity='1'"
                    onmouseout="this.style.opacity='0.6'"
                    title="Dismiss notice"
                >&times;</button>
            </div>
            <script>
                document.getElementById('stitch-express-dismiss-webhook-notice').addEventListener('click', function() {
                    var notice = document.getElementById('stitch-express-webhook-notice');
                    notice.style.opacity = '0';
                    notice.style.maxHeight = '0';
                    notice.style.padding = '0';
                    notice.style.margin = '0';
                    notice.style.border = 'none';

                    var data = new FormData();
                    data.append('action', 'stitch_express_dismiss_webhook_notice');
                    data.append('nonce', '<?php echo esc_js(wp_create_nonce('stitch_express_dismiss_webhook_notice')); ?>');
                    fetch(ajaxurl, { method: 'POST', body: data });
                });
            </script>
        <?php
        }

        parent::admin_options();
    }

    public function init_form_fields(): void {
        $this->form_fields = [
            'enabled' => [
                'title' => __('Enable/Disable', 'stitch-express'),
                'type' => 'checkbox',
                'label' => __('Enable Stitch Express Payments', 'stitch-express'),
                'default' => 'no',
            ],
            'client_id' => [
                'title' => __('Client ID', 'stitch-express'),
                'type' => 'text',
                'description' => __('Stitch Express Client ID', 'stitch-express'),
                'desc_tip' => true,
                'custom_attributes' => [
                    'required' => 'true',
                ],
            ],
            'client_secret' => [
                'title' => __('Client Secret', 'stitch-express'),
                'type' => 'password',
                'description' => __('Stitch Express Client Secret', 'stitch-express'),
                'desc_tip' => true,
                'custom_attributes' => [
                    'required' => 'true',
                ],
            ],
            'redirect_url_info' => [
                'title' => __('Redirect URL', 'stitch-express'),
                'type' => 'title',
                'description' => sprintf(
                    '%s<br><code style="display:inline-block;margin-top:4px;padding:4px 8px;background:#f0f0f1;border-radius:3px;">%s</code>',
                    __('Please add this as a redirect URL on your Stitch Express account page, and ensure this route is not blocked by your firewall or security software.', 'stitch-express'),
                    esc_html(site_url('index.php'))
                ),
            ],
            'skip_checkout' => [
                'title' => __('Skip Checkout Page', 'stitch-express'),
                'type' => 'checkbox',
                'label' => __('Skip the Stitch Express checkout page', 'stitch-express'),
                'default' => 'yes',
            ],
            'auto_update' => [
                'title' => __('Auto-Updates', 'stitch-express'),
                'type' => 'checkbox',
                'label' => __('Automatically update Stitch Express when new versions are released', 'stitch-express'),
                'description' => __('Highly recommended. Ensures your store receives critical security and payment fixes promptly.', 'stitch-express'),
                'default' => 'no',
            ],
            'widget_settings_title' => [
                'title' => __('BNPL Product Widget Settings', 'stitch-express'),
                'type' => 'title',
                'description' => __('Configure the "Buy Now Pay Later" widget that appears on product pages', 'stitch-express'),
            ],
            'widget_enabled' => [
                'title' => __('Enable Product Widget', 'stitch-express'),
                'type' => 'checkbox',
                'label' => __('Show BNPL messaging on product pages', 'stitch-express'),
                'default' => 'no',
            ],
            'widget_auto_display' => [
                'title' => __('Auto-Display Widget', 'stitch-express'),
                'type' => 'checkbox',
                'label' => __('Automatically display widget on all product pages', 'stitch-express'),
                'description' => __('Uncheck to use shortcode [stitch_bnpl_widget] or block for manual placement', 'stitch-express'),
                'default' => 'yes',
            ],
            'widget_position' => [
                'title' => __('Widget Position', 'stitch-express'),
                'type' => 'select',
                'description' => __('Where to display the widget on product pages (only if auto-display is enabled)', 'stitch-express'),
                'default' => 'after_price',
                'options' => [
                    'before_title' => __('Before Product Title', 'stitch-express'),
                    'after_title' => __('After Product Title', 'stitch-express'),
                    'after_price' => __('After Product Price', 'stitch-express'),
                    'after_excerpt' => __('After Product Short Description', 'stitch-express'),
                    'before_add_to_cart' => __('Before Add to Cart Button', 'stitch-express'),
                    'after_add_to_cart' => __('After Add to Cart Button', 'stitch-express'),
                ],
            ],
            'widget_minimum_amount' => [
                'title' => __('Minimum Amount (Rands)', 'stitch-express'),
                'type' => 'number',
                'description' => __('Only show widget for products above this amount (e.g., 100 = R100)', 'stitch-express'),
                'default' => '100',
                'custom_attributes' => [
                    'min' => '0',
                    'step' => '1',
                ],
            ],
            'widget_background_color' => [
                'title' => __('Background Color', 'stitch-express'),
                'type' => 'text',
                'description' => __('Widget background color (hex code)', 'stitch-express'),
                'default' => '#F2F2F2',
                'custom_attributes' => [
                    'placeholder' => '#F2F2F2',
                ],
            ],
            'widget_border_color' => [
                'title' => __('Border Color', 'stitch-express'),
                'type' => 'text',
                'description' => __('Widget border color (hex code)', 'stitch-express'),
                'default' => '#F2F2F2',
                'custom_attributes' => [
                    'placeholder' => '#F2F2F2',
                ],
            ],
            'widget_text_color' => [
                'title' => __('Text Color', 'stitch-express'),
                'type' => 'text',
                'description' => __('Widget text color (hex code)', 'stitch-express'),
                'default' => '#100E13',
                'custom_attributes' => [
                    'placeholder' => '#100E13',
                ],
            ],
            'widget_highlight_color' => [
                'title' => __('Highlight Color', 'stitch-express'),
                'type' => 'text',
                'description' => __('Price amount highlight color (hex code)', 'stitch-express'),
                'default' => '#000000',
                'custom_attributes' => [
                    'placeholder' => '#000000',
                ],
            ],
            'widget_logo_background' => [
                'title' => __('Logo Background', 'stitch-express'),
                'type' => 'select',
                'description' => __('Stitch logo background color', 'stitch-express'),
                'default' => 'purple',
                'options' => [
                    'purple' => __('Purple (Default)', 'stitch-express'),
                    'white' => __('White', 'stitch-express'),
                    'black' => __('Black', 'stitch-express'),
                ],
            ],
            'widget_width' => [
                'title' => __('Widget Width', 'stitch-express'),
                'type' => 'select',
                'description' => __('Widget width on product pages', 'stitch-express'),
                'default' => '100%',
                'options' => [
                    '100%' => __('100% (Full width)', 'stitch-express'),
                    '90%' => __('90%', 'stitch-express'),
                    '80%' => __('80%', 'stitch-express'),
                    '70%' => __('70%', 'stitch-express'),
                    '60%' => __('60%', 'stitch-express'),
                    '50%' => __('50%', 'stitch-express'),
                    'auto' => __('Auto (fit content)', 'stitch-express'),
                ],
            ],
        ];
    }

    public function process_refund($order_id, $amount = null, $reason = ''): bool|WP_Error {
        if ($amount === null || $amount === 0) {
            return true;
        }

        if (!in_array($reason, array_map('strtolower', $this->valid_refund_reasons))) {
            $pretty_reasons = implode(', ', $this->valid_refund_reasons);

            return new WP_Error('invalid_refund_reason', __("Invalid refund reason. Must be one of: {$pretty_reasons}", 'stitch-express'));
        }

        $order = wc_get_order($order_id);
        $payment_id = $order->get_transaction_id();
        $amount_in_cents = (int) ($amount * 100);

        $stitch_express_client = new Stitch_Express_Client($this->get_option('client_id'), $this->get_option('client_secret'));

        try {
            $stitch_express_client->refund_payment($payment_id, $amount_in_cents, $reason);
        } catch (Exception $exception) {
            $this->handle_api_error($exception, 'Payment failed. Please try again.');

            return false;
        }

        return true;
    }

    public function process_payment($order_id): ?array {
        $order = new WC_Order($order_id);
        $order->update_status('awaiting-payment');

        $total_in_cents = (int) ($order->get_total() * 100);

        $payer_email = $order->get_billing_email();
        $payer_phonenumber = $order->get_billing_phone();
        $customer_name = substr(
            $order->get_billing_first_name().
            ' '.
            $order->get_billing_last_name(),
            0,
            20
        );
        $merchant_ref = $this->generate_merchant_reference($order);
        $stitch_express_client = new Stitch_Express_Client($this->get_option('client_id'), $this->get_option('client_secret'));
        $skip_checkout_page = $this->get_option('skip_checkout') === 'yes';

        try {
            $url = $stitch_express_client->create_payment_link($total_in_cents, $customer_name, $payer_phonenumber, $payer_email, $merchant_ref, $skip_checkout_page);
        } catch (Exception $exception) {
            $this->handle_api_error($exception, 'Payment failed. Please try again.');

            return null;
        }

        return [
            'result' => 'success',
            'redirect' => $url.'?'.http_build_query(['redirect_url' => $this->generate_redirect_url()]),
        ];
    }

    private function generate_merchant_reference(WC_Order $order): string {
        return 'WC-'.$order->get_id();
    }

    private function generate_redirect_url(): string {
        $params = http_build_query(['rest_route' => '/stitch-express/v1/callback/']);

        return site_url('/index.php').'?'.$params;
    }

    private function handle_api_error(Exception $exception, string $message): void {
        $this->logger->error($exception, ['source' => 'stitch-express']);
        wc_add_notice($message, 'error');
    }
}
