<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * @return string
 */
function elementsell_fio_get_api_token() {
    return trim( (string) get_option( 'fio_api_token' ) );
}

/**
 * @return bool
 */
function elementsell_fio_can_call_api() {
    $last = (int) get_transient( 'elementsell_fio_api_last_call' );

    return ( time() - $last ) >= 30;
}

/**
 * @return void
 */
function elementsell_fio_mark_api_called() {
    set_transient( 'elementsell_fio_api_last_call', time(), 90 );
}

/**
 * @param string $error_message
 * @return string
 */
function elementsell_fio_format_cron_error( $error_message ) {
    $error_message = trim( (string) $error_message );

    if ( $error_message === '' ) {
        return 'Fio: neznámá chyba API';
    }

    if ( preg_match( '/timed?\s*out|curl error 28/i', $error_message ) ) {
        return 'Fio: API neodpovědělo včas (zkusí se znovu při další kontrole)';
    }

    if ( stripos( $error_message, 'rate_limit' ) !== false || stripos( $error_message, '30 s' ) !== false ) {
        return 'Fio: čeká se na další dotaz (limit API)';
    }

    return 'Fio: ' . $error_message;
}

/**
 * @param int  $days_back
 * @param bool $force
 * @return array<int, array{vs: string, amount: float}>|WP_Error
 */
function elementsell_fio_fetch_transactions( $days_back = 2, $force = false ) {
    $override = apply_filters( 'elementsell_fio_transactions_override', null, $days_back, $force );

    if ( is_array( $override ) ) {
        return $override;
    }

    if ( is_wp_error( $override ) ) {
        return $override;
    }

    $token = elementsell_fio_get_api_token();

    if ( $token === '' ) {
        return new WP_Error( 'elementsell_fio_no_token', 'Fio API token není nastaven.' );
    }

    if ( ! $force && ! elementsell_fio_can_call_api() ) {
        return new WP_Error( 'elementsell_fio_rate_limit', 'Fio API: čekejte 30 s mezi dotazy.' );
    }

    $days_back = max( 1, min( 14, (int) $days_back ) );
    $end       = wp_date( 'Y-m-d' );
    $start     = wp_date( 'Y-m-d', strtotime( '-' . $days_back . ' days', current_time( 'timestamp' ) ) );
    $url       = sprintf(
        'https://fioapi.fio.cz/v1/rest/periods/%s/%s/%s/transactions.json',
        rawurlencode( $token ),
        $start,
        $end
    );

    $response = wp_remote_get(
        $url,
        [
            'timeout' => 45,
            'headers' => [
                'Accept' => 'application/json',
            ],
        ]
    );

    elementsell_fio_mark_api_called();

    if ( is_wp_error( $response ) ) {
        return $response;
    }

    $code = (int) wp_remote_retrieve_response_code( $response );
    $body = json_decode( (string) wp_remote_retrieve_body( $response ), true );

    if ( $code !== 200 ) {
        $message = is_array( $body ) && ! empty( $body['errorMessage'] )
            ? (string) $body['errorMessage']
            : 'Fio API HTTP ' . $code;

        return new WP_Error( 'elementsell_fio_api', $message );
    }

    $list = $body['accountStatement']['transactionList']['transaction'] ?? [];

    if ( ! is_array( $list ) ) {
        return [];
    }

    if ( isset( $list['column1'] ) ) {
        $list = [ $list ];
    }

    $transactions = [];

    foreach ( $list as $transaction ) {
        if ( ! is_array( $transaction ) ) {
            continue;
        }

        $amount = isset( $transaction['column1']['value'] ) ? (float) $transaction['column1']['value'] : 0.0;

        if ( $amount <= 0 ) {
            continue;
        }

        $vs = isset( $transaction['column5']['value'] ) ? (string) $transaction['column5']['value'] : '';
        $vs = preg_replace( '/\D+/', '', $vs );

        if ( $vs === '' ) {
            continue;
        }

        $transactions[] = [
            'vs'     => $vs,
            'amount' => $amount,
        ];
    }

    return $transactions;
}

/**
 * @return array<int, object>
 */
function elementsell_fio_get_pending_orders() {
    global $wpdb;

    $table = $wpdb->prefix . 'elementsell_orders';

    return (array) $wpdb->get_results(
        "
        SELECT *
        FROM {$table}
        WHERE payment_method = 'fio'
        AND payment_status IN ('pending', 'waiting_for_confirmation')
        AND vs IS NOT NULL
        AND vs != ''
        ORDER BY id ASC
        "
    );
}

