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

/** Minimální skóre pro zablokování objednávky (honeypot má vždy 10). */
const ELEMENTSELL_SPAM_BLOCK_THRESHOLD = 5;

/**
 * @return string
 */
function elementsell_get_client_ip_for_spam_check() {
    $ip = isset( $_SERVER['REMOTE_ADDR'] ) ? (string) $_SERVER['REMOTE_ADDR'] : '';

    return sanitize_text_field( $ip );
}

/**
 * @return void
 */
function elementsell_payment_rate_limit_check() {
    $ip = elementsell_get_client_ip_for_spam_check();

    if ( $ip === '' ) {
        return;
    }

    $key   = 'elementsell_pay_rl_' . md5( $ip );
    $count = (int) get_transient( $key );

    if ( $count >= 20 ) {
        elementsell_payment_fail( 'Příliš mnoho pokusů o odeslání. Zkuste to prosím později.' );
    }

    set_transient( $key, $count + 1, HOUR_IN_SECONDS );
}

/**
 * @param string $text
 * @return string
 */
function elementsell_spam_normalize_text( $text ) {
    $text = trim( wp_strip_all_tags( (string) $text ) );
    $text = preg_replace( '/\s+/u', ' ', $text );

    return is_string( $text ) ? $text : '';
}

/**
 * Detekce zjevného botového textu. Kontext určuje přísnost (jména vs. adresa/firma).
 *
 * @param string $text
 * @param string $context 'name' | 'address' | 'company'
 * @return bool
 */
function elementsell_spam_text_looks_like_gibberish( $text, $context = 'name' ) {
    $text = elementsell_spam_normalize_text( $text );

    if ( $text === '' ) {
        return false;
    }

    $context = in_array( $context, [ 'name', 'address', 'company' ], true ) ? $context : 'name';
    $is_name = $context === 'name';

    $max_length = $is_name ? 48 : 120;

    if ( mb_strlen( $text, 'UTF-8' ) > $max_length ) {
        return true;
    }

    if ( $is_name && preg_match( '/\d/u', $text ) ) {
        return true;
    }

    if ( $is_name && preg_match( '/[<>@#$%^&*()_+=\[\]{}|\\\\;:"\/,?]/u', $text ) ) {
        return true;
    }

    if ( ! $is_name && preg_match( '/[<>@#$%^&*_{}|\\\\;"]/u', $text ) ) {
        return true;
    }

    if ( preg_match( '/(.)\1{3,}/u', $text ) ) {
        return true;
    }

    if ( preg_match( '/(qwerty|asdfgh|zxcvbn|qwer|hjkl|yxcv)/iu', $text ) ) {
        return true;
    }

    if ( $is_name ) {
        if ( ! preg_match( '/^[\p{L}\p{M}\s\'\-\.]+$/u', $text ) ) {
            return true;
        }
    } elseif ( ! preg_match( '/^[\p{L}\p{M}\p{N}\s\'\-\.,\/\(\):]+$/u', $text ) ) {
        return true;
    }

    $letters = preg_replace( '/[^\p{L}]/u', '', $text );

    if ( $letters === '' ) {
        return $is_name;
    }

    $length = mb_strlen( $letters, 'UTF-8' );

    if ( $is_name && $length < 4 ) {
        return false;
    }

    if ( $length >= 8 ) {
        $vowels = preg_match_all( '/[aeiouyáéíóúůýěAEIOUYÁÉÍÓÚŮÝĚ]/u', $letters );

        if ( (int) $vowels === 0 ) {
            return true;
        }
    }

    if ( $is_name && $length >= 8 && preg_match( '/[bcdfghjklmnpqrstvwxzřžčšďťňBCDFGHJKLMNPQRSTVWXZŘŽČŠĎŤŇ]{8,}/u', $letters ) ) {
        return true;
    }

    return false;
}

/**
 * Zjevný spam v jméně — číslice se symboly, nebo číslice v náhodném řetězci (samo stačí k blokaci).
 *
 * @param string $text
 * @return bool
 */
function elementsell_spam_name_looks_like_strong_gibberish( $text ) {
    $text = elementsell_spam_normalize_text( $text );

    if ( $text === '' ) {
        return false;
    }

    $has_digits  = (bool) preg_match( '/\d/u', $text );
    $has_symbols = (bool) preg_match( '/[<>@#$%^&*()_+=\[\]{}|\\\\;:"\/,?]/u', $text );

    if ( $has_digits && $has_symbols ) {
        return true;
    }

    if ( $has_digits && elementsell_spam_text_looks_like_gibberish( $text, 'name' ) ) {
        return true;
    }

    return false;
}

/**
 * @param string $email
 * @return bool
 */
function elementsell_spam_email_looks_suspicious( $email ) {
    $email = sanitize_email( (string) $email );

    return $email === '' || ! is_email( $email );
}

/**
 * @param string $phone
 * @return bool
 */
function elementsell_spam_phone_looks_suspicious( $phone ) {
    $phone = elementsell_spam_normalize_text( $phone );

    if ( $phone === '' ) {
        return false;
    }

    if ( preg_match( '/[a-zA-ZáčďéěíňóřšťúůýžÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]/u', $phone ) ) {
        return true;
    }

    $digits = preg_replace( '/\D/u', '', $phone );

    return $digits === '';
}

