<?php
/**
 * Storefront product information output.
 *
 * @package CertaCart_EU_Product_Readiness
 */

namespace CertaCart\EU_Product_Readiness;

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

final class Storefront_Renderer {
	private static ?Storefront_Renderer $instance = null;
	private int $render_sequence = 0;

	public static function instance(): Storefront_Renderer {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	public function register(): void {
		add_action( 'wp', array( $this, 'register_position_hook' ) );
		add_shortcode( 'certacart_product_information', array( $this, 'shortcode' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ) );
	}

	public function register_position_hook(): void {
		$position = (string) Settings::get( 'display_position', 'after_meta' );
		if ( 'manual' === $position ) {
			return;
		}
		if ( 'before_add_to_cart' === $position ) {
			add_action( 'woocommerce_before_add_to_cart_form', array( $this, 'render_current' ), 5 );
		} elseif ( 'after_meta' === $position ) {
			add_action( 'woocommerce_product_meta_end', array( $this, 'render_current' ), 20 );
		} else {
			add_action( 'woocommerce_after_single_product_summary', array( $this, 'render_current' ), 7 );
		}
	}

	public function enqueue(): void {
		if ( is_product() ) {
			$this->enqueue_style();
		}
	}

	public function render_current(): void {
		global $product;
		if ( $product instanceof \WC_Product ) {
			echo $this->render( $product ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Fully escaped by render().
		}
	}

	public function shortcode( array $atts = array() ): string {
		$atts = shortcode_atts( array( 'product_id' => 0 ), $atts, 'certacart_product_information' );
		$product_id = absint( $atts['product_id'] );
		if ( ! $product_id ) {
			$product_id = get_the_ID();
		}
		$product = wc_get_product( $product_id );
		if ( ! $product instanceof \WC_Product ) {
			return '';
		}
		$this->enqueue_style();
		return $this->render( $product );
	}

	public function render( \WC_Product $product ): string {
		if ( ! $this->should_display( $product ) ) {
			return '';
		}

		$rows     = array();
		$prefix   = Rules::META_PREFIX;
		$settings = Settings::all();
		$identifier = trim( (string) $product->get_meta( $prefix . 'product_identifier', true ) );
		if ( '' === $identifier ) {
			$identifier = (string) $product->get_sku();
		}
		$this->add_row( $rows, __( 'Product identifier', 'certacart-eu-product-readiness' ), $identifier );
		$this->add_row( $rows, __( 'Manufacturer', 'certacart-eu-product-readiness' ), $product->get_meta( $prefix . 'manufacturer_name', true ) );
		$this->add_row( $rows, __( 'Manufacturer address', 'certacart-eu-product-readiness' ), $product->get_meta( $prefix . 'manufacturer_address', true ), true );
		$this->add_contact_rows( $rows, __( 'Manufacturer email', 'certacart-eu-product-readiness' ), __( 'Manufacturer website', 'certacart-eu-product-readiness' ), $product->get_meta( $prefix . 'manufacturer_email', true ), $product->get_meta( $prefix . 'manufacturer_url', true ) );

		$manufacturer_in_eu = (string) $product->get_meta( $prefix . 'manufacturer_in_eu', true );
		if ( '' === $manufacturer_in_eu || 'inherit' === $manufacturer_in_eu ) {
			$manufacturer_in_eu = $settings['default_manufacturer_in_eu'];
		}
		if ( 'no' === $manufacturer_in_eu ) {
			$this->add_row( $rows, __( 'EU responsible person', 'certacart-eu-product-readiness' ), $product->get_meta( $prefix . 'responsible_person_name', true ) );
			$this->add_row( $rows, __( 'Responsible person address', 'certacart-eu-product-readiness' ), $product->get_meta( $prefix . 'responsible_person_address', true ), true );
			$this->add_contact_rows( $rows, __( 'Responsible person email', 'certacart-eu-product-readiness' ), __( 'Responsible person website', 'certacart-eu-product-readiness' ), $product->get_meta( $prefix . 'responsible_person_email', true ), $product->get_meta( $prefix . 'responsible_person_url', true ) );
		}

		$safety_state = (string) $product->get_meta( $prefix . 'safety_state', true );
		$safety_text  = trim( (string) $product->get_meta( $prefix . 'safety_warning', true ) );
		$safety_url   = esc_url( (string) $product->get_meta( $prefix . 'safety_information_url', true ) );
		$notice_html = $this->render_notice( $settings );

		if ( empty( $rows ) && ! ( 'provided' === $safety_state && '' !== $safety_text ) && '' === $notice_html ) {
			return '';
		}
		$heading_id = sprintf( 'ccpr-product-information-heading-%d-%d', $product->get_id(), ++$this->render_sequence );

		ob_start();
		?>
		<section class="ccpr-product-information" aria-labelledby="<?php echo esc_attr( $heading_id ); ?>">
			<h2 id="<?php echo esc_attr( $heading_id ); ?>"><?php echo esc_html( (string) $settings['section_heading'] ); ?></h2>
			<?php if ( $rows ) : ?>
				<dl class="ccpr-product-information__list">
					<?php foreach ( $rows as $row ) : ?>
						<dt><?php echo esc_html( $row['label'] ); ?></dt>
						<dd><?php echo $row['value']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped when constructed. ?></dd>
					<?php endforeach; ?>
				</dl>
			<?php endif; ?>
			<?php if ( 'provided' === $safety_state && '' !== $safety_text ) : ?>
				<div class="ccpr-product-information__warning" role="note">
					<h3><?php esc_html_e( 'Warnings and safety information', 'certacart-eu-product-readiness' ); ?></h3>
					<?php echo wp_kses_post( wpautop( esc_html( $safety_text ) ) ); ?>
					<?php if ( $safety_url ) : ?><p><a href="<?php echo esc_url( $safety_url ); ?>" rel="noopener noreferrer"><?php esc_html_e( 'View safety document', 'certacart-eu-product-readiness' ); ?></a></p><?php endif; ?>
				</div>
			<?php endif; ?>
			<?php echo $notice_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped in render_notice(). ?>
		</section>
		<?php
		return (string) ob_get_clean();
	}


	private function enqueue_style(): void {
		if ( ! wp_style_is( 'ccpr-frontend', 'registered' ) ) {
			wp_register_style( 'ccpr-frontend', CCPR_URL . 'assets/css/frontend.css', array(), CCPR_VERSION );
		}
		wp_enqueue_style( 'ccpr-frontend' );
	}

	private function should_display( \WC_Product $product ): bool {
		$target = (string) $product->get_meta( Rules::META_PREFIX . 'targets_eu', true );
		if ( '' === $target || 'inherit' === $target ) {
			$target = (string) Settings::get( 'default_targets_eu', 'review' );
		}
		if ( 'yes' !== $target ) {
			return false;
		}
		$display = (string) $product->get_meta( Rules::META_PREFIX . 'display_information', true );
		if ( '' === $display || 'inherit' === $display ) {
			$display = (string) Settings::get( 'display_product_information', 'yes' );
		}
		return 'yes' === $display;
	}

	private function add_row( array &$rows, string $label, $value, bool $multiline = false ): void {
		$value = trim( (string) $value );
		if ( '' === $value ) {
			return;
		}
		$rows[] = array(
			'label' => $label,
			'value' => $multiline ? nl2br( esc_html( $value ) ) : esc_html( $value ),
		);
	}

	private function add_contact_rows( array &$rows, string $email_label, string $url_label, $email, $url ): void {
		$email = sanitize_email( (string) $email );
		$url   = esc_url( (string) $url, array( 'http', 'https' ) );
		if ( is_email( $email ) ) {
			$rows[] = array( 'label' => $email_label, 'value' => '<a href="mailto:' . esc_attr( $email ) . '">' . esc_html( antispambot( $email ) ) . '</a>' );
		}
		if ( $url && wp_http_validate_url( $url ) ) {
			$rows[] = array( 'label' => $url_label, 'value' => '<a href="' . esc_url( $url ) . '" rel="noopener noreferrer">' . esc_html( $url ) . '</a>' );
		}
	}

	private function render_notice( array $settings ): string {
		if ( 'configured' !== ( $settings['notice_scope'] ?? 'review' ) || 'yes' !== ( $settings['notice_enabled'] ?? 'no' ) || empty( $settings['notice_attachment_id'] ) ) {
			return '';
		}
		$image = wp_get_attachment_image( absint( $settings['notice_attachment_id'] ), 'full', false, array( 'class' => 'ccpr-guarantee-notice__image', 'alt' => (string) $settings['notice_alt_text'], 'loading' => 'lazy' ) );
		if ( ! $image ) {
			return '';
		}
		$link = esc_url( (string) ( $settings['notice_link_url'] ?? '' ) );
		if ( $link ) {
			$image = '<a href="' . esc_url( $link ) . '" rel="noopener noreferrer">' . $image . '</a>';
		}
		return '<div class="ccpr-guarantee-notice">' . $image . '</div>';
	}
}
