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

function elementsell_get_order( $id ) {
    global $wpdb;

    $order = $wpdb->get_row(
        $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}elementsell_orders WHERE id = %d",
            $id
        )
    );

    if ( $order || ! function_exists( 'elementsell_orders_archive_table_exists' ) || ! elementsell_orders_archive_table_exists() ) {
        return $order;
    }

    return $wpdb->get_row(
        $wpdb->prepare(
            'SELECT * FROM ' . elementsell_get_orders_archive_table_name() . ' WHERE id = %d',
            $id
        )
    );
}

function elementsell_get_order_by_payment_uid( $payment_uid ) {
    global $wpdb;

    $order = $wpdb->get_row(
        $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}elementsell_orders WHERE payment_uid = %s",
            $payment_uid
        )
    );

    if ( $order || ! function_exists( 'elementsell_orders_archive_table_exists' ) || ! elementsell_orders_archive_table_exists() ) {
        return $order;
    }

    return $wpdb->get_row(
        $wpdb->prepare(
            'SELECT * FROM ' . elementsell_get_orders_archive_table_name() . ' WHERE payment_uid = %s',
            $payment_uid
        )
    );
}

function elementsell_get_order_field( $order_id, $field_name ) {
    global $wpdb;

    $value = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT field_value
             FROM {$wpdb->prefix}elementsell_order_fields
             WHERE order_id = %d
             AND field_name = %s
             LIMIT 1",
            $order_id,
            $field_name
        )
    );

    if ( $value !== null ) {
        return $value;
    }

    if ( ! function_exists( 'elementsell_orders_archive_table_exists' ) || ! elementsell_orders_archive_table_exists() ) {
        return null;
    }

    return $wpdb->get_var(
        $wpdb->prepare(
            'SELECT field_value
             FROM ' . elementsell_get_order_fields_archive_table_name() . '
             WHERE order_id = %d
             AND field_name = %s
             LIMIT 1',
            $order_id,
            $field_name
        )
    );
}

/**
 * URL stránky, odkud zákazník odeslal platební formulář (stejná doména).
 *
 * @param string $url
 * @return string
 */
function elementsell_normalize_customer_source_page_url( $url ) {
    $url = esc_url_raw( trim( (string) $url ) );

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

    $site_host = wp_parse_url( home_url(), PHP_URL_HOST );
    $url_host  = wp_parse_url( $url, PHP_URL_HOST );

    if ( ! $site_host || ! $url_host || strtolower( (string) $url_host ) !== strtolower( (string) $site_host ) ) {
        return '';
    }

    $fragment     = (string) wp_parse_url( $url, PHP_URL_FRAGMENT );
    $query_string = (string) wp_parse_url( $url, PHP_URL_QUERY );
    $query        = [];

    if ( $query_string !== '' ) {
        parse_str( $query_string, $query );
    }

    $preview_post_id = isset( $query['preview_id'] ) ? (int) $query['preview_id'] : 0;

    if ( $preview_post_id > 0 ) {
        $status = get_post_status( $preview_post_id );

        if ( in_array( $status, [ 'publish', 'private' ], true ) ) {
            $permalink = get_permalink( $preview_post_id );

            if ( is_string( $permalink ) && $permalink !== '' ) {
                $url          = $permalink;
                $query_string = (string) wp_parse_url( $url, PHP_URL_QUERY );
                $query        = [];

                if ( $query_string !== '' ) {
                    parse_str( $query_string, $query );
                }
            }
        }
    }

    foreach ( [ 'preview', 'preview_id', 'preview_nonce', 'elementor-preview' ] as $strip_key ) {
        unset( $query[ $strip_key ] );
    }

    $path = (string) wp_parse_url( $url, PHP_URL_PATH );

    if ( $path === '' ) {
        $path = '/';
    }

    $clean = home_url( $path );

    if ( ! empty( $query ) ) {
        $clean = add_query_arg( $query, $clean );
    }

    if ( $fragment !== '' ) {
        $clean .= '#' . $fragment;
    }

    return esc_url_raw( $clean );
}

/**
 * @param object $order
 * @return string
 */
