<?php

namespace SugarCalendarBookings\Availability;

use DateTime;
use Exception;
use SugarCalendarBookings\Appointments\AppointmentValidationService;
use SugarCalendarBookings\Employees\EmployeeModel;
use SugarCalendarBookings\Locations\LocationFactory;
use SugarCalendarBookings\Plugin;
use SugarCalendarBookings\Services\ServiceModel;
use SugarCalendarBookings\Support\Ajax\AbstractController;
use SugarCalendarBookings\Support\Helpers\Date;

/**
 * Availability controller.
 *
 * @since 1.0.0
 */
class AvailabilityController extends AbstractController {

	/**
	 * Get slots.
	 *
	 * @since 1.0.0
	 * @since 1.3.1 Added context parameter to support admin-specific availability behavior.
	 */
	public function get_slots() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh

		$rules = [
			'from_date'              => 'required|string|date_format:' . DateTime::ATOM,
			'to_date'                => 'required|string|date_format:' . DateTime::ATOM,
			'service_id'             => 'required|id',
			'employee_id'            => 'nullable|id',
			'location'               => 'required|array',
			'location.type'          => 'required|string|in:in_person,online',
			'location.id'            => 'required_if:type,in_person|id',
			'location.uid'           => 'required_if:type,online|string',
			'exclude_appointments'   => 'nullable|array',
			'exclude_appointments.*' => 'id',
			'context'                => 'nullable|string|in:admin',
			'ignore_availability'    => 'nullable|numeric',
		];

		$data = $this->get_input_data( $rules );

		$from_date = Date::to_utc( $data['from_date'] );
		$to_date   = Date::to_utc( $data['to_date'] );

		$service = ServiceModel::query()
			->with( [ 'employees' => fn( $q ) => $q->where( 'status', '=', 'enabled', '%s' ) ] )
			->where( 'id', '=', $data['service_id'], '%d' )
			->first();

		if ( ! $service ) {
			wp_send_json_error( esc_html__( 'Service not found.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$employee = null;

		if ( ! empty( $data['employee_id'] ) ) {
			$employee = EmployeeModel::get( $data['employee_id'] );

			if ( ! $employee ) {
				wp_send_json_error( esc_html__( 'Employee not found.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
			}
		}

		$location = LocationFactory::from_array( $data['location'] );

		if ( ! $location ) {
			wp_send_json_error( esc_html__( 'Location not found.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		if ( $employee ) {
			try {
				Plugin::get( AppointmentValidationService::class )->validate_relations( $service, $location, $employee );
			} catch ( Exception $e ) {
				wp_send_json_error( $e->getMessage() );
			}
		}

		$is_admin_context    = ! empty( $data['context'] ) && $data['context'] === 'admin';
		$ignore_availability = ! empty( $data['ignore_availability'] );
		$skip_advance_window = $is_admin_context && current_user_can( 'manage_options' );

		$slots = Plugin::get( AvailabilityService::class )->get_slots( $from_date, $to_date, $service, $location, $employee, null, $data['exclude_appointments'] ?? [], $skip_advance_window );

		wp_send_json_success( $slots );
	}
}
