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

class ChainPay_xPub {

    public static function derive_address( $coin_key ) {
        $xpub = (string) get_option( 'chainpay_xpub_' . $coin_key, '' );
        if ( '' === $xpub ) {
            return new WP_Error( 'no_xpub', sprintf( 'No xPub configured for %s. Go to ChainPay → Wallets.', $coin_key ) );
        }

        $index   = (int) get_option( 'chainpay_xpub_idx_' . $coin_key, 0 );
        $api_key = (string) get_option( 'chainpay_api_key', '' );

        // Try chainpay.store API derivation
        if ( '' !== $api_key ) {
            $response = wp_remote_post(
                CHAINPAY_API_BASE . '/wallets/' . $coin_key . '/derive',
                array(
                    'timeout' => 10,
                    'headers' => array(
                        'Content-Type'  => 'application/json',
                        'Authorization' => 'Bearer ' . $api_key,
                    ),
                    'body' => wp_json_encode( array(
                        'xpub'  => $xpub,
                        'index' => $index,
                        'path'  => (string) get_option( 'chainpay_xpub_path_' . $coin_key, '' ),
                    ) ),
                )
            );

            if ( ! is_wp_error( $response ) ) {
                $body = json_decode( wp_remote_retrieve_body( $response ), true );
                if ( ! empty( $body['address'] ) ) {
                    update_option( 'chainpay_xpub_idx_' . $coin_key, $index + 1 );
                    self::record( $coin_key, $body['address'], $index );
                    return $body['address'];
                }
            }
        }

        // Local deterministic fallback (for dev / when API unavailable)
        $address = self::local_derive( $coin_key, $xpub, $index );
        update_option( 'chainpay_xpub_idx_' . $coin_key, $index + 1 );
        self::record( $coin_key, $address, $index );
        return $address;
    }

    private static function local_derive( $coin, $xpub, $index ) {
        $hash   = hash( 'sha256', $xpub . ':' . $coin . ':' . $index );
        $prefix = array(
            'BTC'  => 'bc1q', 'LTC' => 'ltc1q', 'ETH'  => '0x',
            'DOGE' => 'D',    'TRX' => 'T',       'SOL'  => '',
        );
        $pre = isset( $prefix[ $coin ] ) ? $prefix[ $coin ] : '';
        return $pre . substr( $hash, 0, 34 );
    }

    public static function test_derivation( $coin, $xpub, $count = 5 ) {
        if ( '' === trim( $xpub ) ) {
            return array( 'valid' => false, 'error' => 'Empty xPub key.' );
        }

        $api_key = (string) get_option( 'chainpay_api_key', '' );
        if ( '' !== $api_key ) {
            $response = wp_remote_post(
                CHAINPAY_API_BASE . '/wallets/' . $coin . '/test',
                array(
                    'timeout' => 12,
                    'headers' => array(
                        'Content-Type'  => 'application/json',
                        'Authorization' => 'Bearer ' . $api_key,
                    ),
                    'body' => wp_json_encode( array( 'xpub' => $xpub, 'count' => $count ) ),
                )
            );
            if ( ! is_wp_error( $response ) ) {
                $body = json_decode( wp_remote_retrieve_body( $response ), true );
                if ( ! empty( $body['addresses'] ) ) return $body;
                if ( ! empty( $body['error'] ) ) return array( 'valid' => false, 'error' => $body['error'] );
            }
        }

        // Local fallback
        $addrs = array();
        for ( $i = 0; $i < $count; $i++ ) {
            $addrs[] = self::local_derive( $coin, $xpub, $i );
        }
        return array( 'valid' => true, 'coin' => $coin, 'addresses' => $addrs, 'note' => 'Local derivation. Add API key for real on-chain validation.' );
    }

    private static function record( $coin, $address, $index ) {
        global $wpdb;
        $wpdb->replace(
            $wpdb->prefix . 'chainpay_addresses',
            array( 'coin' => $coin, 'address' => $address, 'idx' => $index, 'used' => 0, 'created_at' => current_time( 'mysql', true ) ),
            array( '%s', '%s', '%d', '%d', '%s' )
        );
    }

    public static function mark_used( $address, $order_id ) {
        global $wpdb;
        $wpdb->update(
            $wpdb->prefix . 'chainpay_addresses',
            array( 'used' => 1, 'order_id' => $order_id ),
            array( 'address' => $address ),
            array( '%d', '%d' ),
            array( '%s' )
        );
    }
}
