<?php
/**
 * Break Time Sync Service
 */

namespace RadiusTheme\RadiusBooking\Services\EmployeeServices;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}
use Exception;
use InvalidArgumentException;
use RadiusTheme\RadiusBooking\Repositories\UserRepository;
use RadiusTheme\RadiusBooking\Core\Support\Collection;

/**
 * Class UserBreakTimeSyncService
 *
 * Handles synchronization of user break times
 *
 * @package RadiusTheme\RadiusBooking\Services\UserServices
 * @since 1.0.0
 */
class BreakTimeSyncService {

	/**
	 * The user repository instance.
	 *
	 * @var UserRepository $userRepo
	 */
	private UserRepository $userRepo;

	/**
	 * Constructor
	 *
	 * @param UserRepository $userRepo  User repository instance.
	 */
	public function __construct( UserRepository $userRepo ) {
		$this->userRepo = $userRepo;
	}

	/**
	 * Synchronizes the user's break times for a specific weekday by validating, removing obsolete data, and saving the updated breaks.
	 *
	 * @param int $userId The ID of the user whose break times are being synchronized.
	 * @param int $weekdayId The ID of the weekday for which break times are being synchronized.
	 * @param array $breaks An array of break data to be validated and saved.
	 *
	 * @return void
	 * @throws Exception If an error occurs during the synchronization process.
	 */
	public function syncUserBreakTime( int $userId, int $weekdayId, array $breaks ): void {
		try {
			$this->validateBreakData( $breaks );
			$this->removeObsoleteBreaks( $weekdayId, $breaks );
			$this->saveBreakTimes( $userId, $weekdayId, $breaks );
		} catch ( Exception $e ) {
			error_log( 'Error syncing user break time: ' . $e->getMessage() );
			throw $e;
		}
	}

	/**
	 * Validate the provided break data to ensure it meets the required format.
	 *
	 * @param array $breaks An array of break data, where each item must include 'start_time' and 'end_time' keys.
	 *
	 * @return void
	 * @throws InvalidArgumentException If the input is not an array or if any break lacks the required keys.
	 */
	private function validateBreakData( array $breaks ): void {
		if ( ! is_array( $breaks ) ) {
			throw new InvalidArgumentException( 'Breaks must be an array' );
		}

		foreach ( $breaks as $break ) {
			if ( ! isset( $break['start_time'] ) || ! isset( $break['end_time'] ) ) {
				throw new InvalidArgumentException( 'Start time and end time are required for breaks' );
			}
		}
	}

	/**
	 * Remove obsolete break times for a specific weekday, based on the provided breaks.
	 *
	 * @param int $weekdayId The ID of the weekday for which obsolete breaks should be removed.
	 * @param array $breaks An array of break data to be retained.
	 *
	 * @return void
	 */
	private function removeObsoleteBreaks( int $weekdayId, array $breaks ): void {
		if ( empty( $breaks ) ) {
			$this->userRepo->deleteAllBreaksForWeekday( $weekdayId );
			return;
		}

		$breakIds = ( new Collection( $breaks ) )->pluck( 'id' );
		if ( ! empty( $breakIds ) ) {
			$this->userRepo->deleteBreaksNotInList( $breaks, $weekdayId, $breakIds );
		}
	}

	/**
	 * Saves the break times for a specific user on a specific weekday.
	 *
	 * @param int $userId The ID of the user for whom the break times are being saved.
	 * @param int $weekdayId The ID of the weekday for which the break times are being saved.
	 * @param array $breaks An array containing the break times to be saved.
	 *
	 * @return void
	 */
	private function saveBreakTimes( int $userId, int $weekdayId, array $breaks ): void {
		foreach ( $breaks as $break ) {
			$this->userRepo->saveBreakTime( $userId, $weekdayId, $break );
		}
	}
}
