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

/**
 * Programmatic Open Graph image for chat share previews.
 * Crawlers need a real image URL — this paints logo + “Finish your order”.
 */
class DC_V2_Og_Image {

	const WIDTH  = 1200;
	const HEIGHT = 630;

	public static function url_for_slug( $slug ) {
		$slug = sanitize_title( (string) $slug );
		if ( ! $slug ) {
			return '';
		}
		return home_url( '/c/' . $slug . '/og.png' );
	}

	public static function maybe_serve() {
		$slug = get_query_var( 'dc_v2_og_slug' );
		if ( ! $slug ) {
			return;
		}
		if ( ! function_exists( 'imagecreatetruecolor' ) ) {
			status_header( 503 );
			header( 'Content-Type: text/plain; charset=utf-8' );
			echo 'OG image requires GD.';
			exit;
		}

		$post = DC_V2_Document_CPT::find_by_slug( $slug );
		if ( ! $post ) {
			status_header( 404 );
			exit;
		}

		$meta = DC_V2_Document_CPT::get_meta( $post->ID );
		$headline = function_exists( 'dc_v2_share_preview_text' )
			? dc_v2_share_preview_text( $meta['copy'] ?? array() )
			: 'Finish your order';

		$appearance = DC_V2_Document_CPT::normalize_appearance(
			get_option( 'dc_v2_appearance', dc_v2_default_appearance() )
		);
		$brand = function_exists( 'dc_v2_resolve_header_brand' )
			? dc_v2_resolve_header_brand( $appearance['logo_url'] ?? '' )
			: array( 'src' => '', 'mode' => 'none' );

		$cache_key = 'dc_v2_og_' . md5( $slug . '|' . ( $brand['src'] ?? '' ) . '|' . $headline . '|' . DC_V2_VERSION );
		$cached    = get_transient( $cache_key );
		if ( is_string( $cached ) && '' !== $cached ) {
			header( 'Content-Type: image/png' );
			header( 'Cache-Control: public, max-age=86400' );
			// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			echo $cached;
			exit;
		}

		$png = self::render_png( $brand['src'] ?? '', $headline );
		if ( ! $png ) {
			status_header( 500 );
			exit;
		}
		set_transient( $cache_key, $png, DAY_IN_SECONDS );
		header( 'Content-Type: image/png' );
		header( 'Cache-Control: public, max-age=86400' );
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo $png;
		exit;
	}

	/**
	 * @param string $logo_url Absolute URL to logo/favicon (optional).
	 * @param string $headline Share preview line painted on the card.
	 * @return string|false PNG binary
	 */
	private static function render_png( $logo_url, $headline = '' ) {
		$w  = self::WIDTH;
		$h  = self::HEIGHT;
		$im = imagecreatetruecolor( $w, $h );
		if ( ! $im ) {
			return false;
		}
		imagealphablending( $im, true );
		imagesavealpha( $im, false );

		$bg     = imagecolorallocate( $im, 18, 18, 20 );
		$card   = imagecolorallocate( $im, 38, 38, 42 );
		$ink    = imagecolorallocate( $im, 250, 250, 250 );
		$muted  = imagecolorallocate( $im, 161, 161, 170 );
		$accent = imagecolorallocate( $im, 147, 51, 234 );
		imagefilledrectangle( $im, 0, 0, $w, $h, $bg );

		imagefilledellipse( $im, 980, 120, 420, 420, imagecolorallocatealpha( $im, 147, 51, 234, 100 ) );
		imagefilledellipse( $im, 160, 520, 360, 360, imagecolorallocatealpha( $im, 192, 38, 211, 110 ) );

		$pad_x = 120;
		$pad_y = 140;
		imagefilledrectangle( $im, $pad_x, $pad_y, $w - $pad_x, $h - $pad_y, $card );

		$logo      = self::load_logo( $logo_url );
		$cx        = (int) ( $w / 2 );
		$logo_size = 128;
		$logo_top  = $pad_y + 56;
		if ( $logo ) {
			$lw  = imagesx( $logo );
			$lh  = imagesy( $logo );
			$dst = imagecreatetruecolor( $logo_size, $logo_size );
			imagealphablending( $dst, false );
			imagesavealpha( $dst, true );
			$transparent = imagecolorallocatealpha( $dst, 0, 0, 0, 127 );
			imagefilledrectangle( $dst, 0, 0, $logo_size, $logo_size, $transparent );
			imagealphablending( $dst, true );
			imagecopyresampled( $dst, $logo, 0, 0, 0, 0, $logo_size, $logo_size, $lw, $lh );
			imagecopy( $im, $dst, $cx - (int) ( $logo_size / 2 ), $logo_top, 0, 0, $logo_size, $logo_size );
			imagedestroy( $dst );
			imagedestroy( $logo );
		} else {
			imagefilledellipse( $im, $cx, $logo_top + (int) ( $logo_size / 2 ), $logo_size, $logo_size, $accent );
		}

		$text_y  = $logo_top + $logo_size + 48;
		$display = self::prepare_headline( $headline );
		$scale   = self::fit_scale( $display, 5, 900 );
		$tw      = imagefontwidth( 5 ) * strlen( $display ) * $scale;
		self::draw_scaled_text( $im, $display, $cx, $text_y, $ink, 5, $scale );
		if ( $tw < 820 ) {
			self::draw_cart_glyph( $im, $cx + (int) ( $tw / 2 ) + 18, $text_y + 8, $ink );
		}
		self::draw_scaled_text( $im, 'Order From DM', $cx, $text_y + 72, $muted, 3, 3 );

		ob_start();
		imagepng( $im, null, 6 );
		$png = ob_get_clean();
		imagedestroy( $im );
		return is_string( $png ) ? $png : false;
	}

