<?php

namespace SugarCalendarBookings\Abilities\Services;

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

/**
 * Ability: list bookable services.
 *
 * @since 1.5.0
 */
class ListServicesAbility extends AbstractAbility {

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

		return 'list-services';
	}

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

		return esc_html__( 'List Services', 'sugar-calendar-bookings-scheduling-appointments-lite' );
	}

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

		return esc_html__( 'List bookable services with pagination.', 'sugar-calendar-bookings-scheduling-appointments-lite' );
	}

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

		return [
			'type'       => 'object',
			'properties' => array_merge(
				self::SCHEMA_PAGINATION,
				[
					'status' => [
						'type' => 'string',
						'enum' => [ 'enabled', 'disabled', 'trash' ],
					],
				]
			),
		];
	}

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

		return [
			'type'       => 'object',
			'properties' => [
				'services' => [ 'type' => 'array' ],
				'total'    => [ 'type' => 'integer' ],
			],
		];
	}

	/**
	 * Query the service list and return summary bodies plus the total count.
	 *
	 * @since 1.5.0
	 *
	 * @param mixed $input Input data.
	 *
	 * @return array|WP_Error
	 */
	public function execute( $input ) {

		$args       = $this->normalize_input( $input );
		$pagination = $this->get_pagination( $args );
		$limit      = $pagination['limit'];
		$offset     = $pagination['offset'];

		// Summary mode skips `payment_gateways`/`emails` (only used by `get-service` in full mode).
		$query = 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', 'override_email_notifications' ], '%s' ),
			]
		);

		$count_query = ServiceModel::query();

		if ( ! empty( $args['status'] ) ) {
			$query->where( 'services.status', '=', (string) $args['status'], '%s' );
			$count_query->where( 'services.status', '=', (string) $args['status'], '%s' );
		}

		$total = (int) $count_query->count();

		$query->order_by( 'services.id', 'DESC' )
			->offset( $offset )
			->limit( $limit );

		$rows      = $query->get();
		$formatter = $this->formatter();

		$out = [];

		foreach ( $rows as $row ) {
			$out[] = $formatter->service( $row );
		}

		return [
			'services' => $out,
			'total'    => $total,
		];
	}
}