function elementsell_get_order_source_page_url( $order ) {
    if ( ! $order ) {
        return home_url( '/' );
    }

    $order_id = (int) $order->id;

    $url = elementsell_normalize_customer_source_page_url(
        (string) elementsell_get_order_field( $order_id, 'source_page_url' )
    );

    if ( $url !== '' ) {
        return $url;
    }

    $post_id = (int) elementsell_get_order_field( $order_id, 'elementsell_post_id' );

    if ( $post_id > 0 && get_post_status( $post_id ) === 'publish' ) {
        $url = elementsell_normalize_customer_source_page_url( (string) get_permalink( $post_id ) );

        if ( $url !== '' ) {
            return $url;
        }
    }

    if ( function_exists( 'elementsell_automation_get_catalog' ) ) {
        $product_name = trim( (string) $order->product_name );
        $role_keys    = function_exists( 'elementsell_get_order_role_keys' )
            ? elementsell_get_order_role_keys( $order )
            : [];

        foreach ( elementsell_automation_get_catalog() as $product ) {
            if ( ! is_array( $product ) ) {
                continue;
            }

            $match = false;

            if ( $product_name !== '' && trim( (string) ( $product['product_name'] ?? '' ) ) === $product_name ) {
                $match = true;
            } elseif ( ! empty( $role_keys ) ) {
                $catalog_role = sanitize_key( (string) ( $product['role_key'] ?? '' ) );

                if ( $catalog_role !== '' && in_array( $catalog_role, $role_keys, true ) ) {
                    $match = true;
                }
            }

            if ( ! $match ) {
                continue;
            }

            $url = elementsell_normalize_customer_source_page_url( (string) ( $product['page_url'] ?? '' ) );

            if ( $url !== '' ) {
                return $url;
            }
        }
    }

    return home_url( '/' );
}

/**
 * ID kotvy na platební widget objednávky.
 *
 * @param object $order
 * @return string
 */
function elementsell_get_order_form_anchor( $order ) {
    if ( ! $order ) {
        return 'elementsell-form';
    }

    $widget_id = trim( (string) elementsell_get_order_field( (int) $order->id, 'elementsell_widget_id' ) );

    if ( $widget_id !== '' ) {
        return 'elementsell-payment-' . $widget_id;
    }

    return 'elementsell-form';
}

/**
 * @param string $url
 * @param string $fragment
 * @return string
 */
function elementsell_append_url_fragment( $url, $fragment ) {
    $url      = trim( (string) $url );
    $fragment = preg_replace( '/[^A-Za-z0-9_\-]/', '', (string) $fragment );

    if ( $url === '' || $fragment === '' ) {
        return $url;
    }

    $url = preg_replace( '/#.*$/', '', $url );

    return $url . '#' . $fragment;
}

/**
 * URL zdrojové stránky s kotvou na platební formulář.
 *
 * @param object $order
 * @return string
 */
function elementsell_get_order_source_page_url_with_form( $order ) {
    return elementsell_append_url_fragment(
        elementsell_get_order_source_page_url( $order ),
        elementsell_get_order_form_anchor( $order )
    );
}

/**
 * @return void
 */
function elementsell_maybe_scroll_to_form_anchor() {
    if ( is_admin() ) {
        return;
    }
    ?>
    <script>
    (function () {
        var hash = (window.location.hash || '').replace(/^#/, '');
        if (!hash) {
            return;
        }
        if (hash.indexOf('elementsell-payment-') !== 0 && hash !== 'elementsell-form') {
            return;
        }

        function scrollToForm() {
            var target = document.getElementById(hash);
            if (!target && hash === 'elementsell-form') {
                target = document.querySelector('.elementsell-payment-widget');
            }
            if (!target) {
                return false;
            }
            target.scrollIntoView({ behavior: 'smooth', block: 'start' });
            return true;
        }

        function tryScroll() {
            if (scrollToForm()) {
                return;
            }
            setTimeout(scrollToForm, 300);
            setTimeout(scrollToForm, 900);
        }

        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', tryScroll);
        } else {
            tryScroll();
        }
    })();
    </script>
    <?php
}

add_action( 'wp_footer', 'elementsell_maybe_scroll_to_form_anchor', 20 );

