<?php
/**
 * Adds a small Amazon product box with a price alert feature.
 *
 * Displays a compact Amazon product box, including the product image, title,
 * price details, and an optional discount label. Users can set a price alert
 * to receive notifications when the price drops below their desired amount.
 *
 * Uses Amazon’s PA-API to fetch product data, stores price tracking information
 * in a custom database table, and schedules a cron job for periodic updates.
 *
 * @package Boxyfy
 * 
 */

// ----------------------------------------------
// 0) Sicherheitscheck
// ----------------------------------------------
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// ----------------------------------------------
// A) Lizenzüberprüfung und erforderliche Klassen
// ----------------------------------------------
if ( ! class_exists( 'AwsV4' ) ) {
	// require_once 'path-to-your/AwsV4.php';
}

// ----------------------------------------------
// B) Tabellen erstellen und Cron-Job einplanen
// ----------------------------------------------
add_action( 'init', 'boxyfy_amazon_preiswecker_init_fallback' );
function boxyfy_amazon_preiswecker_init_fallback() {
	boxyfy_amazon_preiswecker_create_tables_if_needed();
	if ( ! wp_next_scheduled( 'boxyfy_amazon_smallproductbox_preiswecker_update' ) ) {
		wp_schedule_event( time(), 'every_12_hours', 'boxyfy_amazon_smallproductbox_preiswecker_update' );
	}
}

function boxyfy_amazon_preiswecker_create_tables_if_needed() {
	global $wpdb;
	$table_preisabrufe = esc_sql( $wpdb->prefix . 'boxyfy_amazon_preiswecker_preisabrufe' );
	$table_zielpreise  = esc_sql( $wpdb->prefix . 'boxyfy_amazon_preiswecker_zielpreise' );
	$charset_collate   = $wpdb->get_charset_collate();
	require_once ABSPATH . 'wp-admin/includes/upgrade.php';

	$sql1 = "CREATE TABLE IF NOT EXISTS $table_preisabrufe (
		id MEDIUMINT NOT NULL AUTO_INCREMENT,
		asin VARCHAR(20) NOT NULL,
		price FLOAT NOT NULL,
		recorded_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
		PRIMARY KEY (id)
	) $charset_collate;";
	dbDelta( $sql1 );

	$sql2 = "CREATE TABLE IF NOT EXISTS $table_zielpreise (
		id MEDIUMINT NOT NULL AUTO_INCREMENT,
		asin VARCHAR(20) NOT NULL,
		target_price FLOAT NOT NULL,
		email VARCHAR(255) NOT NULL,
		notified TINYINT(1) DEFAULT 0 NOT NULL,
		created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
		PRIMARY KEY (id)
	) $charset_collate;";
	dbDelta( $sql2 );
}

// ----------------------------------------------
// C) Aktivierungs- und Deaktivierungshooks
// ----------------------------------------------
register_activation_hook( BOXYFY_PLUGIN_FILE, 'boxyfy_amazon_preiswecker_activate' );
function boxyfy_amazon_preiswecker_activate() {
	boxyfy_amazon_preiswecker_create_tables_if_needed();
	boxyfy_amazon_preiswecker_schedule_cron();
}

register_deactivation_hook( BOXYFY_PLUGIN_FILE, 'boxyfy_amazon_preiswecker_deactivate' );
function boxyfy_amazon_preiswecker_deactivate() {
	wp_clear_scheduled_hook( 'boxyfy_amazon_smallproductbox_preiswecker_update' );
}

// ----------------------------------------------
// D) Cron-Schedule hinzufügen
// ----------------------------------------------
add_filter( 'cron_schedules', 'boxyfy_amazon_preiswecker_add_cron_schedules' );
function boxyfy_amazon_preiswecker_add_cron_schedules( $schedules ) {
	if ( ! isset( $schedules['every_12_hours'] ) ) {
		$schedules['every_12_hours'] = array(
			'interval' => 12 * 3600,
			'display'  => __( 'Alle 12 Stunden', 'boxyfy' ),
		);
	}
	return $schedules;
}

