<?php

if (!defined('ABSPATH')) {
    exit;
}

function seaxpay_reusable_order_statuses() {
    return array('pending', 'processing', 'confirming');
}

function seaxpay_find_reusable_order($wc_order_id, $coin = null, $network = null) {
    global $wpdb;
    if (!$wc_order_id) {
        return null;
    }
    $table = $wpdb->prefix . 'seaxpay_orders';
    $statuses = seaxpay_reusable_order_statuses();
    $placeholders = implode(',', array_fill(0, count($statuses), '%s'));
    if ($coin !== null && $coin !== '' && $network !== null && $network !== '') {
        $params = array_merge(array((int) $wc_order_id, $coin, $network), $statuses);
        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $sql = "SELECT * FROM {$table} WHERE wc_order_id = %d AND coin = %s AND network = %s AND status IN ({$placeholders}) ORDER BY id DESC LIMIT 1";
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        return $wpdb->get_row($wpdb->prepare($sql, $params));
    }
    $params = array_merge(array((int) $wc_order_id), $statuses);
    // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    $sql = "SELECT * FROM {$table} WHERE wc_order_id = %d AND status IN ({$placeholders}) ORDER BY id DESC LIMIT 1";
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    return $wpdb->get_row($wpdb->prepare($sql, $params));
}

function seaxpay_status_terminal_no_downgrade() {
    return array('completed', 'withdrawing', 'settled', 'risk_refunded', 'risk_rejected', 'risk_frozen', 'failed', 'overpaid', 'expired_refund_pending');
}

function seaxpay_status_state_machine() {
    static $cached = null;
    if ($cached !== null) {
        return $cached;
    }
    $term = seaxpay_status_terminal_no_downgrade();
    $confirming_skip = array_values(array_unique(array_merge(
        array('confirming', 'paid', 'expired', 'risk_blocked', 'pending_withdraw'), $term
    )));
    $expired_skip = array_values(array_unique(array_merge(
        array('paid', 'confirming', 'risk_blocked', 'pending_withdraw'), $term
    )));
    $expired_refund_pending_skip = array_values(array_unique(array_merge(
        array('paid', 'pending_withdraw'), $term
    )));
    $cached = array();
    $cached['payment.success'] = array(
        'target_status' => 'paid',
        'skip_statuses' => array('completed', 'settled', 'risk_refunded', 'risk_frozen'),
        'wc_action_auto' => 'payment_complete_then_auto_complete',
        'wc_action_manual' => 'payment_complete_then_auto_complete',
    );
    $cached['payment.confirming'] = array(
        'target_status' => 'confirming',
        'skip_statuses' => $confirming_skip,
        'wc_action_auto' => 'note_only',
        'wc_action_manual' => 'note_only',
    );
    $cached['payment.expired'] = array(
        'target_status' => 'expired',
        'skip_statuses' => $expired_skip,
        'wc_action_auto' => 'cancel_if_pending',
        'wc_action_manual' => 'cancel_if_pending',
    );
    $cached['payment.expired_refund_pending'] = array(
        'target_status' => 'expired_refund_pending',
        'skip_statuses' => $expired_refund_pending_skip,
        'wc_action_auto' => 'note_only',
        'wc_action_manual' => 'note_only',
    );
    $cached['payment.failed'] = array(
        'target_status' => 'failed',
        'skip_statuses' => array('completed', 'settled', 'risk_refunded', 'risk_frozen'),
        'wc_action_auto' => 'failed',
        'wc_action_manual' => 'failed',
    );
    $cached = seaxpay_status_state_machine_extend2(seaxpay_status_state_machine_extend($cached));
    return $cached;
}

function seaxpay_status_state_machine_extend(array $cached) {
    $cached['payment.risk_blocked'] = array(
        'target_status' => 'risk_blocked',
        'skip_statuses' => array('completed', 'settled', 'risk_refunded', 'risk_frozen', 'risk_rejected'),
        'wc_action_auto' => 'on_hold_risk',
        'wc_action_manual' => 'on_hold_risk',
    );
    $cached['payment.risk_approved'] = array(
        'target_status_auto' => 'paid',
        'target_status_manual' => 'pending_withdraw',
        'skip_statuses' => array('completed', 'settled', 'risk_refunded', 'risk_rejected', 'risk_frozen'),
        'wc_action_auto' => 'payment_complete_then_auto_complete',
        'wc_action_manual' => 'note_only',
    );
    $cached['payment.risk_rejected'] = array(
        'target_status' => 'risk_rejected',
        'skip_statuses' => array('risk_frozen', 'completed', 'settled', 'risk_refunded'),
        'wc_action_auto' => 'cancel_risk_rejected',
        'wc_action_manual' => 'cancel_risk_rejected',
    );
    $cached['payment.risk_refund_initiated'] = array(
        'target_status' => null,
        'skip_statuses' => array(),
        'wc_action_auto' => 'note_only',
        'wc_action_manual' => 'note_only',
    );
    $cached['payment.risk_refunded'] = array(
        'target_status' => 'risk_refunded',
        'skip_statuses' => array('completed', 'settled'),
        'wc_action_auto' => 'refunded',
        'wc_action_manual' => 'refunded',
    );
    $cached['payment.risk_frozen'] = array(
        'target_status' => 'risk_frozen',
        'skip_statuses' => array('completed', 'settled', 'risk_refunded'),
        'wc_action_auto' => 'on_hold_frozen',
        'wc_action_manual' => 'on_hold_frozen',
    );
    return $cached;
}

