<?php

declare(strict_types=1);

namespace FormConnector\Features\UTM;

/**
 * UTM Data Reader
 *
 * Reads UTM tracking data from form fields, native cookies, or
 * third-party tracking plugin cookies. Derives a human-readable
 * referral label for CareHQ from UTM source/medium.
 */
class UTMDataReader {

	/**
	 * Standard UTM parameters
	 */
	private const UTM_PARAMS = ['source', 'medium', 'campaign', 'term', 'content', 'id'];

	/**
	 * Extract all UTM values from form fields and cookies.
	 *
	 * Priority: form fields → native utm_* cookies → third-party cookies.
	 *
	 * @param array $field_values Raw form field values
	 * @return array Keyed by param name (source, medium, campaign, etc.)
	 */
	public function extract_utm_values(array $field_values): array {
		$utm_values = [];

		foreach (self::UTM_PARAMS as $param) {
			$form_key = 'utm_' . $param;

			// 1. Check form fields first
			$possible_keys = [$form_key, "field_{$form_key}", strtoupper($form_key)];
			foreach ($possible_keys as $key) {
				if (!empty($field_values[$key])) {
					$utm_values[$param] = sanitize_text_field($field_values[$key]);
					break;
				}
			}

			// 2. Fall back to our own cookies (utm_source, utm_medium, etc.)
			if (empty($utm_values[$param]) && isset($_COOKIE[$form_key]) && $_COOKIE[$form_key] !== '') {
				$utm_values[$param] = sanitize_text_field($_COOKIE[$form_key]);
			}

			// 3. Fall back to any third-party tracking cookies that end with
			//    the UTM param suffix (e.g. *_utm_source, *_utm_medium).
			if (empty($utm_values[$param])) {
				$utm_values[$param] = $this->find_utm_cookie($param);
			}
		}

		return $utm_values;
	}

	/**
	 * Build the CareHQ-compatible tracking data array.
	 *
	 * Only adds fields that CareHQ accepts: tracking_campaign, tracking_id, referrer_other.
	 *
	 * @param array $data    Existing payload data
	 * @param array $field_values Raw form field values
	 * @return array Updated payload
	 */
	public function apply_to_payload(array $data, array $field_values): array {
		$utm_values = $this->extract_utm_values($field_values);

		if (!empty($utm_values['campaign'])) {
			$data['tracking_campaign'] = $utm_values['campaign'];
		}
		if (!empty($utm_values['id'])) {
			$data['tracking_id'] = $utm_values['id'];
		}

		// Derive a human-readable referral label from UTM source/medium
		$referral_label = $this->derive_referral_source(
			$utm_values['source'] ?? '',
			$utm_values['medium'] ?? ''
		);

		// Set referrer_other: prefer derived UTM label, fall back to HTTP referrer cookie
		$http_referrer = isset($_COOKIE['fc_referrer_other']) ? sanitize_text_field($_COOKIE['fc_referrer_other']) : '';

		if (!empty($referral_label)) {
			$data['referrer_other'] = $referral_label;
		} elseif (!empty($http_referrer)) {
			$data['referrer_other'] = $http_referrer;
		}

		return $data;
	}

	/**
	 * Get UTM values for logging (includes all params, not just CareHQ fields).
	 *
	 * @param array $mapped CareHQ mapped data (from a successful submission)
	 * @return array UTM log data keyed for the Logs system
	 */
	public function get_log_data(array $mapped = []): array {
		$get_utm = function (string $mapped_key, string $param) use ($mapped): string {
			if (!empty($mapped[$mapped_key])) {
				return $mapped[$mapped_key];
			}
			$cookie_key = 'utm_' . $param;
			if (isset($_COOKIE[$cookie_key]) && $_COOKIE[$cookie_key] !== '') {
				return sanitize_text_field($_COOKIE[$cookie_key]);
			}
			return $this->find_utm_cookie($param);
		};

		return [
			'utm_source'    => $get_utm('tracking_source', 'source'),
			'utm_medium'    => $get_utm('tracking_medium', 'medium'),
			'utm_campaign'  => $get_utm('tracking_campaign', 'campaign'),
			'utm_term'      => $get_utm('tracking_term', 'term'),
			'utm_content'   => $get_utm('tracking_content', 'content'),
			'utm_id'        => $get_utm('tracking_id', 'id'),
			'landing_page'  => $this->get_landing_page($mapped),
			'referrer_other' => $mapped['referrer_other'] ?? (isset($_COOKIE['fc_referrer_other']) ? sanitize_text_field($_COOKIE['fc_referrer_other']) : ''),
		];
	}

	/**
	 * Get diagnostic info about UTM data extraction.
	 *
	 * @param array $utm_values Extracted UTM values
	 * @return array Diagnostic context
	 */
	public function get_debug_info(array $utm_values): array {
		return [
			'utm_data_found'  => !empty($utm_values['source']) || !empty($utm_values['medium']) || !empty($utm_values['campaign']),
			'cookie_source'   => $this->identify_cookie_source(),
			'source'          => $utm_values['source'] ?? '',
			'medium'          => $utm_values['medium'] ?? '',
			'campaign'        => $utm_values['campaign'] ?? '',
			'content'         => $utm_values['content'] ?? '',
		];
	}

