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

add_action( 'elementsell_order_paid', 'elementsell_telemetry_report_sale', 20, 1 );
add_action( 'elementsell_daily_billing_check', 'elementsell_telemetry_send_heartbeat', 5 );
add_action( 'admin_init', 'elementsell_telemetry_maybe_register_existing_site' );
add_action( 'admin_init', 'elementsell_telemetry_maybe_refresh_setup_snapshot', 20 );
add_action( 'plugins_loaded', 'elementsell_telemetry_maybe_send_on_upgrade', 99 );

/**
 * @return string
 */
function elementsell_telemetry_get_install_id() {
    $install_id = (string) get_option( 'elementsell_install_id', '' );

    if ( $install_id === '' ) {
        $install_id = wp_generate_password( 32, false, false );
        update_option( 'elementsell_install_id', $install_id, false );
    }

    return $install_id;
}

/**
 * Načte $ELEMENTSELL_SECRET z kořene webu (pouze na update serveru).
 *
 * @return string
 */
function elementsell_telemetry_read_local_server_secret() {
    if ( ! function_exists( 'elementsell_should_sync_publish_endpoint' ) || ! elementsell_should_sync_publish_endpoint() ) {
        return '';
    }

    $secrets_file = trailingslashit( ABSPATH ) . 'elementsell-secrets.php';

    if ( ! is_readable( $secrets_file ) ) {
        return '';
    }

    $ELEMENTSELL_SECRET = '';

    include $secrets_file;

    if ( ! isset( $ELEMENTSELL_SECRET ) || ! is_string( $ELEMENTSELL_SECRET ) ) {
        return '';
    }

    $secret = trim( $ELEMENTSELL_SECRET );

    $invalid = [
        '',
        'your_secret_token',
        'change_me_stats_token',
        'change_me_stats_password',
        'change_me_strong_password',
        'oselosralosla',
    ];

    if ( in_array( $secret, $invalid, true ) ) {
        return '';
    }

    return $secret;
}

/**
 * Token pro centrální API (telemetrie, credentials, faktury).
 * Distribuovaný ZIP obsahuje hodnotu v ELEMENTSELL_DISTRIBUTED_TOKEN.
 *
 * @return string
 */
function elementsell_telemetry_get_token() {
    if ( defined( 'ELEMENTSELL_DISTRIBUTED_TOKEN' ) && is_string( ELEMENTSELL_DISTRIBUTED_TOKEN ) ) {
        $token = trim( ELEMENTSELL_DISTRIBUTED_TOKEN );

        if ( $token !== '' && $token !== 'your_secret_token' ) {
            return $token;
        }
    }

    $local_secret = elementsell_telemetry_read_local_server_secret();

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

    return (string) apply_filters( 'elementsell_telemetry_token', 'your_secret_token' );
}

/**
 * @return bool
 */
function elementsell_telemetry_token_is_configured() {
    $token = elementsell_telemetry_get_token();

    return $token !== '' && $token !== 'your_secret_token';
}

/**
 * @return string
 */
function elementsell_telemetry_get_endpoint_url() {
    $url = 'https://elementsell.cz/elementsell_stats.php?token=' . rawurlencode( elementsell_telemetry_get_token() );

    return (string) apply_filters( 'elementsell_telemetry_endpoint_url', $url );
}

/**
 * @return array<string, mixed>
 */
function elementsell_telemetry_get_base_payload() {
    $payload = [
        'install_id'     => elementsell_telemetry_get_install_id(),
        'site_url'       => get_site_url(),
        'site_host'      => (string) wp_parse_url( home_url(), PHP_URL_HOST ),
        'plugin_version' => defined( 'PF_VERSION' ) ? PF_VERSION : '',
        'wp_version'     => get_bloginfo( 'version' ),
        'php_version'    => PHP_VERSION,
        'owner_name'     => (string) get_option( 'faktury_jmeno', '' ),
        'owner_email'    => function_exists( 'elementsell_get_invoice_supplier_email' )
            ? elementsell_get_invoice_supplier_email()
            : (string) get_option( 'faktury_email', '' ),
        'paid_orders'    => elementsell_get_production_paid_orders_count(),
        'has_card'       => elementsell_billing_has_saved_card() ? 1 : 0,
        'is_blocked'     => elementsell_is_billing_blocked() ? 1 : 0,
        'payment_failed' => elementsell_billing_is_payment_failed() ? 1 : 0,
    ];

    if ( function_exists( 'elementsell_telemetry_get_setup_health' ) ) {
        $payload = array_merge( $payload, elementsell_telemetry_get_setup_health() );
    }

    return $payload;
}