function seaxpay_status_state_machine_extend2(array $cached) {
    $cached['payment.pending_withdraw'] = array(
        'target_status' => 'pending_withdraw',
        'skip_statuses' => array('completed', 'withdrawing', 'risk_refunded', 'risk_rejected', 'risk_frozen', 'settled'),
        'wc_action_auto' => 'on_hold_pending_withdraw',
        'wc_action_manual' => 'on_hold_pending_withdraw',
    );
    $cached['payment.pending_withdraw_expire_warn'] = array(
        'target_status' => null,
        'skip_statuses' => array(),
        'wc_action_auto' => 'note_only',
        'wc_action_manual' => 'note_only',
    );
    $cached['merchant.withdraw_submitted'] = array(
        'target_status' => 'withdrawing',
        'skip_statuses' => array('completed', 'settled', 'risk_refunded', 'risk_frozen'),
        'wc_action_auto' => 'note_only',
        'wc_action_manual' => 'note_only',
    );
    $cached['merchant.withdraw_completed'] = array(
        'target_status' => 'completed',
        'skip_statuses' => array('risk_refunded', 'risk_frozen'),
        'wc_action_auto' => 'auto_complete_if_enabled',
        'wc_action_manual' => 'auto_complete_if_enabled',
    );
    $cached['merchant.withdraw_failed'] = array(
        'target_status' => 'pending_withdraw',
        'skip_statuses' => array('completed', 'settled', 'risk_refunded', 'risk_frozen'),
        'wc_action_auto' => 'on_hold_withdraw_failed',
        'wc_action_manual' => 'on_hold_withdraw_failed',
    );
    $note_only_no_status = array(
        'target_status' => null,
        'skip_statuses' => array(),
        'wc_action_auto' => 'note_only',
        'wc_action_manual' => 'note_only',
    );
    $cached['merchant.withdraw_review_timeout'] = $note_only_no_status;
    $cached['merchant.withdraw_review_approved'] = $note_only_no_status;
    $cached['merchant.withdraw_review_rejected'] = $note_only_no_status;
    $cached['merchant.withdraw_review_frozen'] = $note_only_no_status;
    $cached['payment.auto_expire_withdraw_triggered'] = $note_only_no_status;
    $cached['payment.pending_withdraw_no_wallet'] = $note_only_no_status;
    $cached['payment.confirming_timeout_alert'] = $note_only_no_status;
    $cached['payment.settle_delayed'] = $note_only_no_status;
    $cached['payment.overpaid'] = array(
        'target_status' => 'overpaid',
        'skip_statuses' => array('completed', 'settled', 'risk_refunded', 'risk_rejected', 'risk_frozen'),
        'wc_action_auto' => 'note_only',
        'wc_action_manual' => 'note_only',
    );
    return $cached;
}

function seaxpay_normalize_settlement_mode($raw) {
    if ($raw === null || $raw === '') {
        return 'auto';
    }
    $normalized = strtolower(trim(strval($raw)));
    if ($normalized === 'manual') {
        return 'manual';
    }
    return 'auto';
}

function seaxpay_resolve_status_decision($event, $settlement_mode_raw, $current_status) {
    $machine = seaxpay_status_state_machine();
    if (!isset($machine[$event])) {
        return array(
            'known' => false,
            'should_skip' => false,
            'target_status' => null,
            'wc_action' => 'unknown',
            'settlement_mode' => seaxpay_normalize_settlement_mode($settlement_mode_raw),
        );
    }
    $entry = $machine[$event];
    $mode = seaxpay_normalize_settlement_mode($settlement_mode_raw);
    $skip_statuses = isset($entry['skip_statuses']) ? $entry['skip_statuses'] : array();
    $should_skip = $current_status !== null && $current_status !== '' && in_array($current_status, $skip_statuses, true);
    if (isset($entry['target_status_auto']) || isset($entry['target_status_manual'])) {
        $target = ($mode === 'manual')
            ? (isset($entry['target_status_manual']) ? $entry['target_status_manual'] : null)
            : (isset($entry['target_status_auto']) ? $entry['target_status_auto'] : null);
    } else {
        $target = isset($entry['target_status']) ? $entry['target_status'] : null;
    }
    $wc_action = ($mode === 'manual')
        ? (isset($entry['wc_action_manual']) ? $entry['wc_action_manual'] : 'note_only')
        : (isset($entry['wc_action_auto']) ? $entry['wc_action_auto'] : 'note_only');
    return array(
        'known' => true,
        'should_skip' => $should_skip,
        'target_status' => $target,
        'wc_action' => $wc_action,
        'settlement_mode' => $mode,
    );
}

function seaxpay_should_skip_event($event, $current_status) {
    $machine = seaxpay_status_state_machine();
    if (!isset($machine[$event])) {
        return false;
    }
    $skip_statuses = isset($machine[$event]['skip_statuses']) ? $machine[$event]['skip_statuses'] : array();
    return $current_status !== null && $current_status !== '' && in_array($current_status, $skip_statuses, true);
}
