<?php
namespace Booktics\Appointment\Schedule;

/**
 * Strategy for generating time slots based on both service and team member schedules.
 * This class handles the intersection of availability between services and team members.
 */
class Service_And_Team_Member_Strategy implements Time_Slot_Strategy {
    /**
     * Generates available time slots based on service and team member schedules.
     *
     * @param Schedule_Entry|null $service_entry The schedule entry for the service
     * @param Schedule_Entry|null $team_entry The schedule entry for the team member
     * @param Schedule_Entry|null $default_entry The default schedule entry
     * @param Time_Slot_Manager $manager The time slot manager instance
     * @param \DateTime $date The date for which to generate slots
     *
     * @return array Array of Time_Slot objects representing available time slots
     */
    public function generate_slots(
        array $service_entries,
        array $team_entries,
        array $default_entries,
        Time_Slot_Manager $manager,
        \DateTime $date
    ): array {
        $slots = array();
        foreach ( $service_entries as $service_entry ) {
            if ( ! $service_entry || $service_entry->is_holiday() ) {
                continue;
            }
            foreach ( $team_entries as $team_entry ) {
                if ( $team_entry->get_day_of_week() !== $service_entry->get_day_of_week() ) {
                    continue;
                }
                if ( ! $team_entry || $team_entry->is_holiday() ) {
                    continue;
                }

                $service_start = strtotime( $service_entry->get_start_time() );
                $service_end   = strtotime( $service_entry->get_end_time() );
                $team_start    = strtotime( $team_entry->get_start_time() );
                $team_end      = strtotime( $team_entry->get_end_time() );

                $start_time = max( $service_start, $team_start );
                $end_time   = min( $service_end, $team_end );

                if ( $start_time >= $end_time ) {
                    continue;
                }

                $slot_length   = $manager->get_slot_length() * 60;
                $before_buffer = $manager->get_before_buffer_time() * 60;
                $after_buffer  = $manager->get_after_buffer_time() * 60;
                $gap           = $before_buffer + $after_buffer;
                $current_start = $start_time;
                while ( $current_start + $slot_length <= $end_time ) {
                    $slot_start = gmdate( 'H:i', $current_start );
                    $slot_end   = gmdate( 'H:i', $current_start + $slot_length );
                    $slots[]    = new Time_Slot( $slot_start, $slot_end, true );
                    $current_start += $slot_length + $gap;
                }
            }
        }
        return $slots;
    }
}
