<?php

namespace SugarCalendarBookings\Abilities\Appointments;

use SugarCalendarBookings\Abilities\AbstractAbility;
use WP_Error;

/**
 * Ability: aggregate appointment counts and revenue.
 *
 * @since 1.5.0
 */
class GetAppointmentStatsAbility extends AbstractAbility {

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

		return 'get-appointment-stats';
	}

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

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

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

		return esc_html__( 'Counts by status and revenue over a date range, optionally filtered by service.', '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_DATE_RANGE,
				[
					'service_id' => [
						'type'    => 'integer',
						'minimum' => 1,
					],
				]
			),
		];
	}

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

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

	/**
	 * Aggregate counts and revenue across the filtered appointment set.
	 *
	 * @since 1.5.0
	 *
	 * @param mixed $input Input data.
	 *
	 * @return array|WP_Error
	 */
	public function execute( $input ) {

		$args = $this->normalize_input( $input );

		$validation = $this->validate_date_range( $args );

		if ( is_wp_error( $validation ) ) {
			return $validation;
		}

		[ $where_sql, $params ] = $this->build_filter_sql( $args );

		$counts  = $this->load_status_counts( $where_sql, $params );
		$revenue = $this->aggregate_revenue( $this->load_revenue_buckets( $where_sql, $params ) );

		return [
			'filters' => [
				'date_from'  => $args['date_from'] ?? null,
				'date_to'    => $args['date_to'] ?? null,
				'service_id' => isset( $args['service_id'] ) ? (int) $args['service_id'] : null,
			],
			'counts'  => [
				'total'     => array_sum( $counts ),
				'by_status' => $counts,
			],
			'revenue' => $revenue,
		];
	}

	/**
	 * Build the shared WHERE clause + bindings used by both the count and revenue queries.
	 *
	 * @since 1.5.0
	 *
	 * @param array $args Normalized input.
	 *
	 * @return array{0: string, 1: array}
	 */
	private function build_filter_sql( array $args ): array {

		$where  = [ '1=1' ];
		$params = [];

		$this->append_date_range_clauses( $args, 'appointments.start_at', $where, $params );

		if ( ! empty( $args['service_id'] ) ) {
			$where[]  = 'appointments.service_id = %d';
			$params[] = (int) $args['service_id'];
		}

		return [ implode( ' AND ', $where ), $params ];
	}
}