// ----------------------------------------------
// E) Cron-Job planen
// ----------------------------------------------
function boxyfy_amazon_preiswecker_schedule_cron() {
	if ( ! wp_next_scheduled( 'boxyfy_amazon_smallproductbox_preiswecker_update' ) ) {
		wp_schedule_event( time(), 'every_12_hours', 'boxyfy_amazon_smallproductbox_preiswecker_update' );
	}
}

// ----------------------------------------------
// F) Cron-Job Callback-Funktion
// ----------------------------------------------
add_action( 'boxyfy_amazon_smallproductbox_preiswecker_update', 'boxyfy_amazon_preiswecker_cron_update_prices' );
function boxyfy_amazon_preiswecker_cron_update_prices() {
	global $wpdb;
	$table_zielpreise  = esc_sql( $wpdb->prefix . 'boxyfy_amazon_preiswecker_zielpreise' );
	$table_preisabrufe = esc_sql( $wpdb->prefix . 'boxyfy_amazon_preiswecker_preisabrufe' );

	// Alle ASINs ermitteln, für die es (noch) nicht benachrichtigte Einträge gibt
	$safe_table = esc_sql( $table_zielpreise );
	$asins = $wpdb->get_col( $wpdb->prepare(
		"SELECT DISTINCT asin FROM $safe_table WHERE notified = %d",
		0
	));

	if ( empty( $asins ) ) {
		return;
	}

	$options     = get_option( 'boxyfy_amazon_settings', array() );
	$partner_tag = isset( $options['partner_tag'] ) ? sanitize_text_field( $options['partner_tag'] ) : '';

	foreach ( $asins as $asin ) {
		$current_price = boxyfy_amazon_preiswecker_fetch_price_via_api( $asin );
		if ( $current_price === false || $current_price <= 0 ) {
			continue;
		}

		// Letzten Preis aus der DB
		$last_price = $wpdb->get_var( $wpdb->prepare(
			"SELECT price FROM {$table_preisabrufe} WHERE asin = %s ORDER BY recorded_at DESC LIMIT 1",
			$asin
		));

		// Eintrag in die Historie (wenn neuer Preis)
		if ( $last_price === null || floatval( $last_price ) !== floatval( $current_price ) ) {
			$wpdb->insert(
				$table_preisabrufe,
				array(
					'asin'        => $asin,
					'price'       => $current_price,
					'recorded_at' => current_time( 'mysql' ),
				),
				array( '%s', '%f', '%s' )
			);
		}
	}

	boxyfy_amazon_preiswecker_check_alerts_and_notify();
}

/**
 * Ruft den aktuellen Preis eines Produkts via API ab.
 *
 * @param string $asin
 * @return float|false
 */
function boxyfy_amazon_preiswecker_fetch_price_via_api( $asin ) {
	$product_data = boxyfy_get_amazon_product_data_small_box( $asin );
	if ( ! $product_data || empty( $product_data['price'] ) ) {
		return false;
	}
	$raw_price = str_replace( array( '€', ',' ), array( '', '.' ), $product_data['price'] );
	$price     = floatval( $raw_price );
	return ( $price > 0 ) ? $price : false;
}

/**
 * Überprüft, ob Preisalarme ausgelöst werden sollen und sendet ggf. Benachrichtigungen.
 *
 * @global wpdb $wpdb
 * @return void
 */
