<?php
/**
 * GTM import package builder.
 *
 * @package Carticy\Conversions\Client
 */

declare(strict_types=1);

namespace Carticy\Conversions\Client;

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

/**
 * Builds a V1 importable GTM package from the validated Carticy event contract.
 */
final class GtmImportBuilder {

	/**
	 * The custom ecommerce-events trigger id referenced by event tags.
	 */
	private const ECOMMERCE_TRIGGER_ID = '100';

	/**
	 * GTM's built-in "All Pages" trigger id used by container exports.
	 */
	private const ALL_PAGES_TRIGGER_ID = '2147479553';

	/**
	 * Build an importable GTM container fragment.
	 *
	 * Every tag MUST reference a firing trigger: an imported tag without
	 * firingTriggerId never fires, which makes the whole package a no-op.
	 *
	 * @param ClientTrackingSettings $settings Settings.
	 * @return array<string, mixed>
	 */
	public function build( ClientTrackingSettings $settings ): array {
		$config = $settings->to_array();
		$ga4    = $config['providers']['ga4'] ?? array();
		$meta   = $config['providers']['meta'] ?? array();

		return array(
			'exportFormatVersion' => 2,
			'containerVersion'    => array(
				'name'     => 'Carticy Conversions for WooCommerce - GTM V1',
				'tag'      => $this->tags( $ga4, $meta ),
				'trigger'  => array(
					array(
						'name'              => 'Carticy - Ecommerce Events',
						'triggerId'         => self::ECOMMERCE_TRIGGER_ID,
						'type'              => 'CUSTOM_EVENT',
						'customEventFilter' => array(
							array(
								'type'      => 'MATCH_REGEX',
								'parameter' => array(
									array(
										'type'  => 'TEMPLATE',
										'key'   => 'arg0',
										'value' => '{{_event}}',
									),
									array(
										'type'  => 'TEMPLATE',
										'key'   => 'arg1',
										'value' => '^(purchase|add_to_cart|begin_checkout)$',
									),
								),
							),
						),
					),
				),
				'variable' => $this->variables(),
			),
		);
	}

	/**
	 * Build GTM tags.
	 *
	 * @param array<string, mixed> $ga4 GA4 config.
	 * @param array<string, mixed> $meta Meta config.
	 * @return array<int, array<string, mixed>>
	 */
	private function tags( array $ga4, array $meta ): array {
		$tags   = array();
		$tag_id = 1;
		if ( ! empty( $ga4['measurementId'] ) ) {
			$tags[] = array(
				'name'            => 'Carticy - GA4 Google Tag',
				'tagId'           => (string) $tag_id++,
				'type'            => 'googtag',
				'firingTriggerId' => array( self::ALL_PAGES_TRIGGER_ID ),
				'tagFiringOption' => 'ONCE_PER_EVENT',
				'parameter'       => array(
					array(
						'type'  => 'TEMPLATE',
						'key'   => 'tagId',
						'value' => (string) $ga4['measurementId'],
					),
				),
			);
			$tags[] = array(
				'name'            => 'Carticy - GA4 Ecommerce Events',
				'tagId'           => (string) $tag_id++,
				'type'            => 'gaawe',
				'firingTriggerId' => array( self::ECOMMERCE_TRIGGER_ID ),
				'tagFiringOption' => 'ONCE_PER_EVENT',
				'parameter'       => array(
					array(
						'type'  => 'TEMPLATE',
						'key'   => 'eventName',
						'value' => '{{Event}}',
					),
					array(
						'type'  => 'TEMPLATE',
						'key'   => 'measurementIdOverride',
						'value' => (string) $ga4['measurementId'],
					),
					array(
						'type'  => 'BOOLEAN',
						'key'   => 'sendEcommerceData',
						'value' => 'false',
					),
					array(
						'type'  => 'TEMPLATE',
						'key'   => 'eventSettingsVariable',
						'value' => '{{Carticy - Event Settings}}',
					),
				),
			);
		}
		if ( ! empty( $meta['pixelId'] ) ) {
			$tags[] = array(
				'name'            => 'Carticy - Meta Pixel Base',
				'tagId'           => (string) $tag_id++,
				'type'            => 'html',
				'firingTriggerId' => array( self::ALL_PAGES_TRIGGER_ID ),
				'tagFiringOption' => 'ONCE_PER_EVENT',
				'parameter'       => array(
					array(
						'type'  => 'TEMPLATE',
						'key'   => 'html',
						'value' => $this->meta_base_html( (string) $meta['pixelId'] ),
					),
					array(
						'type'  => 'BOOLEAN',
						'key'   => 'supportDocumentWrite',
						'value' => 'false',
					),
				),
			);
			$tags[] = array(
				'name'            => 'Carticy - Meta Ecommerce Events',
				'tagId'           => (string) $tag_id++,
				'type'            => 'html',
				'firingTriggerId' => array( self::ECOMMERCE_TRIGGER_ID ),
				'tagFiringOption' => 'ONCE_PER_EVENT',
				'parameter'       => array(
					array(
						'type'  => 'TEMPLATE',
						'key'   => 'html',
						'value' => $this->meta_event_html(),
					),
					array(
						'type'  => 'BOOLEAN',
						'key'   => 'supportDocumentWrite',
						'value' => 'false',
					),
				),
			);
		}

		return $tags;
	}

