<?php
/**
 * @package Hafenstudios\Kurato
 */

namespace Hafenstudios\Kurato\Booking;

defined( 'ABSPATH' ) || exit;

/**
 * Free-Limits des Buchungsmoduls (K5-KONZEPT Abschnitte 1, 7).
 *
 * Der Free-Umfang ist ein Ansprechpartner (Host) mit zwei Terminarten. Pro hebt
 * diese Grenzen nur an; darum liegen sie hinter dem Filter `kurato_booking_limits`
 * und nicht im Repository. Die reine Grenz-Rechnung (Normalisierung des
 * Filterwerts, "darf noch angelegt werden?") ist hier von WordPress entkoppelt und
 * damit ohne echtes WP pruefbar. Nur {@see resolve()} ruft den Filter.
 *
 * Konvention: ein Grenzwert von 0 oder kleiner bedeutet "unbegrenzt" (Pro kann so
 * die Deckelung ganz aufheben).
 */
final class BookingLimits {

	/**
	 * Free-Standardgrenzen.
	 *
	 * @var array{max_hosts:int,max_types_per_host:int}
	 */
	public const DEFAULTS = array(
		'max_hosts'          => 1,
		'max_types_per_host' => 2,
	);

	/**
	 * Aufgeloeste Grenzen: Free-Defaults, ueber den Filter `kurato_booking_limits`
	 * anhebbar, danach normalisiert.
	 *
	 * @return array{max_hosts:int,max_types_per_host:int}
	 */
	public static function resolve(): array {
		/**
		 * Filtert die Buchungs-Grenzen (Free -> Pro).
		 *
		 * @param array{max_hosts:int,max_types_per_host:int} $limits Standardgrenzen.
		 */
		$filtered = apply_filters( 'kurato_booking_limits', self::DEFAULTS );
		return self::normalize( is_array( $filtered ) ? $filtered : array() );
	}

	/**
	 * Normalisiert einen (Filter-)Rohwert auf ganze Zahlen. Fehlende Schluessel
	 * fallen auf die Defaults zurueck; ein Wert <= 0 bedeutet "unbegrenzt".
	 *
	 * @param array<string, mixed> $raw Rohgrenzen.
	 * @return array{max_hosts:int,max_types_per_host:int}
	 */
	public static function normalize( array $raw ): array {
		return array(
			'max_hosts'          => self::clean( $raw['max_hosts'] ?? self::DEFAULTS['max_hosts'] ),
			'max_types_per_host' => self::clean( $raw['max_types_per_host'] ?? self::DEFAULTS['max_types_per_host'] ),
		);
	}

	/**
	 * Darf bei aktuellem Bestand noch eins angelegt werden?
	 *
	 * @param int $current Aktueller Bestand.
	 * @param int $max     Obergrenze (<= 0 = unbegrenzt).
	 * @return bool
	 */
	public static function can_add( int $current, int $max ): bool {
		if ( $max <= 0 ) {
			return true;
		}
		return $current < $max;
	}

	/**
	 * Darf ein weiterer Host angelegt werden?
	 *
	 * @param int                                         $current Zahl vorhandener Hosts.
	 * @param array{max_hosts:int,max_types_per_host:int} $limits  Aufgeloeste Grenzen.
	 * @return bool
	 */
	public static function can_add_host( int $current, array $limits ): bool {
		return self::can_add( $current, (int) ( $limits['max_hosts'] ?? 0 ) );
	}

	/**
	 * Darf eine weitere Terminart fuer den Host angelegt werden?
	 *
	 * @param int                                         $current Zahl vorhandener Terminarten des Hosts.
	 * @param array{max_hosts:int,max_types_per_host:int} $limits  Aufgeloeste Grenzen.
	 * @return bool
	 */
	public static function can_add_type( int $current, array $limits ): bool {
		return self::can_add( $current, (int) ( $limits['max_types_per_host'] ?? 0 ) );
	}

	/**
	 * Wandelt einen Rohwert in eine ganze Zahl (<= 0 bleibt erhalten = unbegrenzt).
	 *
	 * @param mixed $value Rohwert.
	 * @return int
	 */
	private static function clean( $value ): int {
		if ( is_bool( $value ) || ! is_numeric( $value ) ) {
			return 0;
		}
		return (int) $value;
	}
}