function boxyfy_amazon_preiswecker_check_alerts_and_notify() {
	global $wpdb;
	$table_zielpreise  = esc_sql( $wpdb->prefix . 'boxyfy_amazon_preiswecker_zielpreise' );
	$table_preisabrufe = esc_sql( $wpdb->prefix . 'boxyfy_amazon_preiswecker_preisabrufe' );
	$options           = get_option( 'boxyfy_amazon_settings', array() );
	$partner_tag       = isset( $options['partner_tag'] ) ? sanitize_text_field( $options['partner_tag'] ) : '';

	// Alle Alerts mit notified=0
	$alerts = $wpdb->get_results( "SELECT * FROM {$table_zielpreise} WHERE notified = 0" );

	foreach ( $alerts as $alert ) {
		// Letzten Preis aus DB
		$current_price = $wpdb->get_var( $wpdb->prepare(
			"SELECT price FROM {$table_preisabrufe} WHERE asin = %s ORDER BY recorded_at DESC LIMIT 1",
			$alert->asin
		));
		if ( $current_price === null ) {
			continue;
		}

		// Check: Ist aktueller Preis <= Wunschpreis?
		if ( floatval( $current_price ) <= floatval( $alert->target_price ) ) {
			$purchase_url = "https://www.amazon.de/dp/{$alert->asin}?tag={$partner_tag}&linkCode=ogi&th=1";
			$domain_parts = wp_parse_url( home_url() );
			$domain_host  = isset( $domain_parts['host'] ) ? $domain_parts['host'] : '';
			$product_data = boxyfy_get_amazon_product_data_small_box( $alert->asin );

			if ( $product_data && ! empty( $product_data['title'] ) ) {
				$product_title = mb_strimwidth( $product_data['title'], 0, 100, '...' );
			} else {
				$product_title = __( 'Amazon-Produkt', 'boxyfy' );
			}
			$subject = __( 'Preiswecker: Wunschpreis wurde erreicht!', 'boxyfy' );
			$message = "
				" . __( 'Hallo,', 'boxyfy' ) . "<br><br>
				" . __( 'Du hattest für das Amazon-Produkt:', 'boxyfy' ) . " <strong><br><br>
				{$product_title}<br><br></strong> " . __( 'einen Wunschpreis von', 'boxyfy' ) . " <strong>" . number_format( $alert->target_price, 2, ',', '.' ) . " €</strong> " . __( 'auf der Website', 'boxyfy' ) . " {$domain_host} " . __( 'über den Preiswecker gespeichert.', 'boxyfy' ) . "<br><br>
				" . __( 'Aktuell liegt der Preis bei nur', 'boxyfy' ) . " <strong style=\"color: green;\">" . number_format( $current_price, 2, ',', '.' ) . " €</strong><br><br>
				<a href=\"{$purchase_url}\" style=\"display:inline-block;padding:10px 15px;background:#e86c07;color:#fff;text-decoration:none;border-radius:11px;font-weight:600;\">" . __( 'Produkt jetzt auf Amazon ansehen', 'boxyfy' ) . "</a><br><br>
				" . __( 'Viel Erfolg beim Sparen!', 'boxyfy' ) . "
			";
			$headers = array(
				'From: ' . __( 'Dein Amazon-Preiswecker', 'boxyfy' ) . ' <no-reply@' . $domain_host . '>',
				'Content-Type: text/html; charset=UTF-8',
			);

			wp_mail( $alert->email, $subject, $message, $headers );

			// Datensatz löschen
			$wpdb->delete(
    			$table_zielpreise,
    			array( 'id' => $alert->id ),
    			array( '%d' )
			);
		}
	}
}

/**
 * Holt Produkt­daten für die kompakte Amazon-Box + optionale
 * Preiswecker-Funktion und legt sie – falls aktiviert – in den
 * zentralen Boxyfy-Cache.
 *
 * @param string  $asin           Amazon-ASIN
 * @param bool    $force_refresh  TRUE ⇒ Cache ignorieren
 *                                (z. B. Cron-Job für Preiswecker)
 * @return array|null             Produktdaten oder NULL bei Fehler
 */