	/**
	 * Build DLV variables for the canonical contract.
	 *
	 * @return array<int, array<string, mixed>>
	 */
	private function variables(): array {
		$names     = array( 'event_id', 'transaction_id', 'value', 'currency', 'items', 'content_ids', 'content_type', 'affiliation' );
		$variables = array();
		foreach ( $names as $name ) {
			$variables[] = array(
				'name'      => 'DLV - ' . ucwords( str_replace( '_', ' ', $name ) ),
				'type'      => 'v',
				'parameter' => array(
					array(
						'type'  => 'INTEGER',
						'key'   => 'dataLayerVersion',
						'value' => '2',
					),
					array(
						'type'  => 'BOOLEAN',
						'key'   => 'setDefaultValue',
						'value' => 'false',
					),
					array(
						'type'  => 'TEMPLATE',
						'key'   => 'name',
						'value' => $name,
					),
				),
			);
		}
		$variables[] = array(
			'name'      => 'Carticy - Event Settings',
			'type'      => 'gtes',
			'parameter' => array(
				array(
					'type' => 'LIST',
					'key'  => 'eventSettingsTable',
					'list' => array(
						array(
							'type' => 'MAP',
							'map'  => array(
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameter',
									'value' => 'event_id',
								),
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameterValue',
									'value' => '{{DLV - Event Id}}',
								),
							),
						),
						array(
							'type' => 'MAP',
							'map'  => array(
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameter',
									'value' => 'transaction_id',
								),
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameterValue',
									'value' => '{{DLV - Transaction Id}}',
								),
							),
						),
						array(
							'type' => 'MAP',
							'map'  => array(
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameter',
									'value' => 'value',
								),
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameterValue',
									'value' => '{{DLV - Value}}',
								),
							),
						),
						array(
							'type' => 'MAP',
							'map'  => array(
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameter',
									'value' => 'currency',
								),
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameterValue',
									'value' => '{{DLV - Currency}}',
								),
							),
						),
						array(
							'type' => 'MAP',
							'map'  => array(
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameter',
									'value' => 'items',
								),
								array(
									'type'  => 'TEMPLATE',
									'key'   => 'parameterValue',
									'value' => '{{DLV - Items}}',
								),
							),
						),
					),
				),
			),
		);

		return $variables;
	}

	/**
	 * Meta base tag HTML.
	 *
	 * @param string $pixel_id Pixel ID.
	 * @return string
	 */
	private function meta_base_html( string $pixel_id ): string {
		return "<script>!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;t.defer=!0;t.setAttribute('data-cfasync','false');t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');fbq('init','" . esc_js( $pixel_id ) . "');</script>";
	}

	/**
	 * Meta event tag HTML.
	 *
	 * @return string
	 */
	private function meta_event_html(): string {
		return "<script>var eventName='{{Event}}';var map={purchase:'Purchase',add_to_cart:'AddToCart',begin_checkout:'InitiateCheckout'};var eventData={};var value={{DLV - Value}};if(typeof value!=='undefined'&&value!==null&&value!==''){eventData.value=Number(value);}var currency='{{DLV - Currency}}';if(currency&&currency!=='undefined'){eventData.currency=currency;}var contentType='{{DLV - Content Type}}';if(contentType&&contentType!=='undefined'){eventData.content_type=contentType;}var contentIds={{DLV - Content Ids}};if(Array.isArray(contentIds)&&contentIds.length){eventData.content_ids=contentIds;}var eventId='{{DLV - Event Id}}';if(typeof fbq!=='undefined'&&map[eventName]){fbq('track',map[eventName],eventData,eventId&&eventId!=='undefined'?{eventID:eventId}:undefined);}</script>";
	}
}