	/**
	 * Search all cookies for a UTM parameter value.
	 *
	 * Scans cookies for names ending in "_utm_{param}" to pick up values
	 * from any third-party tracking plugin without hardcoding prefixes.
	 *
	 * @param string $param The UTM param suffix (source, medium, campaign, etc.)
	 * @return string The cookie value, or empty string if not found
	 */
	public function find_utm_cookie(string $param): string {
		$suffixes = ['_utm_' . $param, 'utm_' . $param];

		foreach ($suffixes as $suffix) {
			foreach ($_COOKIE as $name => $value) {
				if (str_ends_with(strtolower($name), $suffix) && $value !== '') {
					return sanitize_text_field($value);
				}
			}
		}

		return '';
	}

	/**
	 * Identify which cookie source provided UTM data (for diagnostic logging).
	 */
	public function identify_cookie_source(): string {
		if (isset($_COOKIE['utm_source']) || isset($_COOKIE['utm_medium'])) {
			return 'form_connector';
		}

		foreach ($_COOKIE as $name => $value) {
			if ($name !== 'utm_source' && $name !== 'utm_medium'
				&& (str_contains($name, 'utm_source') || str_contains($name, 'utm_medium'))
				&& $value !== '') {
				return 'third_party (' . $name . ')';
			}
		}

		return 'none';
	}

	/**
	 * Derive a human-readable referral source from UTM source/medium.
	 *
	 * @param string $source utm_source value
	 * @param string $medium utm_medium value
	 * @return string Human-readable referral label
	 */
	public function derive_referral_source(string $source, string $medium): string {
		if (empty($source) && empty($medium)) {
			return '';
		}

		$source_lower = strtolower(trim($source));
		$medium_lower = strtolower(trim($medium));

		// Paid search
		if (in_array($source_lower, ['google', 'google_ads', 'adwords'], true)
			&& in_array($medium_lower, ['cpc', 'ppc', 'paid_search', 'paid-search', 'sem'], true)) {
			return 'Google PPC';
		}

		if (in_array($source_lower, ['bing', 'microsoft', 'msn'], true)
			&& in_array($medium_lower, ['cpc', 'ppc', 'paid_search', 'paid-search'], true)) {
			return 'Bing PPC';
		}

		// Paid social
		if (in_array($source_lower, ['facebook', 'fb', 'meta', 'instagram', 'ig'], true)
			&& in_array($medium_lower, ['paid_social', 'paid-social', 'paidsocial', 'cpc', 'paid', 'social_paid', 'display'], true)) {
			return 'Facebook Ads';
		}

		if (in_array($source_lower, ['linkedin'], true)
			&& in_array($medium_lower, ['paid_social', 'paid-social', 'cpc', 'paid', 'sponsored'], true)) {
			return 'LinkedIn Ads';
		}

		if (in_array($source_lower, ['tiktok'], true)
			&& in_array($medium_lower, ['paid_social', 'paid-social', 'cpc', 'paid'], true)) {
			return 'TikTok Ads';
		}

		// Organic social
		if (in_array($source_lower, ['facebook', 'fb', 'meta', 'instagram', 'ig', 'linkedin', 'twitter', 'x', 'tiktok'], true)
			&& in_array($medium_lower, ['social', 'organic', 'organic_social', 'organic-social', 'referral', 'post'], true)) {
			return ucfirst($source_lower) . ' (Organic)';
		}

		// Organic search
		if (in_array($source_lower, ['google', 'bing', 'yahoo', 'duckduckgo'], true)
			&& in_array($medium_lower, ['organic', 'organic_search', 'organic-search', 'seo'], true)) {
			return ucfirst($source_lower) . ' (Organic)';
		}

		// Email
		if (in_array($medium_lower, ['email', 'e-mail', 'newsletter', 'email_marketing'], true)) {
			return 'Email Marketing';
		}

		// Display advertising
		if (in_array($medium_lower, ['display', 'banner', 'cpm'], true)) {
			return ucfirst($source_lower) . ' Display';
		}

		// Referral
		if ($medium_lower === 'referral') {
			return !empty($source_lower) ? ucfirst($source_lower) . ' Referral' : 'Referral';
		}

		// Fallback: "Source / Medium" format
		if (!empty($source) && !empty($medium)) {
			return $source . ' / ' . $medium;
		}

		return !empty($source) ? $source : $medium;
	}

	/**
	 * Get landing page from cookies (ours first, then generic fallback).
	 *
	 * @param array $mapped CareHQ mapped data
	 * @return string Landing page URL/path
	 */
	private function get_landing_page(array $mapped): string {
		if (!empty($mapped['landing_page'])) {
			return $mapped['landing_page'];
		}
		if (isset($_COOKIE['fc_landing_page'])) {
			return sanitize_text_field($_COOKIE['fc_landing_page']);
		}
		foreach ($_COOKIE as $name => $value) {
			if (stripos($name, 'landing_page') !== false && !empty($value)) {
				return sanitize_url($value);
			}
		}
		return '';
	}
}