function elementsell_update_order( $order_id, $data ) {
    global $wpdb;

    $table = function_exists( 'elementsell_get_orders_storage_table_for_id' )
        ? elementsell_get_orders_storage_table_for_id( $order_id )
        : $wpdb->prefix . 'elementsell_orders';

    return $wpdb->update(
        $table,
        $data,
        [ 'id' => $order_id ]
    );
}

/**
 * Atomicky označí objednávku jako zaplacenou. Vrátí true jen při prvním přechodu na paid.
 *
 * @param int                  $order_id
 * @param array<string, mixed> $update_data
 * @return bool
 */
function elementsell_mark_order_payment_paid_atomically( $order_id, $update_data = [] ) {
    global $wpdb;

    $order_id = (int) $order_id;

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

    $table = function_exists( 'elementsell_get_orders_storage_table_for_id' )
        ? elementsell_get_orders_storage_table_for_id( $order_id )
        : $wpdb->prefix . 'elementsell_orders';
    $now   = current_time( 'mysql' );
    $sets  = [
        "payment_status = 'paid'",
        'updated_at = %s',
        'paid_at = COALESCE(paid_at, %s)',
    ];
    $params = [ $now, $now ];

    if ( isset( $update_data['payment_method'] ) ) {
        $payment_method = sanitize_text_field( (string) $update_data['payment_method'] );

        if ( $payment_method !== '' ) {
            $sets[]   = 'payment_method = %s';
            $params[] = $payment_method;
        }
    }

    $params[] = $order_id;

    $sql  = 'UPDATE ' . $table . ' SET ' . implode( ', ', $sets ) . " WHERE id = %d AND payment_status <> 'paid'";
    $rows = $wpdb->query( $wpdb->prepare( $sql, ...$params ) );

    return is_int( $rows ) && $rows > 0;
}

/**
 * @param int $order_id
 * @return string
 */
function elementsell_get_paid_customer_email_lock_option_name( $order_id ) {
    return 'elementsell_paid_email_lock_' . (int) $order_id;
}

/**
 * @param int $order_id
 * @return string
 */
function elementsell_get_merchant_paid_notification_lock_option_name( $order_id ) {
    return 'elementsell_merchant_paid_notified_' . (int) $order_id;
}

/**
 * Atomicky rezervuje odeslání potvrzovacího e-mailu zákazníkovi.
 *
 * @param int $order_id
 * @return bool
 */
function elementsell_claim_paid_customer_email_send( $order_id ) {
    $order_id = (int) $order_id;

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

    if ( ! empty( elementsell_get_order_field( $order_id, 'paid_email_sent_at' ) ) ) {
        return false;
    }

    return add_option(
        elementsell_get_paid_customer_email_lock_option_name( $order_id ),
        (string) time(),
        '',
        'no'
    );
}

/**
 * @param int $order_id
 * @return void
 */
function elementsell_release_paid_customer_email_claim( $order_id ) {
    delete_option( elementsell_get_paid_customer_email_lock_option_name( (int) $order_id ) );
}

/**
 * Atomicky rezervuje upozornění obchodníkovi o zaplacení.
 *
 * @param int $order_id
 * @return bool
 */
function elementsell_claim_merchant_paid_notification( $order_id ) {
    $order_id = (int) $order_id;

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

    if ( ! empty( elementsell_get_order_field( $order_id, 'paid_admin_notification_sent_at' ) ) ) {
        return false;
    }

    return add_option(
        elementsell_get_merchant_paid_notification_lock_option_name( $order_id ),
        (string) time(),
        '',
        'no'
    );
}

/**
 * @param int $order_id
 * @return void
 */
function elementsell_release_merchant_paid_notification_claim( $order_id ) {
    delete_option( elementsell_get_merchant_paid_notification_lock_option_name( (int) $order_id ) );
}

function elementsell_save_order_field( $order_id, $field_name, $field_value ) {
    global $wpdb;

    return $wpdb->insert(
        $wpdb->prefix . 'elementsell_order_fields',
        [
            'order_id'    => intval($order_id),
            'field_name'  => sanitize_key($field_name),
            'field_value' => sanitize_textarea_field((string) $field_value),
            'created_at'  => current_time('mysql', true),
        ],
        [
            '%d',
            '%s',
            '%s',
            '%s',
        ]
    );
}