/**
 * @param array<string, mixed>|WP_Error $response
 * @return array{ok: bool, http_code: int, message: string, checked_at: int}
 */
function elementsell_telemetry_parse_response( $response ) {
    $checked_at = time();

    if ( is_wp_error( $response ) ) {
        return [
            'ok'         => false,
            'http_code'  => 0,
            'message'    => $response->get_error_message(),
            'checked_at' => $checked_at,
        ];
    }

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

    if ( $http_code >= 200 && $http_code < 300 && is_array( $data ) && ! empty( $data['ok'] ) ) {
        return [
            'ok'         => true,
            'http_code'  => $http_code,
            'message'    => 'OK',
            'checked_at' => $checked_at,
        ];
    }

    if ( is_array( $data ) && ! empty( $data['message'] ) ) {
        $message = (string) $data['message'];
    } elseif ( $http_code === 403 ) {
        $message = 'Neplatný token telemetrie (403).';
    } elseif ( $http_code === 503 ) {
        $message = 'Server statistik není nakonfigurován (503).';
    } elseif ( $http_code > 0 ) {
        $message = 'Server vrátil HTTP ' . $http_code . '.';
    } else {
        $message = 'Prázdná odpověď serveru.';
    }

    if ( $http_code === 200 && stripos( $body, '<html' ) !== false ) {
        $message = 'Server odmítl token (vrátil přihlašovací stránku místo JSON).';
    }

    return [
        'ok'         => false,
        'http_code'  => $http_code,
        'message'    => $message,
        'checked_at' => $checked_at,
    ];
}

/**
 * @param string               $event_type
 * @param array<string, mixed> $data
 * @param bool                 $blocking
 * @return array{ok: bool, http_code: int, message: string, checked_at: int}
 */
function elementsell_telemetry_send( $event_type, $data = [], $blocking = false ) {
    $body = array_merge(
        elementsell_telemetry_get_base_payload(),
        $data,
        [
            'event' => sanitize_key( $event_type ),
        ]
    );

    $response = wp_remote_post(
        elementsell_telemetry_get_endpoint_url(),
        [
            'timeout'  => 10,
            'blocking' => $blocking,
            'body'     => $body,
        ]
    );

    $result = elementsell_telemetry_parse_response( $response );

    elementsell_telemetry_store_send_result( $event_type, $result, $blocking );

    return $result;
}

/**
 * @param string               $event_type
 * @param array<string, mixed> $result
 * @param bool                 $blocking
 * @return void
 */
function elementsell_telemetry_store_send_result( $event_type, $result, $blocking ) {
    $entry = array_merge(
        $result,
        [
            'event' => sanitize_key( $event_type ),
        ]
    );

    if ( $blocking ) {
        update_option( 'elementsell_telemetry_last_result', $entry, false );
    }

    if ( empty( $result['ok'] ) ) {
        $log = get_option( 'elementsell_telemetry_debug_log', [] );

        if ( ! is_array( $log ) ) {
            $log = [];
        }

        array_unshift(
            $log,
            array_merge(
                $entry,
                [
                    'blocking' => $blocking ? 1 : 0,
                ]
            )
        );

        $log = array_slice( $log, 0, 20 );
        update_option( 'elementsell_telemetry_debug_log', $log, false );
    }
}

/**
 * @return string
 */
function elementsell_telemetry_get_sent_version() {
    $sent = (string) get_option( 'elementsell_telemetry_sent_version', '' );

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

    return (string) get_option( 'elementsell_plugin_version', '' );
}

/**
 * @param string $version
 * @return void
 */
function elementsell_telemetry_mark_sent_version( $version ) {
    $version = (string) $version;

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

    update_option( 'elementsell_telemetry_sent_version', $version, false );
    update_option( 'elementsell_plugin_version', $version, false );
}

/**
 * @return bool
 */
function elementsell_telemetry_has_pending_upgrade() {
    return (bool) get_transient( 'elementsell_telemetry_pending_upgrade' );
}

/**
 * @return void
 */
function elementsell_telemetry_clear_pending_upgrade() {
    delete_transient( 'elementsell_telemetry_pending_upgrade' );
}

/**
 * @return void
 */
function elementsell_telemetry_send_activation() {
    elementsell_telemetry_send(
        'activation',
        [
            'activated_at' => current_time( 'mysql' ),
        ],
        true
    );
}

