<?php
/**
 * Meta pixel — prohlížečová polovina měření.
 *
 * Conversions API v meta-capi.php posílá Purchase ze serveru. Meta ale chce
 * klíčové události dostávat OBĚMA kanály a spárovat je přes event_id; jinak
 * hlásí „Nízká míra událostí pixelu pokrytých Conversions API" a zhoršuje
 * atribuci. Tenhle modul dodává tu druhou polovinu.
 *
 * Zásady:
 * - Je to DOPLNĚK, ne konkurent. Když je na stránce cizí pixel (typicky plugin
 *   „Meta pixel pro WordPress"), základní kód nevkládáme — jen chybějící událost.
 * - Purchase používá STEJNÉ event_id jako CAPI, takže Meta obojí sloučí do
 *   jednoho nákupu. Funguje to i při obnovení stránky.
 * - Děkovací stránka se u některých šablon vykresluje mimo wp_head/wp_footer,
 *   proto se obsah zachytává výstupním bufferem.
 *
 * @package ElementSell
 */

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

add_action( 'template_redirect', 'elementsell_meta_pixel_maybe_start_buffer', 20 );

/**
 * Je prohlížečová polovina zapnutá?
 *
 * @return bool
 */
function elementsell_meta_pixel_is_enabled() {
    $enabled = get_option( 'elementsell_meta_pixel_browser_enabled', '1' ) !== '0';

    return (bool) apply_filters( 'elementsell_meta_pixel_enabled', $enabled );
}

/**
 * ID pixelu — sdílené s CAPI, ať se nemohou rozejít.
 *
 * @return string
 */
function elementsell_meta_pixel_get_id() {
    if ( function_exists( 'elementsell_meta_capi_get_pixel_id' ) ) {
        return (string) elementsell_meta_capi_get_pixel_id();
    }

    return '';
}

/**
 * Zaplacená objednávka pro aktuální požadavek (návrat z platby / z e-mailu).
 *
 * @return object|null
 */
function elementsell_meta_pixel_get_current_paid_order() {
    static $cache = false;

    if ( $cache !== false ) {
        return $cache;
    }

    $cache = null;

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

    $uid = '';

    if ( function_exists( 'elementsell_get_thank_you_request_payment_uid' ) ) {
        $uid = (string) elementsell_get_thank_you_request_payment_uid();
    }

    if ( $uid === '' && isset( $_GET['payment_uid'] ) ) {
        $uid = sanitize_text_field( wp_unslash( $_GET['payment_uid'] ) );
    }

    if ( $uid === '' ) {
        return null;
    }

    $order = elementsell_get_order_by_payment_uid( $uid );

    if ( ! $order || (string) ( $order->payment_status ?? '' ) !== 'paid' ) {
        return null;
    }

    $cache = $order;

    return $cache;
}

/**
 * Spustí zachytávání výstupu, jen když je co doplnit.
 *
 * @return void
 */
function elementsell_meta_pixel_maybe_start_buffer() {
    if ( ! elementsell_meta_pixel_is_enabled() ) {
        return;
    }

    if ( elementsell_meta_pixel_get_id() === '' ) {
        return;
    }

    if ( ! elementsell_meta_pixel_get_current_paid_order() ) {
        return;
    }

    ob_start( 'elementsell_meta_pixel_inject_into_html' );
}

/**
 * Doplní do hotového HTML chybějící Purchase (a základní pixel, když chybí).
 *
 * @param string $html
 * @return string
 */
function elementsell_meta_pixel_inject_into_html( $html ) {
    $order = elementsell_meta_pixel_get_current_paid_order();

    if ( ! $order || strripos( $html, '</body>' ) === false ) {
        return $html;
    }

    // Purchase už na stránce je (jiný plugin, šablona) — nepřidávat podruhé.
    if ( preg_match( '/fbq\s*\(\s*[\'"]track[A-Za-z]*[\'"]\s*,\s*[\'"]Purchase[\'"]/i', $html ) ) {
        return $html;
    }

    /*
     * Cizí pixel nepoznáme jen podle fbq('init'). Oficiální plugin „Meta pixel
     * pro WordPress" startuje přes FacebookSignal.initPixel(), takže by nám
     * podle staré detekce prošel a základní kód bychom vložili podruhé —
     * výsledkem dvojitý PageView.
     */
    $has_pixel = (bool) preg_match(
        '/(fbq\s*\(\s*[\'"]init[\'"]|FacebookSignal\s*\.\s*initPixel|connect\.facebook\.net\/[^\'"]*fbevents\.js)/i',
        $html
    );
    $script    = elementsell_meta_pixel_build_script( $order, $has_pixel );

    if ( $script === '' ) {
        return $html;
    }

    $pos = strripos( $html, '</body>' );

    // Stopa pro diagnostiku v adminu — ať je vidět, že prohlížečová půlka jede.
    update_option(
        'elementsell_meta_pixel_last_purchase',
        [
            'cas'      => current_time( 'mysql', true ),
            'event_id' => function_exists( 'elementsell_meta_capi_get_event_id' )
                ? (string) elementsell_meta_capi_get_event_id( $order )
                : '',
            'vlastni_pixel' => ! $has_pixel,
        ],
        false
    );

    return substr( $html, 0, $pos ) . $script . substr( $html, $pos );
}

/**
 * @param object $order
 * @return array<string, mixed>
 */
function elementsell_meta_pixel_get_purchase_params( $order ) {
    $currency = strtoupper( trim( (string) ( $order->currency ?? '' ) ) );

    $params = [
        'value'        => round( (float) ( $order->amount ?? 0 ), 2 ),
        'currency'     => $currency !== '' ? $currency : 'CZK',
        'content_name' => (string) ( $order->product_name ?? '' ),
        'content_type' => 'product',
    ];

    return (array) apply_filters( 'elementsell_meta_pixel_purchase_params', $params, $order );
}

/**
 * @param object $order
 * @param bool   $has_pixel Základní pixel už na stránce je.
 * @return string
 */
function elementsell_meta_pixel_build_script( $order, $has_pixel ) {
    $pixel_id = elementsell_meta_pixel_get_id();

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

    $event_id = function_exists( 'elementsell_meta_capi_get_event_id' )
        ? (string) elementsell_meta_capi_get_event_id( $order )
        : '';

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

    $params = elementsell_meta_pixel_get_purchase_params( $order );

    /*
     * Skládáme řetězcem, ne přes ob_start() — tahle funkce běží uvnitř callbacku
     * výstupního bufferu a tam PHP další buffer otevřít nedovolí (výsledkem by
     * byla prázdná stránka).
     */
    $out = "\n<!-- ElementSell: Purchase spárovaný s Conversions API přes event_id -->\n"
         . "<script>\n(function () {\n";

    if ( ! $has_pixel ) {
        $out .= "  !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?\n"
              . "  n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;\n"
              . "  n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;\n"
              . "  t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}\n"
              . "  (window,document,'script','https://connect.facebook.net/en_US/fbevents.js');\n"
              . '  fbq("init", ' . wp_json_encode( $pixel_id ) . ");\n"
              . "  fbq(\"track\", \"PageView\");\n";
    } else {
        $out .= "  if (typeof fbq !== 'function') { return; }\n";
    }

    $out .= '  fbq("track", "Purchase", ' . wp_json_encode( $params )
          . ', { eventID: ' . wp_json_encode( $event_id ) . " });\n"
          . "})();\n</script>\n";

    return $out;
}
