<?php

namespace SugarCalendarBookings\Availability;

use DateTimeImmutable;
use DateTimeZone;
use SugarCalendarBookings\Employees\EmployeeModel;

/**
 * Time period.
 *
 * Always in UTC.
 *
 * @since 1.0.0
 */
class WorkingPeriod {

	/**
	 * Start time in UTC.
	 *
	 * @since 1.0.0
	 *
	 * @var DateTimeImmutable
	 */
	private $start;

	/**
	 * End time in UTC.
	 *
	 * @since 1.0.0
	 *
	 * @var DateTimeImmutable
	 */
	private $end;

	/**
	 * Employees.
	 *
	 * Employees that are working during this period.
	 *
	 * @since 1.0.0
	 *
	 * @var array<EmployeeModel>
	 */
	private $employees;

	/**
	 * Constructor.
	 *
	 * @since 1.0.0
	 *
	 * @param DateTimeImmutable    $start     Start time in UTC.
	 * @param DateTimeImmutable    $end       End time in UTC.
	 * @param array<EmployeeModel> $employees Employee model.
	 */
	public function __construct( $start, $end, $employees ) {

		$this->start     = $start;
		$this->end       = $end;
		$this->employees = $employees;
	}

	/**
	 * Get start time in UTC.
	 *
	 * @since 1.0.0
	 *
	 * @return DateTimeImmutable Start time.
	 */
	public function start() {

		return $this->start;
	}

	/**
	 * Get end time in UTC.
	 *
	 * @since 1.0.0
	 *
	 * @return DateTimeImmutable End time.
	 */
	public function end() {

		return $this->end;
	}

	/**
	 * Get employee.
	 *
	 * @since 1.0.0
	 *
	 * @return array<EmployeeModel> Employee models.
	 */
	public function get_employees() {

		return $this->employees;
	}

	/**
	 * Create a time period from a working period rule.
	 *
	 * @since 1.0.0
	 *
	 * @param WorkingPeriodRule $working_period_rule Working period rule.
	 * @param DateTimeImmutable $date                Date.
	 *
	 * @return WorkingPeriod Working period.
	 */
	public static function from_rule( $working_period_rule, $date ) {

		$employee  = $working_period_rule->get_employee();
		$time_zone = $working_period_rule->get_time_zone();
		$start     = self::convert_time_to_utc( $working_period_rule->start(), $time_zone, $date );
		$end       = self::convert_time_to_utc( $working_period_rule->end(), $time_zone, $date );

		return new self( $start, $end, [ $employee ] );
	}

	/**
	 * Convert a time to UTC minutes since midnight.
	 * Handles DST by using the date.
	 *
	 * @since 1.0.0
	 *
	 * @param int               $time     Time in minutes since midnight.
	 * @param DateTimeZone      $timezone Timezone.
	 * @param DateTimeImmutable $date     Date. Required for proper DST handling.
	 *
	 * @return DateTimeImmutable
	 */
	private static function convert_time_to_utc( $time, $timezone, $date ) {

		static $utc_timezone = null;

		if ( $utc_timezone === null ) {
			$utc_timezone = new DateTimeZone( 'UTC' );
		}

		return $date->setTimezone( $timezone )
			->setTime( 0, 0 )
			->modify( "+{$time} minutes" )
			->setTimezone( $utc_timezone );
	}
}