function boxyfy_get_amazon_product_data_small_box( $asin, $force_refresh = false ) {

	/* ------------------------------------------------------------------
	 * 1) Globale Cache-Einstellungen holen
	 * ---------------------------------------------------------------- */
	$cache_enabled = ( get_option( 'boxyfy_cache_enable', 'no' ) === 'yes' );
	$cache_ttl     = (int) get_option( 'boxyfy_cache_ttl', 360 ) * MINUTE_IN_SECONDS;
	$cache_key     = boxyfy_build_cache_key( 'small', $asin );   // → _transient_boxyfy_amz_small_<hash>

	/* ------------------------------------------------------------------
	 * 2) Wenn möglich direkt aus dem Cache liefern
	 * ---------------------------------------------------------------- */
	if ( $cache_enabled && ! $force_refresh ) {
		$cached = get_transient( $cache_key );
		if ( false !== $cached ) {
			return $cached;
		}
	}

	/* ------------------------------------------------------------------
	 * 3)  PA-API-Request durchführen (wie gehabt)
	 * ---------------------------------------------------------------- */
	if ( ! boxyfy_is_license_valid() ) {
		return null;
	}

	$defaults = array(
		'access_key'  => '',
		'secret_key'  => '',
		'partner_tag' => '',
		'host'        => 'webservices.amazon.de',
		'region'      => 'eu-west-1',
	);
	$opt         = wp_parse_args( get_option( 'boxyfy_amazon_settings', array() ), $defaults );
	$host        = sanitize_text_field( $opt['host'] );
	$region      = sanitize_text_field( $opt['region'] );
	$accessKey   = sanitize_text_field( $opt['access_key'] );
	$secretKey   = sanitize_text_field( $opt['secret_key'] );
	$partnerTag  = sanitize_text_field( $opt['partner_tag'] );

	$payload = wp_json_encode( array(
		'ItemIds'   => array( $asin ),
		'Resources' => array(
			'ItemInfo.Title',
			'Images.Primary.Large',
			'Offers.Listings.Price',
			'Offers.Listings.SavingBasis',
		),
		'PartnerTag'  => $partnerTag,
		'PartnerType' => 'Associates',
		'Marketplace' => 'www.amazon.de',
	) );

	$uri_path = '/paapi5/getitems';

	if ( ! class_exists( 'AwsV4' ) ) {
		require_once plugin_dir_path( BOXYFY_PLUGIN_FILE ) . 'assets/vendor/amazon/boxyfy-class-aws-v4.php';
	}

	$awsv4 = new AwsV4( $accessKey, $secretKey );
	$awsv4->setRegionName( $region );
	$awsv4->setServiceName( 'ProductAdvertisingAPI' );
	$awsv4->setPath( $uri_path );
	$awsv4->setPayload( $payload );
	$awsv4->setRequestMethod( 'POST' );
	$awsv4->addHeader( 'content-encoding', 'amz-1.0' );
	$awsv4->addHeader( 'content-type', 'application/json; charset=utf-8' );
	$awsv4->addHeader( 'host', $host );
	$awsv4->addHeader( 'x-amz-target', 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1.GetItems' );

	$args = array(
		'headers' => $awsv4->getHeaders(),
		'body'    => $payload,
		'method'  => 'POST',
		'timeout' => 15,
	);

	$response = wp_remote_post( 'https://' . $host . $uri_path, $args );
	if ( is_wp_error( $response ) ) {
		return null;
	}

	$body = wp_remote_retrieve_body( $response );
	if ( empty( $body ) ) {
		return null;
	}

	$data_json = json_decode( $body, true );
	if ( empty( $data_json['ItemsResult']['Items'][0] ) ) {
		return null;
	}

	$item        = $data_json['ItemsResult']['Items'][0];
	$title       = $item['ItemInfo']['Title']['DisplayValue']             ?? '';
	$thumbnail   = $item['Images']['Primary']['Large']['URL']             ?? '';
	$price_small = $item['Offers']['Listings'][0]['Price']['DisplayAmount']       ?? '';
	$savingBasis = $item['Offers']['Listings'][0]['SavingBasis']['DisplayAmount'] ?? '';

	/* ------------------------------------------------------------------
	 * 4) Ergebnis aufbereiten  + fetched_at hinzufügen
	 * ---------------------------------------------------------------- */
	$result = array(
		'asin'          => $asin,
		'title'         => $title,
		'primary_image' => $thumbnail,
		'price'         => $price_small,
		'savingBasis'   => $savingBasis,
		'fetched_at'    => current_time( 'timestamp' ),
	);

	/* ------------------------------------------------------------------
	 * 5)  Cachen, falls aktiviert
	 * ---------------------------------------------------------------- */
	if ( $cache_enabled ) {
		set_transient( $cache_key, $result, $cache_ttl );
	}

	return $result;
}

// ----------------------------------------------
// H) Shortcode definieren (Cookie-Version)
// ----------------------------------------------
add_shortcode( 'boxyfy_amazon_productbox_small', 'boxyfy_amazon_productbox_small_alert_shortcode' );
function boxyfy_amazon_productbox_small_alert_shortcode( $atts ) {

    // 1. Shortcode-Attribute auslesen
    $atts = shortcode_atts(
        array(
            'asin'              => '',
            'title'             => '',
            'button_title'      => __( 'Bei Amazon kaufen', 'boxyfy' ),
            'max_title_length'  => '200',
            'discount_boxstyle' => 'style1',
            'box_shadow'        => '',
        ),
        $atts
    );

    // 2. Falls keine ASIN angegeben -> Abbruch
    if ( empty( $atts['asin'] ) ) {
        return '<p>' . esc_html__( 'Bitte eine gültige ASIN angeben.', 'boxyfy' ) . '</p>';
    }

    // 3. Formularverarbeitung (POST)
    if (
        isset( $_SERVER['REQUEST_METHOD'] )
        && 'POST' === sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) )
        && isset( $_POST['boxyfy_amazon_preiswecker_nonce'] )
    ) {
        // Nonce check
        $nonce = sanitize_text_field( wp_unslash( $_POST['boxyfy_amazon_preiswecker_nonce'] ) );
        if ( ! wp_verify_nonce( $nonce, 'boxyfy_amazon_preiswecker_form' ) ) {
            return '<p>' . esc_html__( 'Ungültige Formularübermittlung.', 'boxyfy' ) . '</p>';
        }

        // Prüfen, ob das Formular zur richtigen ASIN gehört
        if ( isset( $_POST['asin_post'] ) && sanitize_text_field( wp_unslash( $_POST['asin_post'] ) ) === $atts['asin'] ) {

            // Felder auslesen
            $target_price = isset( $_POST['target_price'] ) ? floatval( wp_unslash( $_POST['target_price'] ) ) : 0;
            $email        = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';
            $errors       = array();

            // Validierung
            if ( $target_price <= 0 ) {
                $errors[] = __( 'Bitte einen gültigen Wunschpreis angeben.', 'boxyfy' );
            }
            if ( empty( $email ) || ! is_email( $email ) ) {
                $errors[] = __( 'Bitte eine gültige E-Mail-Adresse angeben.', 'boxyfy' );
            }

            // Wenn keine Fehler
            if ( empty( $errors ) ) {
                global $wpdb;
                $table_zielpreise = $wpdb->prefix . 'boxyfy_amazon_preiswecker_zielpreise';

                // Gibt es bereits einen Eintrag mit derselben ASIN + E-Mail?
                $existing_entry = $wpdb->get_row( $wpdb->prepare(
                    "SELECT id FROM {$table_zielpreise} WHERE asin = %s AND email = %s LIMIT 1",
                    $atts['asin'],
                    $email
                ) );

                // Cookie-Name ASIN-spezifisch erstellen
                $cookie_name = 'apw_success_message_' . sanitize_key( $atts['asin'] );

                if ( $existing_entry ) {
                    // => Update
                    $updated = $wpdb->update(
                        $table_zielpreise,
                        array(
                            'target_price' => $target_price,
                            'notified'     => 0,
                            'created_at'   => current_time( 'mysql' ),
                        ),
                        array( 'id' => $existing_entry->id ),
                        array( '%f', '%d', '%s' ),
                        array( '%d' )
                    );
                    if ( false !== $updated ) {
                        // Cookie setzen
                        $msg = __( 'Ihr Preisalarm wurde erfolgreich aktualisiert.', 'boxyfy' );
                        setcookie( $cookie_name, sanitize_text_field( $msg ), time() + 120, COOKIEPATH, COOKIE_DOMAIN );
                        wp_redirect( get_permalink() );
                        exit;
                    } else {
                        $errors[] = __( 'Beim Aktualisieren Ihres Preisalarms ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.', 'boxyfy' );
                    }
                } else {
                    // => Insert
                    $inserted = $wpdb->insert(
                        $table_zielpreise,
                        array(
                            'asin'         => $atts['asin'],
                            'target_price' => $target_price,
                            'email'        => $email,
                            'notified'     => 0,
                            'created_at'   => current_time( 'mysql' ),
                        ),
                        array( '%s', '%f', '%s', '%d', '%s' )
                    );
                    if ( $inserted ) {
                        // Cookie setzen
                        $msg = __( 'Ihr Preisalarm wurde erfolgreich gespeichert.', 'boxyfy' );
                        setcookie( $cookie_name, sanitize_text_field( $msg ), time() + 120, COOKIEPATH, COOKIE_DOMAIN );
                        wp_redirect( get_permalink() );
                        exit;
                    } else {
                        $errors[] = __( 'Beim Speichern Ihres Preisalarms ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.', 'boxyfy' );
                    }
                }
            }

            // Falls Fehler existieren
            if ( ! empty( $errors ) ) {
                $error_html = '<div class="amz-preiswecker-message amz-preiswecker-message-error">';
                foreach ( $errors as $error ) {
                    $error_html .= '<p>' . esc_html( $error ) . '</p>';
                }
                $error_html .= '</div>';
                echo wp_kses_post( $error_html );
            }
        }
    }

    // 4. Erfolgs-Cookie wieder auslesen und anzeigen
    $cookie_name = 'apw_success_message_' . sanitize_key( $atts['asin'] );
    $boxyfy_success_message_smallbox = '';
    if ( ! empty( $_COOKIE[ $cookie_name ] ) ) {
        $boxyfy_success_message_smallbox = sanitize_text_field( wp_unslash( $_COOKIE[ $cookie_name ] ) );
        // Cookie löschen, damit es nach Reload verschwindet
        setcookie( $cookie_name, '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN );
    }

    // 5. Produktdaten abrufen
    $title_length = intval( $atts['max_title_length'] );
    if ( $title_length > 200 ) {
        $title_length = 200;
    }
    $product_data = boxyfy_get_amazon_product_data_small_box( $atts['asin'] );
    if ( ! $product_data ) {
        return '<p>' . esc_html__( 'Keine Produkte beim Abruf gefunden (ASIN: ', 'boxyfy' )
            . esc_html( $atts['asin'] ) . ').</p>';
    }

    // 6. Daten vorbereiten
    $product_title = ! empty( $atts['title'] ) ? $atts['title'] : $product_data['title'];
    $price_str     = isset( $product_data['price'] ) ? $product_data['price'] : esc_html__( 'N/A', 'boxyfy' );
    $saving_str    = isset( $product_data['savingBasis'] ) ? $product_data['savingBasis'] : '';

    $price_float  = floatval( str_replace( array( '€', ',' ), array( '', '.' ), $price_str ) );
    $saving_float = floatval( str_replace( array( '€', ',' ), array( '', '.' ), $saving_str ) );

    $discount_percentage = 0;
    if ( $saving_float > 0 && $saving_float > $price_float ) {
        $discount_percentage = round( ( ( $saving_float - $price_float ) / $saving_float ) * 100 );
    }

    $options     = get_option( 'boxyfy_amazon_settings', array() );
    $partner_tag = isset( $options['partner_tag'] ) ? sanitize_text_field( $options['partner_tag'] ) : '';
    $purchase_url = "https://www.amazon.de/dp/" . esc_attr( $atts['asin'] ) . "?tag=" . esc_attr( $partner_tag ) . "&linkCode=ogi&th=1";

    $discount_class   = 'discount-percentage-box ' . sanitize_html_class( $atts['discount_boxstyle'] );
    $box_shadow_class = ( isset( $atts['box_shadow'] ) && 'yes' === $atts['box_shadow'] ) ? 'box-shadow' : '';

    // 7. Ausgabe starten
    ob_start();

    // 8. Erfolgsmeldung anzeigen (falls vorhanden)
    if ( $boxyfy_success_message_smallbox ) {
        echo '<div class="amz-preiswecker-message amz-preiswecker-message-success">'
             . esc_html( $boxyfy_success_message_smallbox ) . '</div>';
    }
    ?>
	
	<div class="boxyfy-productbox-alert">
	<div class="amazon-product-box-small<?php echo $box_shadow_class ? ' ' . esc_attr( $box_shadow_class ) : ''; ?>">
		<?php if ( $discount_percentage > 0 ) : ?>
			<div class="<?php echo esc_attr( $discount_class ); ?>">
				- <?php echo esc_html( $discount_percentage ); ?> %
			</div>
		<?php endif; ?>

		<div class="amazon-product-small-content">
			<div class="amazon-product-box-small-img-container">
				<a href="<?php echo esc_url( $purchase_url ); ?>" target="_blank" rel="nofollow sponsored">
					<img src="<?php echo esc_url( $product_data['primary_image'] ); ?>" alt="<?php echo esc_attr__( 'Primary Image', 'boxyfy' ); ?>">
				</a>
			</div>

			<div class="amazon-product-small-text">
				<div class="boxyfy-smallbox-title">
					<a href="<?php echo esc_url( $purchase_url ); ?>" target="_blank" rel="nofollow sponsored">
						<?php echo esc_html( mb_strimwidth( $product_title, 0, $title_length, '...' ) ); ?>
					</a>
				</div>

				<span class="product-price-smallbox">
					<?php echo esc_html( $price_str ); ?>
				</span>

				<?php if ( ! empty( $saving_str ) ) : ?>
					<span class="product-saveprice-small-box">
						<?php echo esc_html__( 'UVP:', 'boxyfy' ); ?> <?php echo esc_html( $saving_str ); ?> | 
						<span class="amazon-product-box-small-save-amount">
							<?php
							printf(
								/* translators: %s is the amount saved, e.g. "12,34" */
								esc_html__( 'Spare: %s €', 'boxyfy' ),
								number_format( ( $saving_float - $price_float ), 2, ',', '.' )
							);
							?>
						</span>
					</span>
				<?php endif; ?>

				<!-- PREISALARM-FORMULAR (Accordion) -->
				<div class="amz-preiswecker-accordion">
					<button class="amz-preiswecker-toggle-btn" type="button">
						<svg viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg">
							<title>ic_fluent_alert_on_24_filled</title>
    						<g fill="currentColor" fill-rule="nonzero">
								<path d="M9.04172524,19.0029603 L14.9582748,19.0029603 C14.7196327,20.4210965 13.4859868,21.5014962 12,21.5014962 C10.5140132,21.5014962 9.28036729,20.4210965 9.04172524,19.0029603 Z M12,2.00389443 C16.1421356,2.00389443 19.5,5.36175881 19.5,9.50389443 L19.5,13.5024024 L20.9183309,16.6624964 C20.973238,16.7848314 21.001625,16.9174043 21.001625,17.0514962 C21.001625,17.5761667 20.5762955,18.0014962 20.051625,18.0014962 L3.95218538,18.0014962 C3.81840073,18.0014962 3.68612461,17.9732391 3.56401742,17.918575 C3.08514303,17.7041957 2.87072735,17.1422026 3.08510659,16.6633282 L4.50000427,13.5027692 L4.50011124,9.49097734 L4.50452793,9.2410613 C4.64359849,5.21033445 7.95587136,2.00389443 12,2.00389443 Z M23,8.25 C23.4142136,8.25 23.75,8.58578644 23.75,9 C23.75,9.37969577 23.4678461,9.69349096 23.1017706,9.74315338 L23,9.75 L21,9.75 C20.5857864,9.75 20.25,9.41421356 20.25,9 C20.25,8.62030423 20.5321539,8.30650904 20.8982294,8.25684662 L21,8.25 L23,8.25 Z M3,8.25 C3.41421356,8.25 3.75,8.58578644 3.75,9 C3.75,9.37969577 3.46784612,9.69349096 3.10177056,9.74315338 L3,9.75 L1,9.75 C0.585786438,9.75 0.25,9.41421356 0.25,9 C0.25,8.62030423 0.532153882,8.30650904 0.898229443,8.25684662 L1,8.25 L3,8.25 Z M22.6,2.55 C22.8259347,2.85124623 22.7909723,3.26714548 22.5337844,3.52699676 L22.45,3.6 L20.45,5.1 C20.1186292,5.34852814 19.6485281,5.28137085 19.4,4.95 C19.1740653,4.64875377 19.2090277,4.23285452 19.4662156,3.97300324 L19.55,3.9 L21,2.4 C21.8813708,2.15147186 22.3514719,2.21862915 22.6,2.55 Z M2.45,2.4 L4.45,3.9 C4.78137085,4.14852814 4.84852814,4.61862915 4.6,4.95 C4.35147186,5.28137085 3.88137085,5.34852814 3.55,5.1 L1.55,3.6 C1.21862915,3.35147186 1.15147186,2.88137085 1.4,2.55 C1.64852814,2.21862915 2.11862915,2.15147186 2.45,2.4 Z" />
							</g>
						</svg>
						<?php echo esc_html__( 'Preisalarm aktivieren', 'boxyfy' ); ?>
					</button>

					<div class="amz-preiswecker-form-container">
						<form method="post" class="amz-preiswecker-form">
							<?php wp_nonce_field( 'boxyfy_amazon_preiswecker_form', 'boxyfy_amazon_preiswecker_nonce' ); ?>
							<input type="hidden" name="asin_post" value="<?php echo esc_attr( $atts['asin'] ); ?>">

							<label for="target_price_<?php echo esc_attr( $atts['asin'] ); ?>" class="amz-preiswecker-label">
								<?php echo esc_html__( 'Wunschpreis', 'boxyfy' ); ?>
							</label>
							<div class="amz-preiswecker-input-wrapper">
								<span class="amz-preiswecker-currency-prefix">€</span>
								<input 
									type="number" 
									name="target_price" 
									id="target_price_<?php echo esc_attr( $atts['asin'] ); ?>" 
									step="0.01" 
									min="0" 
									required
									placeholder="<?php echo esc_attr__( 'Wunschpreis eingeben', 'boxyfy' ); ?>" 
									class="amz-preiswecker-price-input"
								/>
							</div>

							<label for="email_<?php echo esc_attr( $atts['asin'] ); ?>" class="amz-preiswecker-label">
								<?php echo esc_html__( 'E-Mail', 'boxyfy' ); ?>
							</label>
							<div class="amz-preiswecker-input-wrapper">
								<input 
									type="email" 
									name="email" 
									id="email_<?php echo esc_attr( $atts['asin'] ); ?>"
									required
									placeholder="<?php echo esc_attr__( 'E-Mail eingeben für Preisalarm', 'boxyfy' ); ?>"
									class="amz-preiswecker-email-input"
								/>
							</div>
							<span class="boxyfy-preiswecker-hinweis-amz-smallbox">
    							<?php echo esc_html__( 'Mit dem Absenden willigst du ein, dass Deine E-Mail und Dein Wunschpreis auf dieser Website gespeichert werden, um Dich einmalig zu benachrichtigen, sobald der Preis erreicht ist. Weitere Hinweise findest Du in unseren Datenschutzbestimmungen.', 'boxyfy' ); ?>
							</span>
							<button type="submit" class="amz-preiswecker-submit-btn">
								<?php echo esc_html__( 'Preisalarm speichern', 'boxyfy' ); ?>
							</button>
						</form>
					</div>
				</div>

				<?php
				$timestamp = isset( $product_data['fetched_at'] )
    				? $product_data['fetched_at']
  	  				: current_time( 'timestamp' );
				?>
				<div class="disclaimer-amz-box-simple">
    				<?php
        				echo esc_html__( 'Preis inkl. MwSt', 'boxyfy' ) . ' | ';
        				echo esc_html__( 'Zuletzt aktualisiert: ', 'boxyfy' ) .
             				esc_html( date_i18n( 'd.m.Y H:i', $timestamp ) ) . ' | ';
        				echo esc_html__( 'Preis kann sich geändert haben | Affiliate-Links enthalten', 'boxyfy' );
    				?>
				</div>
			</div>
		</div>
	</div>
</div>
<?php
	return ob_get_clean();
}