	/**
	 * GD bitmap fonts are Latin-1 — normalize and keep the line short.
	 */
	private static function prepare_headline( $headline ) {
		$text = trim( wp_strip_all_tags( (string) $headline ) );
		if ( '' === $text ) {
			$text = 'Finish your order';
		}
		if ( function_exists( 'iconv' ) ) {
			$converted = @iconv( 'UTF-8', 'ISO-8859-1//TRANSLIT', $text );
			if ( is_string( $converted ) && '' !== $converted ) {
				$text = $converted;
			}
		}
		$text = preg_replace( '/\s+/', ' ', $text );
		if ( strlen( $text ) > 42 ) {
			$text = rtrim( substr( $text, 0, 39 ) ) . '...';
		}
		return $text;
	}

	private static function fit_scale( $text, $font, $max_width ) {
		$scale = 4;
		$fw    = imagefontwidth( $font );
		$len   = max( 1, strlen( (string) $text ) );
		while ( $scale > 2 && ( $fw * $len * $scale ) > $max_width ) {
			$scale--;
		}
		return $scale;
	}

	/**
	 * Upscale a built-in GD bitmap font so hosts without TTF still look readable.
	 *
	 * @param resource|\GdImage $im
	 */
	private static function draw_scaled_text( $im, $text, $cx, $y, $color, $font, $scale = 4 ) {
		$text = (string) $text;
		$fw   = imagefontwidth( $font );
		$fh   = imagefontheight( $font );
		$tw   = $fw * strlen( $text );
		$th   = $fh;
		$tmp  = imagecreatetruecolor( max( 1, $tw ), max( 1, $th ) );
		$bg   = imagecolorallocate( $tmp, 0, 0, 0 );
		imagefill( $tmp, 0, 0, $bg );
		imagecolortransparent( $tmp, $bg );
		$white = imagecolorallocate( $tmp, 255, 255, 255 );
		imagestring( $tmp, $font, 0, 0, $text, $white );

		$dw = $tw * $scale;
		$dh = $th * $scale;
		$dx = (int) ( $cx - $dw / 2 );
		$dy = (int) $y;

		// Tint via colorize by drawing white then... simpler: copy resampled then recolor is hard.
		// Paint text color by replacing white pixels.
		$scaled = imagecreatetruecolor( $dw, $dh );
		$sbg    = imagecolorallocate( $scaled, 0, 0, 0 );
		imagefill( $scaled, 0, 0, $sbg );
		imagecolortransparent( $scaled, $sbg );
		imagecopyresampled( $scaled, $tmp, 0, 0, 0, 0, $dw, $dh, $tw, $th );
		imagedestroy( $tmp );

		for ( $x = 0; $x < $dw; $x++ ) {
			for ( $yy = 0; $yy < $dh; $yy++ ) {
				$rgb = imagecolorat( $scaled, $x, $yy );
				$r   = ( $rgb >> 16 ) & 0xFF;
				if ( $r > 40 ) {
					imagesetpixel( $im, $dx + $x, $dy + $yy, $color );
				}
			}
		}
		imagedestroy( $scaled );
	}

	/**
	 * Simple cart glyph (emoji-free, crawler-safe).
	 *
	 * @param resource|\GdImage $im
	 */
	private static function draw_cart_glyph( $im, $x, $y, $color ) {
		imagefilledrectangle( $im, $x, $y + 10, $x + 36, $y + 34, $color );
		imageline( $im, $x - 6, $y + 6, $x, $y + 10, $color );
		imagefilledellipse( $im, $x + 10, $y + 42, 8, 8, $color );
		imagefilledellipse( $im, $x + 28, $y + 42, 8, 8, $color );
	}

	/**
	 * @return resource|\GdImage|null
	 */
	private static function load_logo( $url ) {
		$url = is_string( $url ) ? trim( $url ) : '';
		if ( '' === $url ) {
			return null;
		}
		$response = wp_remote_get(
			$url,
			array(
				'timeout'     => 8,
				'redirection' => 3,
			)
		);
		if ( is_wp_error( $response ) ) {
			return null;
		}
		$code = (int) wp_remote_retrieve_response_code( $response );
		$body = wp_remote_retrieve_body( $response );
		if ( 200 !== $code || ! is_string( $body ) || '' === $body ) {
			return null;
		}
		$img = @imagecreatefromstring( $body );
		return $img ? $img : null;
	}
}
