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

class ChainPay_Webhook {

    public function __construct() {
        add_filter( 'query_vars',      array( $this, 'add_var' ) );
        add_action( 'init',            array( $this, 'add_rule' ) );
        add_action( 'template_redirect', array( $this, 'handle' ) );
    }

    public function add_var( $vars ) {
        $vars[] = 'chainpay_ipn';
        return $vars;
    }

    public function add_rule() {
        add_rewrite_rule( '^chainpay-ipn/?$', 'index.php?chainpay_ipn=1', 'top' );
    }

    public function handle() {
        if ( ! get_query_var( 'chainpay_ipn' ) && empty( $_GET['chainpay_ipn'] ) ) return;

        if ( 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
            status_header( 405 ); exit( 'Method Not Allowed' );
        }

        $raw    = file_get_contents( 'php://input' );
        $sig    = isset( $_SERVER['HTTP_X_CHAINPAY_SIGNATURE'] ) ? $_SERVER['HTTP_X_CHAINPAY_SIGNATURE'] : '';
        $secret = (string) get_option( 'chainpay_webhook_secret', '' );

        if ( '' !== $secret && ! $this->verify( $raw, $sig, $secret ) ) {
            status_header( 401 ); exit( 'Unauthorized' );
        }

        $payload = json_decode( $raw, true );
        if ( ! is_array( $payload ) ) {
            status_header( 400 ); exit( 'Bad Request' );
        }

        $event      = isset( $payload['event'] )      ? $payload['event']      : '';
        $invoice_id = isset( $payload['invoice_id'] ) ? $payload['invoice_id'] : '';
        $tx_hash    = isset( $payload['tx_hash'] )    ? $payload['tx_hash']    : '';
        $confs      = isset( $payload['confirmations'] ) ? (int) $payload['confirmations'] : 0;

        if ( 'payment.detected' === $event || 'payment.confirmed' === $event ) {
            ChainPay_Invoice::mark_paid( $invoice_id, $tx_hash, $confs );
        } elseif ( 'payment.underpaid' === $event ) {
            ChainPay_Invoice::mark_underpaid(
                $invoice_id,
                isset( $payload['received'] ) ? $payload['received'] : '',
                isset( $payload['expected'] ) ? $payload['expected'] : ''
            );
        } elseif ( 'invoice.expired' === $event ) {
            $inv = ChainPay_Invoice::get( $invoice_id );
            if ( $inv && 'pending' === $inv['status'] ) {
                $order = wc_get_order( $inv['order_id'] );
                if ( $order ) {
                    $order->update_status( (string) get_option( 'chainpay_expired_status', 'cancelled' ), 'ChainPay: Invoice expired (webhook).' );
                }
            }
        }

        status_header( 200 );
        header( 'Content-Type: application/json' );
        echo wp_json_encode( array( 'received' => true ) );
        exit;
    }

    private function verify( $payload, $sig, $secret ) {
        return hash_equals( hash_hmac( 'sha256', $payload, $secret ), $sig );
    }
}
