<?php
defined( 'ABSPATH' ) || exit;

class ChainPay_Gateway extends WC_Payment_Gateway {

    public function __construct() {
        $this->id                 = 'chainpay';
        $this->has_fields         = false;
        $this->method_title       = 'ChainPay Crypto Payments';
        $this->method_description = 'Accept BTC, LTC & 12+ cryptocurrencies directly to your wallet. Non-custodial. Powered by <a href="https://chainpay.store" target="_blank">chainpay.store</a>';
        $this->supports           = array( 'products' );
        $this->icon               = CHAINPAY_URL . 'public/img/chainpay-icon.svg';

        $this->init_form_fields();
        $this->init_settings();

        $this->title       = $this->get_option( 'title', 'Pay with Cryptocurrency' );
        $this->description = $this->get_option( 'description', 'Pay with Bitcoin, Litecoin and 12+ cryptocurrencies directly to our wallet. Non-custodial — funds go straight to our wallet.' );
        $this->enabled     = $this->get_option( 'enabled' );

        add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
        add_action( 'woocommerce_checkout_process',                              array( $this, 'validate_before_checkout' ) );

        // AJAX — both logged-in and guests (checkout page visitors are NOT logged into WP)
        add_action( 'wp_ajax_chainpay_get_invoice',        array( $this, 'ajax_get_invoice' ) );
        add_action( 'wp_ajax_nopriv_chainpay_get_invoice', array( $this, 'ajax_get_invoice' ) );
        add_action( 'wp_ajax_chainpay_poll_status',        array( $this, 'ajax_poll_status' ) );
        add_action( 'wp_ajax_nopriv_chainpay_poll_status', array( $this, 'ajax_poll_status' ) );

        // Payment page intercept
        add_action( 'template_redirect', array( 'ChainPay_Gateway', 'maybe_show_payment_page' ) );
    }

    public function init_form_fields() {
        $this->form_fields = array(
            'enabled' => array(
                'title'   => 'Enable/Disable',
                'type'    => 'checkbox',
                'label'   => 'Enable ChainPay Crypto Payments',
                'default' => 'yes',
            ),
            'title' => array(
                'title'       => 'Title',
                'type'        => 'text',
                'default'     => 'Pay with Cryptocurrency',
                'desc_tip'    => true,
                'description' => 'Shown at WooCommerce checkout.',
            ),
            'description' => array(
                'title'   => 'Description',
                'type'    => 'textarea',
                'default' => 'Pay with Bitcoin, Litecoin and more. Non-custodial — funds go directly to our wallet.',
            ),
        );
    }

    /* ── Validate at checkout (before order created) ──────── */
    public function validate_before_checkout() {
        if ( ! isset( $_POST['payment_method'] ) || 'chainpay' !== sanitize_text_field( $_POST['payment_method'] ) ) {
            return;
        }

        if ( ChainPay_License::is_over_free_limit() ) {
            wc_add_notice(
                sprintf(
                    'ChainPay: You have reached the %d payments/month free limit. <a href="%s" target="_blank">Upgrade to Pro for unlimited payments →</a>',
                    CHAINPAY_FREE_LIMIT,
                    'https://chainpay.store/pricing'
                ),
                'error'
            );
        }
    }

    /* ── Process payment ─────────────────────────────────────── */
    public function process_payment( $order_id ) {
        $order = wc_get_order( $order_id );
        if ( ! $order ) {
            wc_add_notice( 'ChainPay: Order not found.', 'error' );
            return array( 'result' => 'failure' );
        }

        // Server-side limit check (defence in depth)
        if ( ChainPay_License::is_over_free_limit() ) {
            wc_add_notice(
                sprintf(
                    'ChainPay: Free plan limit of %d payments/month reached. <a href="%s" target="_blank">Upgrade to Pro →</a>',
                    CHAINPAY_FREE_LIMIT,
                    'https://chainpay.store/pricing'
                ),
                'error'
            );
            return array( 'result' => 'failure' );
        }

        $order->update_status( 'pending', 'ChainPay: Awaiting cryptocurrency payment.' );
        WC()->cart->empty_cart();

        return array(
            'result'   => 'success',
            'redirect' => add_query_arg(
                array(
                    'chainpay'  => '1',
                    'order_id'  => $order_id,
                    'order_key' => $order->get_order_key(),
                ),
                home_url( '/' )
            ),
        );
    }

    /* ── Show payment page ───────────────────────────────────── */
    public static function maybe_show_payment_page() {
        if ( empty( $_GET['chainpay'] ) ) return;

        $order_id  = isset( $_GET['order_id'] )  ? absint( $_GET['order_id'] )                           : 0;
        $order_key = isset( $_GET['order_key'] ) ? sanitize_text_field( wp_unslash( $_GET['order_key'] ) ) : '';
        if ( ! $order_id || ! $order_key ) return;

        $order = wc_get_order( $order_id );
        if ( ! $order || ! hash_equals( $order->get_order_key(), $order_key ) ) {
            wp_die( 'Invalid payment link.', 'ChainPay', array( 'response' => 404 ) );
        }

        if ( $order->is_paid() ) {
            wp_redirect( $order->get_checkout_order_received_url() );
            exit;
        }

        include CHAINPAY_DIR . 'templates/payment-page.php';
        exit;
    }