/**
 * Uloží zákaznické pole s čitelným názvem (label).
 *
 * @param int    $order_id
 * @param string $label
 * @param string $value
 * @return int|false
 */
function elementsell_save_order_label_field( $order_id, $label, $value ) {
    global $wpdb;

    $order_id = (int) $order_id;
    $label    = sanitize_text_field( (string) $label );
    $value    = sanitize_textarea_field( (string) $value );

    if ( $order_id <= 0 || $label === '' || $value === '' ) {
        return false;
    }

    if ( strlen( $label ) > 190 ) {
        $label = substr( $label, 0, 190 );
    }

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

    if ( function_exists( 'elementsell_is_order_archived' ) && elementsell_is_order_archived( $order_id ) ) {
        $table = elementsell_get_order_fields_archive_table_name();
    }

    $existing_id = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT id FROM {$table} WHERE order_id = %d AND field_name = %s LIMIT 1",
            $order_id,
            $label
        )
    );

    if ( $existing_id ) {
        $result = $wpdb->update(
            $table,
            [ 'field_value' => $value ],
            [ 'id' => (int) $existing_id ],
            [ '%s' ],
            [ '%d' ]
        );
    } else {
        $result = $wpdb->insert(
            $table,
            [
                'order_id'    => $order_id,
                'field_name'  => $label,
                'field_value' => $value,
                'created_at'  => current_time( 'mysql', true ),
            ],
            [ '%d', '%s', '%s', '%s' ]
        );
    }

    $legacy_name = sanitize_key( $label );

    if ( $legacy_name !== '' && $legacy_name !== $label ) {
        elementsell_delete_order_field_by_name( $order_id, $legacy_name );
    }

    return $result;
}

/**
 * @return array<int, string>
 */
function elementsell_get_hidden_order_field_names() {
    return [
        'gdpr_consent',
        'gdpr_consent_at',
        'gdpr_privacy_url',
        'vytvorit_profil',
        'login_url',
        'source_page_url',
        'reminder_subject',
        'reminder_body',
        'reminder_sent_count',
        'last_reminder_sent_at',
        'environment',
        'merchant_id',
        'project_id',
        'api_password',
        'api_url',
        'gate_url',
        'payment_detail_url',
        'thepay_error',
        'thepay_exception',
        'thepay_verify_error',
        'fio_test',
        'access_completed_at',
        'email_from',
        'email_from_name',
        'paid_email_sent_at',
        'paid_email_error',
        'paid_admin_notification_sent_at',
        'elementsell_post_id',
        'elementsell_widget_id',
        'landing_demo',
        'elementsell_landing_demo_nonce',
        'elementsell_landing_return_url',
        'billing_test',
        'delivery_health',
        'Upsell doručení',
        'Upsell role',
        'Upsell tlačítko',
        'Upsell odkaz',
        'Upsell informace',
    ];
}

/**
 * @param string $field_name
 * @return bool
 */
function elementsell_order_field_label_is_readable( $field_name ) {
    return (bool) preg_match( '/[A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽáčďéěíňóřšťúůýž ]/u', (string) $field_name );
}

/**
 * @param int    $order_id
 * @param string $stored_name
 * @return string
 */
function elementsell_resolve_customer_field_label( $order_id, $stored_name ) {
    $stored_name = trim( (string) $stored_name );

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

    if ( elementsell_order_field_label_is_readable( $stored_name ) ) {
        return $stored_name;
    }

    $widget_labels = elementsell_get_widget_custom_field_labels_for_order( $order_id );
    $stored_slug   = sanitize_key( $stored_name );

    foreach ( $widget_labels as $label ) {
        if ( sanitize_key( (string) $label ) === $stored_slug ) {
            return (string) $label;
        }
    }

    return $stored_name;
}

/**
 * @param int    $order_id
 * @param string $field_name
 * @return void
 */