/**
 * @param float $order_amount
 * @param float $transaction_amount
 * @return bool
 */
function elementsell_fio_amounts_match( $order_amount, $transaction_amount ) {
    return abs( (float) $order_amount - (float) $transaction_amount ) < 0.01;
}

/**
 * @param object   $order
 * @param float|null $transaction_amount
 * @return object
 */
function elementsell_fio_mark_order_paid( $order, $transaction_amount = null ) {
    if ( ! $order ) {
        return $order;
    }

    if ( elementsell_is_order_payment_paid( $order ) ) {
        return $order;
    }

    $was_first_paid_transition = elementsell_mark_order_payment_paid_atomically(
        (int) $order->id,
        [ 'payment_method' => 'fio' ]
    );

    if ( ! $was_first_paid_transition ) {
        $fresh = elementsell_get_order( (int) $order->id );

        return $fresh ? $fresh : $order;
    }

    elementsell_sync_invoice_with_order( (int) $order->id );
    elementsell_complete_paid_order_side_effects( (int) $order->id, false );

    $fresh = elementsell_get_order( (int) $order->id );

    return $fresh ? $fresh : $order;
}

/**
 * @param bool $force
 * @return array{matched: int, pending?: int, skipped?: string, error?: string}
 */
function elementsell_fio_check_pending_payments( $force = false ) {
    if ( elementsell_fio_get_api_token() === '' ) {
        return [
            'matched' => 0,
            'skipped' => 'no_token',
        ];
    }

    $pending = elementsell_fio_get_pending_orders();

    if ( empty( $pending ) ) {
        return [
            'matched' => 0,
            'pending' => 0,
        ];
    }

    if ( ! $force && ! elementsell_fio_can_call_api() ) {
        return [
            'matched' => 0,
            'pending' => count( $pending ),
            'skipped' => 'rate_limit',
        ];
    }

    $transactions = elementsell_fio_fetch_transactions( 2, $force );

    if ( is_wp_error( $transactions ) ) {
        if ( class_exists( 'ElementSell_Cron_Log' ) && ElementSell_Cron_Log::is_active() ) {
            ElementSell_Cron_Log::add( elementsell_fio_format_cron_error( $transactions->get_error_message() ) );
        }

        return [
            'matched' => 0,
            'pending' => count( $pending ),
            'error'   => $transactions->get_error_message(),
        ];
    }

    $matched = 0;

    foreach ( $pending as $order ) {
        $order_vs = preg_replace( '/\D+/', '', (string) $order->vs );

        if ( $order_vs === '' ) {
            continue;
        }

        foreach ( (array) $transactions as $transaction ) {
            if ( $order_vs !== (string) $transaction['vs'] ) {
                continue;
            }

            if ( ! elementsell_fio_amounts_match( $order->amount, $transaction['amount'] ) ) {
                continue;
            }

            elementsell_fio_mark_order_paid( $order, (float) $transaction['amount'] );
            ++$matched;
            break;
        }
    }

    if ( $matched > 0 && class_exists( 'ElementSell_Cron_Log' ) && ElementSell_Cron_Log::is_active() ) {
        ElementSell_Cron_Log::add( 'Fio: spárováno ' . $matched . ' plateb' );
    }

    return [
        'matched' => $matched,
        'pending' => count( $pending ),
    ];
}

/**
 * @param object $order
 * @return object
 */
function elementsell_refresh_fio_order_payment_status( $order ) {
    if ( ! $order || (string) $order->payment_method !== 'fio' || elementsell_is_order_payment_paid( $order ) ) {
        return $order;
    }

    elementsell_fio_check_pending_payments( false );

    $fresh = elementsell_get_order( (int) $order->id );

    return $fresh ? $fresh : $order;
}

add_action( 'elementsell_daily_billing_check', 'elementsell_fio_check_pending_payments_cron', 15 );

/**
 * @return void
 */
function elementsell_fio_check_pending_payments_cron() {
    elementsell_fio_check_pending_payments( false );
}

add_action( 'load-toplevel_page_elementsell', 'elementsell_fio_check_on_admin_page' );

/**
 * @return void
 */
function elementsell_fio_check_on_admin_page() {
    if ( ! current_user_can( 'manage_options' ) || elementsell_fio_get_api_token() === '' ) {
        return;
    }

    $result = elementsell_fio_check_pending_payments( false );

    if ( ! empty( $result['matched'] ) ) {
        elementsell_ops_log_write_quick(
            'x',
            'Fio: spárováno ' . (int) $result['matched'] . ' plateb'
        );
    }
}
