<?php

namespace SugarCalendarBookings\Abilities\Services;

use SugarCalendarBookings\Abilities\AbstractAbility;
use SugarCalendarBookings\Appointments\AppointmentModel;
use SugarCalendarBookings\Services\ServiceModel;
use WP_Error;

/**
 * Ability: get a single service by ID.
 *
 * @since 1.5.0
 */
class GetServiceAbility extends AbstractAbility {

	/**
	 * Ability slug, without the namespace prefix.
	 *
	 * @since 1.5.0
	 *
	 * @return string
	 */
	public function get_name(): string {

		return 'get-service';
	}

	/**
	 * Human-readable label.
	 *
	 * @since 1.5.0
	 *
	 * @return string
	 */
	public function get_label(): string {

		return esc_html__( 'Get Service', 'sugar-calendar-bookings-scheduling-appointments-lite' );
	}

	/**
	 * Human-readable description.
	 *
	 * @since 1.5.0
	 *
	 * @return string
	 */
	public function get_description(): string {

		return esc_html__( 'Get a single service by ID with overrides and appointments_count.', 'sugar-calendar-bookings-scheduling-appointments-lite' );
	}

	/**
	 * Input schema.
	 *
	 * @since 1.5.0
	 *
	 * @return array
	 */
	public function get_input_schema(): array {

		return [
			'type'       => 'object',
			'properties' => self::SCHEMA_ID,
			'required'   => [ 'id' ],
		];
	}

	/**
	 * Output schema.
	 *
	 * @since 1.5.0
	 *
	 * @return array
	 */
	public function get_output_schema(): array {

		return [ 'type' => 'object' ];
	}

	/**
	 * Resolve the service and return its full body with appointments_count.
	 *
	 * @since 1.5.0
	 *
	 * @param mixed $input Input data.
	 *
	 * @return array|WP_Error
	 */
	public function execute( $input ) {

		$args = $this->normalize_input( $input );
		$id   = isset( $args['id'] ) ? (int) $args['id'] : 0;

		if ( $id <= 0 ) {
			return $this->not_found_error(
				esc_html__( 'Service not found.', 'sugar-calendar-bookings-scheduling-appointments-lite' )
			);
		}

		$service = ServiceModel::query()
			->with(
				[
					'locations' => static fn( $q ) => $q->select( [ 'id', 'name' ] ),
					'employees' => static fn( $q ) => $q->select( [ 'id', 'name' ] ),
					'tags'      => static fn( $q ) => $q->select( [ 'id', 'name' ] ),
					'meta'      => static fn( $q ) => $q->where( 'meta_key', 'IN', [ 'feature_image_id', 'use_default_working_schedule', 'working_schedule', 'online_locations', 'override_payment_methods', 'payment_gateways', 'override_email_notifications', 'emails' ], '%s' ),
				]
			)
			->where( 'services.id', '=', $id, '%d' )
			->first();

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

		// Demand framing: drafts are abandoned booking flows (noise), but
		// cancellations are real demand signal for this service and stay in.
		$appointments_count = (int) AppointmentModel::query()
			->where( 'appointments.service_id', '=', $service->id, '%d' )
			->where(
				'appointments.status',
				'NOT IN',
				[ AppointmentModel::STATUS_DRAFT ],
				'%s'
			)
			->count();

		$body                       = $this->formatter()->service( $service, true );
		$body['appointments_count'] = $appointments_count;

		return $body;
	}
}
