<?php

declare(strict_types=1);

namespace FormConnector\Integration\Forms;

/**
 * Mappings Manager
 * 
 * Manages form field mappings to CareHQ fields.
 * Stores mapping configurations and conditional routing rules.
 */
class Mappings {

	/**
	 * Option key for storing all mappings
	 */
	private const OPTION_MAPPINGS = 'fc_form_mappings';

	/**
	 * Option key for conditional mappings
	 */
	private const OPTION_CONDITIONAL = 'fc_conditional_mappings';

	/**
	 * Get all mappings
	 */
	public function get_all_mappings(): array {
		$mappings = get_option(self::OPTION_MAPPINGS, []);
		return is_array($mappings) ? $mappings : [];
	}

	/**
	 * Get mapping for a specific form
	 *
	 * @param string $plugin Plugin key (e.g., 'gravityforms', 'cf7')
	 * @param int|string $form_id Form ID
	 */
	public function get_mapping(string $plugin, $form_id): array {
		$all = $this->get_all_mappings();
		$key = $this->get_form_key($plugin, $form_id);

		$mapping = $all[$key] ?? [
			'enabled' => false,
			'location_id' => '',
			'fields' => [],
		];
		
		// Ensure fields is always an associative array (object in JSON)
		// This prevents PHP from encoding empty array as [] instead of {}
		if (empty($mapping['fields']) || !is_array($mapping['fields'])) {
			$mapping['fields'] = new \stdClass();
		}
		
		return $mapping;
	}

	/**
	 * Save mapping for a specific form
	 *
	 * @param string $plugin Plugin key
	 * @param int|string $form_id Form ID
	 * @param array $mapping Mapping data
	 */
	public function save_mapping(string $plugin, $form_id, array $mapping): bool {
		$all = $this->get_all_mappings();
		$key = $this->get_form_key($plugin, $form_id);

		$all[$key] = [
			'enabled' => (bool) ($mapping['enabled'] ?? false),
			'location_id' => sanitize_text_field($mapping['location_id'] ?? ''),
			'fields' => $this->sanitize_fields_mapping($mapping['fields'] ?? []),
			'updated_at' => current_time('mysql', true),
		];

		return update_option(self::OPTION_MAPPINGS, $all);
	}

	/**
	 * Delete mapping for a specific form
	 */
	public function delete_mapping(string $plugin, $form_id): bool {
		$all = $this->get_all_mappings();
		$key = $this->get_form_key($plugin, $form_id);

		if (isset($all[$key])) {
			unset($all[$key]);
			return update_option(self::OPTION_MAPPINGS, $all);
		}

		return true;
	}

	/**
	 * Get all conditional mappings
	 */
	public function get_all_conditional(): array {
		$mappings = get_option(self::OPTION_CONDITIONAL, []);
		return is_array($mappings) ? $mappings : [];
	}

	/**
	 * Get conditional mapping for a specific form
	 */
	public function get_conditional(string $plugin, $form_id): array {
		$all = $this->get_all_conditional();
		$key = $this->get_form_key($plugin, $form_id);

		return $all[$key] ?? [
			'enabled' => false,
			'field' => '',
			'rules' => [],
		];
	}

	/**
	 * Save conditional mapping for a specific form
	 */
	public function save_conditional(string $plugin, $form_id, array $conditional): bool {
		$all = $this->get_all_conditional();
		$key = $this->get_form_key($plugin, $form_id);

		$all[$key] = [
			'enabled' => (bool) ($conditional['enabled'] ?? false),
			'field' => sanitize_text_field($conditional['field'] ?? ''),
			'rules' => $this->sanitize_conditional_rules($conditional['rules'] ?? []),
			'updated_at' => current_time('mysql', true),
		];

		return update_option(self::OPTION_CONDITIONAL, $all);
	}

	/**
	 * Get enabled forms (forms with active mappings)
	 */
	public function get_enabled_forms(): array {
		$all = $this->get_all_mappings();
		$enabled = [];

		foreach ($all as $key => $mapping) {
			if (!empty($mapping['enabled'])) {
				[$plugin, $form_id] = $this->parse_form_key($key);
				$enabled[] = [
					'plugin' => $plugin,
					'form_id' => $form_id,
					'location_id' => $mapping['location_id'] ?? '',
				];
			}
		}

		return $enabled;
	}

	/**
	 * Evaluate conditional mapping for a form submission
	 *
	 * @param string $plugin Plugin key
	 * @param int|string $form_id Form ID
	 * @param array $field_values Submitted field values
	 * @return string|null Location ID if match found, null otherwise
	 */
	public function evaluate_conditional(string $plugin, $form_id, array $field_values): ?string {
		$conditional = $this->get_conditional($plugin, $form_id);

		if (empty($conditional['enabled']) || empty($conditional['field']) || empty($conditional['rules'])) {
			return null;
		}

		$field_id = $conditional['field'];
		if (!isset($field_values[$field_id])) {
			return null;
		}

		$value = $field_values[$field_id];
		if (is_array($value)) {
			$value = array_map('trim', $value);
		} else {
			$value = trim((string) $value);
		}

		foreach ($conditional['rules'] as $rule) {
			if (empty($rule['value']) || empty($rule['location_id'])) {
				continue;
			}

			$rule_value = trim($rule['value']);
			
			if (is_array($value)) {
				if (in_array($rule_value, $value, true)) {
					return $rule['location_id'];
				}
			} elseif ($value === $rule_value) {
				return $rule['location_id'];
			}
		}

		return null;
	}

	/**
	 * Get the location ID for a form submission
	 */
	public function get_location_for_submission(string $plugin, $form_id, array $field_values): ?string {
		// First, try conditional mapping
		$conditional_location = $this->evaluate_conditional($plugin, $form_id, $field_values);
		if ($conditional_location) {
			return $conditional_location;
		}

		// Fall back to default location
		$mapping = $this->get_mapping($plugin, $form_id);
		return !empty($mapping['location_id']) ? $mapping['location_id'] : null;
	}

	/**
	 * Build form key from plugin and form ID
	 */
	private function get_form_key(string $plugin, $form_id): string {
		return sanitize_key($plugin) . '_' . sanitize_key((string) $form_id);
	}

	/**
	 * Parse form key back to plugin and form ID
	 */
	private function parse_form_key(string $key): array {
		$parts = explode('_', $key, 2);
		return [
			$parts[0] ?? '',
			$parts[1] ?? '',
		];
	}

	/**
	 * Sanitize field mappings
	 */
	private function sanitize_fields_mapping(array $fields): array {
		$sanitized = [];
		foreach ($fields as $carehq_field => $form_field) {
			$sanitized[sanitize_key($carehq_field)] = sanitize_text_field($form_field);
		}
		return $sanitized;
	}

	/**
	 * Sanitize conditional rules
	 */
	private function sanitize_conditional_rules(array $rules): array {
		$sanitized = [];
		foreach ($rules as $rule) {
			if (!is_array($rule)) {
				continue;
			}
			$sanitized[] = [
				'value' => sanitize_text_field($rule['value'] ?? ''),
				'location_id' => sanitize_text_field($rule['location_id'] ?? ''),
			];
		}
		return $sanitized;
	}
}