/**
 * @return void
 */
function elementsell_telemetry_send_heartbeat() {
    $previous_month = strtotime( 'first day of previous month' );
    $year           = (int) gmdate( 'Y', $previous_month );
    $month          = (int) gmdate( 'n', $previous_month );

    elementsell_telemetry_send(
        'heartbeat',
        [
            'heartbeat_at'       => current_time( 'mysql' ),
            'prev_month_revenue' => elementsell_get_production_revenue_for_month( $year, $month ),
        ]
    );

    if ( class_exists( 'ElementSell_Cron_Log' ) && ElementSell_Cron_Log::is_active() ) {
        ElementSell_Cron_Log::add( 'Telemetrie odeslána' );
    }
}

/**
 * @param int $order_id
 * @return void
 */
function elementsell_telemetry_report_sale( $order_id ) {
    $order_id = (int) $order_id;

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

    if ( get_option( 'elementsell_telemetry_sale_' . $order_id, '' ) === '1' ) {
        return;
    }

    $order = elementsell_get_order( $order_id );

    if ( ! $order || elementsell_is_demo_order( $order ) ) {
        return;
    }

    if ( strpos( (string) $order->order_uid, 'es_test_' ) === 0 ) {
        return;
    }

    if ( elementsell_get_order_field( $order_id, 'billing_test' ) === '1' ) {
        return;
    }

    $result = elementsell_telemetry_send(
        'sale',
        [
            'order_id'       => $order_id,
            'order_uid'      => (string) $order->order_uid,
            'payment_uid'    => (string) $order->payment_uid,
            'amount'         => (float) $order->amount,
            'currency'       => (string) $order->currency,
            'product_name'   => (string) $order->product_name,
            'payment_method' => (string) $order->payment_method,
            'paid_at'        => (string) ( $order->paid_at ?: current_time( 'mysql' ) ),
        ],
        true
    );

    if ( ! empty( $result['ok'] ) ) {
        update_option( 'elementsell_telemetry_sale_' . $order_id, '1', false );
    }
}

/**
 * @param array<string, mixed> $data
 * @return void
 */
function elementsell_telemetry_report_fee_charge( $data ) {
    elementsell_telemetry_send( 'fee_charged', $data );
}

/**
 * @param array<string, mixed> $data
 * @return void
 */
function elementsell_telemetry_report_fee_failed( $data ) {
    elementsell_telemetry_send( 'fee_failed', $data );
}

/**
 * @return bool
 */
function elementsell_telemetry_should_attempt_registration() {
    if ( elementsell_telemetry_has_pending_upgrade() ) {
        return true;
    }

    if ( get_option( 'elementsell_telemetry_registered', '' ) !== '1' ) {
        return true;
    }

    $last = get_option( 'elementsell_telemetry_last_result', [] );

    if ( ! is_array( $last ) || ! empty( $last['ok'] ) ) {
        return false;
    }

    $checked_at = isset( $last['checked_at'] ) ? (int) $last['checked_at'] : 0;

    return $checked_at <= 0 || ( time() - $checked_at ) >= HOUR_IN_SECONDS;
}

/**
 * @return void
 */
function elementsell_telemetry_maybe_register_existing_site() {
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }

    if ( ! elementsell_telemetry_token_is_configured() ) {
        return;
    }

    if ( ! elementsell_telemetry_should_attempt_registration() ) {
        return;
    }

    if ( elementsell_telemetry_has_pending_upgrade() ) {
        elementsell_telemetry_send_now();

        return;
    }

    $result = elementsell_telemetry_send(
        'heartbeat',
        [
            'heartbeat_at' => current_time( 'mysql' ),
            'boot'         => 1,
        ],
        true
    );

    if ( ! empty( $result['ok'] ) ) {
        update_option( 'elementsell_telemetry_registered', '1', false );

        if ( defined( 'PF_VERSION' ) ) {
            elementsell_telemetry_mark_sent_version( PF_VERSION );
        }
    }
}

/**
 * Jednou po nasazení setup health pošle kompletní snapshot do centrálních statistik.
 *
 * @return void
 */
