<?php

namespace SugarCalendarBookings\Migration;

use SugarCalendarBookings\Support\DataProcessing\Sanitizer;

/**
 * Abstract base class for source data mappers.
 *
 * @since 1.3.0
 */
abstract class AbstractMapper {

	/**
	 * Amelia status to SCB status mapping.
	 *
	 * @since 1.3.0
	 *
	 * @var array<string, string>
	 */
	private const AMELIA_STATUS_MAP = [
		'visible'  => 'enabled',
		'hidden'   => 'disabled',
		'disabled' => 'disabled',
		'blocked'  => 'disabled',
	];

	/**
	 * Map raw source data to SCB format.
	 *
	 * @since 1.3.0
	 *
	 * @param object               $raw     Raw data from source.
	 * @param array<string, mixed> $context Mapping context (e.g., author_id).
	 *
	 * @return array<string, mixed>|null Mapped data or null if item should be skipped.
	 */
	abstract public function map( object $raw, array $context = [] ): ?array;

	/**
	 * Extract and sanitize fields from raw source object.
	 *
	 * Reduces boilerplate in mapper classes by handling the common pattern of:
	 * 1. Extracting camelCase properties from raw object
	 * 2. Building a normalized array with defaults
	 * 3. Applying sanitization rules
	 *
	 * @since 1.3.0
	 *
	 * @param object                                                             $raw    Raw source object.
	 * @param array<string, array{source: string, default: mixed, rule: string}> $fields Field configuration.
	 *                                                                                Each entry maps target_key => [
	 *                                                                                    'source'  => 'sourcePropertyName',
	 *                                                                                    'default' => default_value,
	 *                                                                                    'rule'    => 'sanitization_rule',
	 *                                                                                ].
	 *
	 * @return array<string, mixed> Sanitized data array.
	 */
	protected function extract_and_sanitize( object $raw, array $fields ): array {

		$raw_data = [];
		$rules    = [];

		// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
		foreach ( $fields as $target_key => $config ) {
			$source_prop             = $config['source'];
			$raw_data[ $target_key ] = $raw->{$source_prop} ?? $config['default'];
			$rules[ $target_key ]    = $config['rule'];
		}
		// phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase

		return Sanitizer::sanitize( $raw_data, $rules );
	}

	/**
	 * Map Amelia entity status to SCB status.
	 *
	 * For entity visibility statuses (visible, hidden, disabled, blocked).
	 *
	 * @since 1.3.0
	 *
	 * @param string $status         Amelia status value.
	 * @param string $default_status Default status if not found.
	 *
	 * @return string SCB status.
	 */
	protected function map_entity_status( string $status, string $default_status = 'enabled' ): string {

		return self::AMELIA_STATUS_MAP[ $status ] ?? $default_status;
	}
}