/**
 * @param array<string, mixed> $data
 * @return array{score: int, reasons: array<int, string>}
 */
function elementsell_score_spam_order_data( array $data ) {
    $score   = 0;
    $reasons = [];

    $first_name = elementsell_spam_normalize_text( $data['first_name'] ?? '' );
    $surname    = elementsell_spam_normalize_text( $data['surname'] ?? '' );
    $email      = sanitize_email( (string) ( $data['email'] ?? '' ) );
    $phone      = elementsell_spam_normalize_text( $data['phone'] ?? '' );
    $address    = elementsell_spam_normalize_text( $data['address'] ?? '' );
    $company    = elementsell_spam_normalize_text( $data['company'] ?? '' );

    if ( ! empty( $data['honeypot'] ) ) {
        $score    += 10;
        $reasons[] = 'honeypot';
    }

    foreach ( [ 'first_name' => $first_name, 'surname' => $surname ] as $field => $value ) {
        if ( $value === '' ) {
            continue;
        }

        if ( elementsell_spam_name_looks_like_strong_gibberish( $value ) ) {
            $score    += 5;
            $reasons[] = $field . '_strong';
            continue;
        }

        if ( elementsell_spam_text_looks_like_gibberish( $value, 'name' ) ) {
            $score    += 3;
            $reasons[] = $field;
        }
    }

    foreach (
        [
            'address' => [ $address, 'address' ],
            'company' => [ $company, 'company' ],
        ] as $field => $field_data
    ) {
        list( $value, $context ) = $field_data;

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

        if ( elementsell_spam_text_looks_like_gibberish( $value, $context ) ) {
            $score    += 2;
            $reasons[] = $field;
        }
    }

    if ( elementsell_spam_email_looks_suspicious( $email ) ) {
        $score    += 5;
        $reasons[] = 'email';
    }

    if ( elementsell_spam_phone_looks_suspicious( $phone ) ) {
        $score    += 2;
        $reasons[] = 'phone';
    }

    if (
        $first_name !== ''
        && $surname !== ''
        && mb_strtolower( $first_name, 'UTF-8' ) === mb_strtolower( $surname, 'UTF-8' )
        && elementsell_spam_text_looks_like_gibberish( $first_name, 'name' )
        && elementsell_spam_text_looks_like_gibberish( $surname, 'name' )
    ) {
        $score    += 2;
        $reasons[] = 'duplicate_name';
    }

    return [
        'score'   => $score,
        'reasons' => $reasons,
    ];
}

/**
 * @return void
 */
function elementsell_validate_payment_spam_submission() {
    elementsell_payment_rate_limit_check();

    if ( ! empty( $_POST['elementsell_hp'] ) ) {
        elementsell_payment_fail( 'Objednávku se nepodařilo odeslat. Zkontrolujte údaje ve formuláři.' );
    }

    $result = elementsell_score_spam_order_data(
        [
            'first_name' => isset( $_POST['first_name'] ) ? wp_unslash( (string) $_POST['first_name'] ) : '',
            'surname'    => isset( $_POST['surname'] ) ? wp_unslash( (string) $_POST['surname'] ) : '',
            'email'      => isset( $_POST['email'] ) ? wp_unslash( (string) $_POST['email'] ) : '',
            'phone'      => isset( $_POST['phone'] ) ? wp_unslash( (string) $_POST['phone'] ) : '',
            'address'    => isset( $_POST['address'] ) ? wp_unslash( (string) $_POST['address'] ) : '',
            'company'    => isset( $_POST['company'] ) ? wp_unslash( (string) $_POST['company'] ) : '',
            'honeypot'   => isset( $_POST['elementsell_hp'] ) ? wp_unslash( (string) $_POST['elementsell_hp'] ) : '',
        ]
    );

    if ( (int) ( $result['score'] ?? 0 ) >= ELEMENTSELL_SPAM_BLOCK_THRESHOLD ) {
        elementsell_payment_fail( 'Zkontrolujte prosím jméno, e-mail a telefon — některý údaj vypadá neplatně.' );
    }
}

/**
 * @param int $order_id
 * @return bool
 */
function elementsell_delete_order_by_id( $order_id ) {
    global $wpdb;

    $order_id = (int) $order_id;

    if ( $order_id <= 0 ) {
        return false;
    }

    $order = function_exists( 'elementsell_get_order' ) ? elementsell_get_order( $order_id ) : null;

    // Ostré zaplacené objednávky nelze mazat. Demo ThePay ano (testovací).
    if (
        $order
        && (string) $order->payment_status === 'paid'
        && ( ! function_exists( 'elementsell_is_demo_order' ) || ! elementsell_is_demo_order( $order ) )
    ) {
        return false;
    }

    $wpdb->delete(
        $wpdb->prefix . 'elementsell_order_fields',
        [ 'order_id' => $order_id ],
        [ '%d' ]
    );

    $wpdb->delete(
        $wpdb->prefix . 'elementsell_invoices',
        [ 'order_id' => $order_id ],
        [ '%d' ]
    );

    $deleted = $wpdb->delete(
        $wpdb->prefix . 'elementsell_orders',
        [ 'id' => $order_id ],
        [ '%d' ]
    );

    return $deleted !== false;
}