function elementsell_telemetry_maybe_refresh_setup_snapshot() {
    if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
        return;
    }

    if ( ! elementsell_telemetry_token_is_configured() ) {
        return;
    }

    if ( ! function_exists( 'elementsell_telemetry_get_setup_health' ) ) {
        return;
    }

    $schema = 2;

    if ( (int) get_option( 'elementsell_telemetry_setup_schema', 0 ) >= $schema ) {
        return;
    }

    $result = elementsell_telemetry_send(
        'heartbeat',
        [
            'heartbeat_at'  => current_time( 'mysql' ),
            'setup_refresh' => 1,
        ],
        true
    );

    if ( ! empty( $result['ok'] ) ) {
        update_option( 'elementsell_telemetry_setup_schema', $schema, false );
        update_option( 'elementsell_telemetry_registered', '1', false );
    }
}

/**
 * @return void
 */
function elementsell_telemetry_report_card_saved() {
    elementsell_telemetry_send(
        'card_saved',
        [
            'saved_at' => current_time( 'mysql' ),
        ],
        true
    );
}

/**
 * @param bool $force
 * @return array<string, mixed>
 */
function elementsell_telemetry_get_diagnostics( $force = false ) {
    $cached = get_option( 'elementsell_telemetry_last_result', [] );

    if ( ! $force && is_array( $cached ) && ! empty( $cached['checked_at'] ) ) {
        return array_merge(
            elementsell_telemetry_get_diagnostics_snapshot(),
            $cached
        );
    }

    $result = elementsell_telemetry_send(
        'heartbeat',
        [
            'heartbeat_at' => current_time( 'mysql' ),
            'diagnostic'   => 1,
        ],
        true
    );

    return array_merge(
        elementsell_telemetry_get_diagnostics_snapshot(),
        $result
    );
}

/**
 * @return array<string, mixed>
 */
function elementsell_telemetry_get_diagnostics_snapshot() {
    $token       = elementsell_telemetry_get_token();
    $token_ok    = elementsell_telemetry_token_is_configured();
    $endpoint    = elementsell_telemetry_get_endpoint_url();
    $registered  = get_option( 'elementsell_telemetry_registered', '' ) === '1';
    $install_id  = elementsell_telemetry_get_install_id();
    $token_hint  = $token_ok ? substr( $token, 0, 4 ) . '…' . substr( $token, -4 ) : 'your_secret_token';

    return [
        'install_id'        => $install_id,
        'site_host'         => (string) wp_parse_url( home_url(), PHP_URL_HOST ),
        'endpoint_url'      => preg_replace( '/token=[^&]+/', 'token=' . rawurlencode( $token_hint ), $endpoint ),
        'token_configured'  => $token_ok,
        'token_hint'        => $token_hint,
        'registered_option' => $registered,
        'has_card'          => elementsell_billing_has_saved_card(),
        'plugin_version'    => defined( 'PF_VERSION' ) ? PF_VERSION : '',
    ];
}

/**
 * Po aktualizaci pluginu (bez reaktivace) odešle heartbeat včetně stavu karty.
 *
 * @return void
 */
function elementsell_telemetry_maybe_send_on_upgrade() {
    $current = defined( 'PF_VERSION' ) ? (string) PF_VERSION : '';

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

    if ( ! elementsell_telemetry_token_is_configured() ) {
        return;
    }

    $pending_upgrade = elementsell_telemetry_has_pending_upgrade();
    $sent_version    = elementsell_telemetry_get_sent_version();
    $registered      = get_option( 'elementsell_telemetry_registered', '' ) === '1';
    $last            = get_option( 'elementsell_telemetry_last_result', [] );
    $last_ok         = is_array( $last ) && ! empty( $last['ok'] );

    $needs_send = $pending_upgrade
        || ! $registered
        || ! $last_ok
        || $sent_version === ''
        || version_compare( $current, $sent_version, '>' );

    if ( ! $needs_send ) {
        return;
    }

    $result = elementsell_telemetry_send_now();

    if ( ! empty( $result['ok'] ) ) {
        elementsell_telemetry_mark_sent_version( $current );
        elementsell_telemetry_clear_pending_upgrade();
    }
}

/**
 * @return array{ok: bool, http_code: int, message: string, checked_at: int}
 */
function elementsell_telemetry_send_now() {
    delete_option( 'elementsell_telemetry_registered' );

    $result = elementsell_telemetry_send(
        'heartbeat',
        [
            'heartbeat_at' => current_time( 'mysql' ),
            'manual'       => 1,
        ],
        true
    );

    if ( ! empty( $result['ok'] ) ) {
        update_option( 'elementsell_telemetry_registered', '1', false );

        if ( defined( 'PF_VERSION' ) ) {
            elementsell_telemetry_mark_sent_version( PF_VERSION );
        }

        elementsell_telemetry_clear_pending_upgrade();
    }

    return $result;
}
