<?php
/**
 * Field Filter for Produktarten
 *
 * Filters booking fields based on service type (Produktart).
 * Sprint 8.1 - Modular architecture.
 *
 * @package KursBooking
 * @since 1.4.0
 */

declare(strict_types=1);

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class Kurs_Booking_Field_Filter
 *
 * Filters form fields based on service type (Produktart).
 * Supports basis fields (always shown) and matrix fields (produktart-specific).
 */
class Kurs_Booking_Field_Filter {

	/**
	 * Filter fields for a specific produktart
	 *
	 * @param array  $fields     All fields from kurs_booking_custom_fields.
	 * @param string $produktart The produktart ID (e.g., 'kurs', 'webinar').
	 * @return array Filtered fields.
	 */
	public static function filter_for_produktart( array $fields, string $produktart ): array {
		return array_filter(
			$fields,
			fn( array $field ): bool => self::should_show_field( $field, $produktart )
		);
	}

	/**
	 * Determine if a field should be shown for a produktart
	 *
	 * @param array  $field      Field data.
	 * @param string $produktart Produktart ID.
	 * @return bool True if field should be shown.
	 */
	public static function should_show_field( array $field, string $produktart ): bool {
		// Inactive fields are never shown.
		if ( isset( $field['active'] ) && ! $field['active'] ) {
			return false;
		}

		// Basis fields are always shown.
		if ( self::is_basis_field( $field ) ) {
			return true;
		}

		// Check produktart assignment.
		return self::field_applies_to( $field, $produktart );
	}

	/**
	 * Check if field is a basis field (always shown)
	 *
	 * @param array $field Field data.
	 * @return bool True if basis field.
	 */
	public static function is_basis_field( array $field ): bool {
		return ! empty( $field['basis_field'] );
	}

	/**
	 * Check if field applies to a specific produktart
	 *
	 * @param array  $field      Field data.
	 * @param string $produktart Produktart ID.
	 * @return bool True if field applies.
	 */
	public static function field_applies_to( array $field, string $produktart ): bool {
		$field_produktarten = $field['produktarten'] ?? array();

		// Empty array = applies to all produktarten.
		if ( empty( $field_produktarten ) ) {
			return true;
		}

		return in_array( $produktart, $field_produktarten, true );
	}

	/**
	 * Get only basis fields from field list
	 *
	 * @param array $fields All fields.
	 * @return array Only basis fields.
	 */
	public static function get_basis_fields( array $fields ): array {
		return array_filter(
			$fields,
			fn( array $field ): bool => self::is_basis_field( $field )
		);
	}

	/**
	 * Get only matrix fields from field list (non-basis)
	 *
	 * @param array $fields All fields.
	 * @return array Only matrix fields.
	 */
	public static function get_matrix_fields( array $fields ): array {
		return array_filter(
			$fields,
			fn( array $field ): bool => ! self::is_basis_field( $field )
		);
	}

	/**
	 * Get fields for a specific kurs (combines global + kurs-specific)
	 *
	 * @param int $kurs_id Kurs post ID.
	 * @return array Filtered fields for this kurs.
	 */
	public static function get_fields_for_kurs( int $kurs_id ): array {
		// Get global fields.
		$global_fields = get_option( 'kurs_booking_custom_fields', array() );

		// Handle JSON string (legacy).
		if ( is_string( $global_fields ) ) {
			$global_fields = json_decode( $global_fields, true ) ?: array();
		}

		// Get produktart for this kurs.
		$produktart = get_post_meta( $kurs_id, '_kurs_produktart', true ) ?: 'kurs';

		// Filter global fields by produktart.
		$filtered_fields = self::filter_for_produktart( $global_fields, $produktart );

		// Get kurs-specific fields.
		$kurs_fields = get_post_meta( $kurs_id, '_kurs_custom_fields', true );
		if ( is_string( $kurs_fields ) ) {
			$kurs_fields = json_decode( $kurs_fields, true ) ?: array();
		}
		if ( ! is_array( $kurs_fields ) ) {
			$kurs_fields = array();
		}

		// Merge global and kurs-specific fields.
		return array_merge( $filtered_fields, $kurs_fields );
	}

	/**
	 * Set produktarten for a field
	 *
	 * @param string $field_name    Field name/key.
	 * @param array  $produktarten Array of produktart IDs.
	 * @return bool Success.
	 */
	public static function set_field_produktarten( string $field_name, array $produktarten ): bool {
		$fields = get_option( 'kurs_booking_custom_fields', array() );

		// Handle JSON string.
		if ( is_string( $fields ) ) {
			$fields = json_decode( $fields, true ) ?: array();
		}

		// Find and update field.
		foreach ( $fields as $key => $field ) {
			if ( ( $field['name'] ?? '' ) === $field_name ) {
				$fields[ $key ]['produktarten'] = $produktarten;
				return update_option( 'kurs_booking_custom_fields', $fields );
			}
		}

		return false;
	}

	/**
	 * Set basis_field flag for a field
	 *
	 * @param string $field_name Field name/key.
	 * @param bool   $is_basis   Whether field is a basis field.
	 * @return bool Success.
	 */
	public static function set_basis_field( string $field_name, bool $is_basis ): bool {
		$fields = get_option( 'kurs_booking_custom_fields', array() );

		// Handle JSON string.
		if ( is_string( $fields ) ) {
			$fields = json_decode( $fields, true ) ?: array();
		}

		// Find and update field.
		foreach ( $fields as $key => $field ) {
			if ( ( $field['name'] ?? '' ) === $field_name ) {
				$fields[ $key ]['basis_field'] = $is_basis;
				return update_option( 'kurs_booking_custom_fields', $fields );
			}
		}

		return false;
	}

	/**
	 * Get produktarten assigned to a field
	 *
	 * @param array $field Field data.
	 * @return array Produktart IDs (empty = all).
	 */
	public static function get_field_produktarten( array $field ): array {
		return $field['produktarten'] ?? array();
	}

	/**
	 * Get all produktarten that have at least one field assigned
	 *
	 * @param array $fields All fields.
	 * @return array Unique produktart IDs.
	 */
	public static function get_used_produktarten( array $fields ): array {
		$used = array();

		foreach ( $fields as $field ) {
			$produktarten = $field['produktarten'] ?? array();
			$used         = array_merge( $used, $produktarten );
		}

		return array_unique( $used );
	}
}