function elementsell_delete_order_field_by_name( $order_id, $field_name ) {
    global $wpdb;

    $order_id   = (int) $order_id;
    $field_name = (string) $field_name;

    if ( $order_id <= 0 || $field_name === '' ) {
        return;
    }

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

    $wpdb->delete(
        $table,
        [
            'order_id'   => $order_id,
            'field_name' => $field_name,
        ],
        [ '%d', '%s' ]
    );
}

/**
 * @param int $order_id
 * @return array<int, array{label: string, value: string}>
 */
function elementsell_get_order_customer_fields( $order_id ) {
    global $wpdb;

    $order_id = (int) $order_id;

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

    $table = $wpdb->prefix . 'elementsell_order_fields';
    $rows  = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT field_name, field_value
             FROM {$table}
             WHERE order_id = %d
             ORDER BY id ASC",
            $order_id
        )
    );

    if ( empty( $rows ) && function_exists( 'elementsell_orders_archive_table_exists' ) && elementsell_orders_archive_table_exists() ) {
        $archive_table = elementsell_get_order_fields_archive_table_name();
        $rows          = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT field_name, field_value
                 FROM {$archive_table}
                 WHERE order_id = %d
                 ORDER BY id ASC",
                $order_id
            )
        );
    }

    if ( empty( $rows ) ) {
        return [];
    }

    $hidden = array_flip( elementsell_get_hidden_order_field_names() );
    $fields = [];

    foreach ( $rows as $row ) {
        $stored_name = (string) $row->field_name;
        $key         = sanitize_key( $stored_name );

        if ( isset( $hidden[ $key ] ) || isset( $hidden[ $stored_name ] ) ) {
            continue;
        }

        $value = trim( (string) $row->field_value );

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

        $label = elementsell_resolve_customer_field_label( $order_id, $stored_name );

        if ( isset( $fields[ $label ] ) ) {
            if ( elementsell_order_field_label_is_readable( $stored_name ) ) {
                $fields[ $label ] = $value;
            }
            continue;
        }

        $fields[ $label ] = $value;
    }

    $result = [];

    foreach ( $fields as $label => $value ) {
        $result[] = [
            'label' => $label,
            'value' => $value,
        ];
    }

    return $result;
}

/**
 * @param array<int> $order_ids
 * @return array<int, array<int, array{label: string, value: string}>>
 */
function elementsell_get_customer_fields_for_orders( $order_ids ) {
    $order_ids = array_values( array_filter( array_map( 'intval', (array) $order_ids ) ) );

    if ( empty( $order_ids ) ) {
        return [];
    }

    $grouped = [];

    foreach ( $order_ids as $order_id ) {
        $grouped[ $order_id ] = elementsell_get_order_customer_fields( $order_id );
    }

    return $grouped;
}

/**
 * @param int    $order_id
 * @param string $field_name
 * @param string $field_value
 * @return int|false
 */
function elementsell_upsert_order_field( $order_id, $field_name, $field_value ) {
    global $wpdb;

    $order_id   = (int) $order_id;
    $field_name = sanitize_key( (string) $field_name );
    $table      = $wpdb->prefix . 'elementsell_order_fields';

    if ( function_exists( 'elementsell_is_order_archived' ) && elementsell_is_order_archived( $order_id ) ) {
        $table = elementsell_get_order_fields_archive_table_name();
    }

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

    $existing_id = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT id FROM {$table} WHERE order_id = %d AND field_name = %s LIMIT 1",
            $order_id,
            $field_name
        )
    );

    $value = sanitize_textarea_field( (string) $field_value );

    if ( $existing_id ) {
        return $wpdb->update(
            $table,
            [ 'field_value' => $value ],
            [
                'id' => (int) $existing_id,
            ],
            [ '%s' ],
            [ '%d' ]
        );
    }

    if ( elementsell_is_order_archived( $order_id ) ) {
        return $wpdb->insert(
            $table,
            [
                'order_id'    => $order_id,
                'field_name'  => $field_name,
                'field_value' => $value,
                'created_at'  => current_time( 'mysql', true ),
            ],
            [ '%d', '%s', '%s', '%s' ]
        );
    }

    return elementsell_save_order_field( $order_id, $field_name, $value );
}