    /* ── AJAX: get / create invoice ──────────────────────────── */
    public function ajax_get_invoice() {
        check_ajax_referer( 'chainpay_nonce', 'nonce' );

        $order_id  = isset( $_POST['order_id'] )  ? absint( $_POST['order_id'] )                           : 0;
        $order_key = isset( $_POST['order_key'] ) ? sanitize_text_field( wp_unslash( $_POST['order_key'] ) ) : '';
        $coin      = isset( $_POST['coin'] )      ? sanitize_text_field( wp_unslash( $_POST['coin'] ) )      : 'BTC';

        $order = wc_get_order( $order_id );
        if ( ! $order || ! hash_equals( $order->get_order_key(), $order_key ) ) {
            wp_send_json_error( 'Invalid order.' );
        }

        // Coin check
        $all_coins = ChainPay_Coin_Registry::all();
        if ( ! isset( $all_coins[ $coin ] ) ) {
            wp_send_json_error( 'Invalid coin.' );
        }
        if ( ! $all_coins[ $coin ]['free'] && ! ChainPay_License::is_active() ) {
            wp_send_json_error( array(
                'message'     => 'A Pro license is required to use ' . $all_coins[ $coin ]['name'] . '.',
                'code'        => 'LICENSE_REQUIRED',
                'upgrade_url' => 'https://chainpay.store/pricing',
            ) );
        }

        // Check free limit
        if ( ! ChainPay_License::is_active() && ChainPay_License::is_over_free_limit() ) {
            wp_send_json_error( array(
                'message'     => sprintf( 'Free plan limit of %d payments/month reached.', CHAINPAY_FREE_LIMIT ),
                'code'        => 'FREE_LIMIT_REACHED',
                'used'        => ChainPay_License::get_monthly_count(),
                'limit'       => CHAINPAY_FREE_LIMIT,
                'upgrade_url' => 'https://chainpay.store/pricing',
            ) );
        }

        // Reuse existing pending invoice for same coin
        $existing = ChainPay_Invoice::get_by_order( $order_id );
        if ( $existing
            && $existing['coin'] === $coin
            && 'pending' === $existing['status']
            && strtotime( $existing['expires_at'] ) > time() + 60
        ) {
            $coin_data = ChainPay_Coin_Registry::get( $coin );
            wp_send_json_success( array(
                'invoice_id'    => $existing['invoice_id'],
                'address'       => $existing['address'],
                'coin'          => $coin,
                'coin_data'     => $coin_data,
                'amount_crypto' => $existing['amount_crypto'],
                'amount_fiat'   => $existing['amount_fiat'],
                'currency'      => $existing['fiat_currency'],
                'exchange_rate' => $existing['exchange_rate'],
                'expires_at'    => $existing['expires_at'],
                'uri'           => ChainPay_Invoice::build_uri( $coin_data, $existing['address'], $existing['amount_crypto'] ),
                'monthly_count' => ChainPay_License::get_monthly_count(),
                'monthly_limit' => ChainPay_License::is_active() ? 'unlimited' : CHAINPAY_FREE_LIMIT,
            ) );
        }

        // Create new invoice
        $result = ChainPay_Invoice::create( $order, $coin );
        if ( is_wp_error( $result ) ) {
            wp_send_json_error( $result->get_error_message() );
        }

        wp_send_json_success( $result );
    }

    /* ── AJAX: poll status ───────────────────────────────────── */
    public function ajax_poll_status() {
        check_ajax_referer( 'chainpay_nonce', 'nonce' );

        $invoice_id = isset( $_POST['invoice_id'] ) ? sanitize_text_field( wp_unslash( $_POST['invoice_id'] ) ) : '';
        if ( ! $invoice_id ) wp_send_json_error( 'Missing invoice_id.' );

        $inv = ChainPay_Invoice::get( $invoice_id );
        if ( ! $inv ) wp_send_json_error( 'Invoice not found.' );

        // Check expiry
        if ( 'pending' === $inv['status'] && strtotime( $inv['expires_at'] ) < time() ) {
            global $wpdb;
            $wpdb->update(
                $wpdb->prefix . 'chainpay_invoices',
                array( 'status' => 'expired' ),
                array( 'invoice_id' => $invoice_id ),
                array( '%s' ), array( '%s' )
            );
            $inv['status'] = 'expired';
        }

        $redirect_url = '';
        if ( 'confirmed' === $inv['status'] ) {
            $order = wc_get_order( $inv['order_id'] );
            if ( $order ) $redirect_url = $order->get_checkout_order_received_url();
        }

        wp_send_json_success( array(
            'status'        => $inv['status'],
            'confirmations' => (int) $inv['confirmations'],
            'tx_hash'       => $inv['tx_hash'],
            'expires_at'    => $inv['expires_at'],
            'redirect_url'  => $redirect_url,
        ) );
    }
}
