<?php
/**
 * REST API controller for vehicles.
 *
 * @package ThemeREX\AutoDealer
 * @version 1.0.0
 */

declare(strict_types=1);

namespace ThemeREX\AutoDealer\REST;

use ThemeREX\AutoDealer\Search\FilterParams;
use ThemeREX\AutoDealer\Search\VehicleQuery;
use WP_Error;
use WP_REST_Controller;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

/**
 * Handles GET requests for vehicle listings and single vehicles.
 */
class VehiclesController extends WP_REST_Controller {

	/**
	 * Route namespace.
	 *
	 * @var string
	 */
	protected $namespace = 'trx-auto-dealer/v1';

	/**
	 * Route base.
	 *
	 * @var string
	 */
	protected $rest_base = 'vehicles';

	/**
	 * Register REST routes.
	 *
	 * @return void
	 */
	public function register_routes(): void {
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base,
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_items' ),
					'permission_callback' => '__return_true',
					'args'                => $this->get_collection_params(),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/(?P<id>[\d]+)',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_item' ),
					'permission_callback' => '__return_true',
					'args'                => array(
						'id' => array(
							'description' => __( 'Unique identifier for the vehicle.', 'trx-auto-dealer' ),
							'type'        => 'integer',
							'required'    => true,
						),
					),
				),
			)
		);
	}

	/**
	 * Retrieve a collection of vehicles.
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_REST_Response|WP_Error Response or error.
	 */
	public function get_items( $request ) {
		$params = FilterParams::fromRequest( $request );
		$query  = new VehicleQuery();

		$total       = $query->count( $params );
		$total_pages = $params->getPerPage() > 0 ? (int) ceil( $total / $params->getPerPage() ) : 0;
		$rows        = $query->fetch( $params );

		$vehicles = array();
		foreach ( $rows as $row ) {
			$post_id    = (int) $row['ID'];
			$vehicles[] = $this->prepare_vehicle_data( $post_id, $row );
		}

		$response = new WP_REST_Response( $vehicles, 200 );
		$response->header( 'X-WP-Total', (string) $total );
		$response->header( 'X-WP-TotalPages', (string) $total_pages );

		return $response;
	}

	/**
	 * Retrieve a single vehicle.
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_REST_Response|WP_Error Response or error.
	 */
	public function get_item( $request ) {
		$post_id = (int) $request->get_param( 'id' );
		$post    = get_post( $post_id );

		if ( null === $post || 'trx_ad_listing' !== $post->post_type || 'publish' !== $post->post_status ) {
			return new WP_Error(
				'trx_ad_listing_not_found',
				__( 'Vehicle not found.', 'trx-auto-dealer' ),
				array( 'status' => 404 )
			);
		}

		$specs = \ThemeREX\AutoDealer\getVehicleSpecs( $post_id );

		if ( null === $specs ) {
			return new WP_Error(
				'trx_ad_specs_not_found',
				__( 'Vehicle specifications not found.', 'trx-auto-dealer' ),
				array( 'status' => 404 )
			);
		}

		$data = $this->prepare_vehicle_data( $post_id, $specs, true );

		return new WP_REST_Response( $data, 200 );
	}

	/**
	 * Prepare vehicle data for API response.
	 *
	 * @param int                  $post_id   The post ID.
	 * @param array<string, mixed> $specs     Vehicle specs row.
	 * @param bool                 $full      Whether to include full details.
	 * @return array<string, mixed> Vehicle data array.
	 */
	private function prepare_vehicle_data( int $post_id, array $specs, bool $full = false ): array {
		$thumbnail_id  = (int) get_post_thumbnail_id( $post_id );
		$thumbnail_url = '';

		if ( $thumbnail_id > 0 ) {
			$image         = wp_get_attachment_image_url( $thumbnail_id, 'large' );
			$thumbnail_url = $image ? $image : '';
		}

		$data = array(
			'id'                 => $post_id,
			'title'              => get_the_title( $post_id ),
			'permalink'          => get_permalink( $post_id ),
			'featured_image_url' => $thumbnail_url,
			'specs'              => array(
				'year'           => isset( $specs['year'] ) ? (int) $specs['year'] : null,
				'make'           => $specs['make'] ?? '',
				'model'          => $specs['model'] ?? '',
				'trim'           => $specs['trim_level'] ?? '',
				'price'          => isset( $specs['price'] ) ? (float) $specs['price'] : null,
				'sale_price'     => isset( $specs['sale_price'] ) && '' !== $specs['sale_price'] ? (float) $specs['sale_price'] : null,
				'mileage'        => isset( $specs['mileage'] ) ? (int) $specs['mileage'] : null,
				'fuel_type'      => $specs['fuel_type'] ?? '',
				'transmission'   => $specs['transmission'] ?? '',
				'drivetrain'     => $specs['drivetrain'] ?? '',
				'condition_type' => $specs['condition_type'] ?? '',
				'status'         => $specs['status'] ?? 'available',
				'body_style'     => $specs['body_style'] ?? '',
			),
		);

		if ( $full ) {
			$data['specs'] = array_merge(
				$data['specs'],
				array(
					'vin'              => $specs['vin'] ?? '',
					'stock_number'     => $specs['stock_number'] ?? '',
					'color_ext'        => $specs['color_ext'] ?? '',
					'color_int'        => $specs['color_int'] ?? '',
					'doors'            => isset( $specs['doors'] ) ? (int) $specs['doors'] : null,
					'seats'            => isset( $specs['seats'] ) ? (int) $specs['seats'] : null,
					'engine'           => $specs['engine'] ?? '',
					'horsepower'       => isset( $specs['horsepower'] ) ? (int) $specs['horsepower'] : null,
					'torque'           => isset( $specs['torque'] ) ? (int) $specs['torque'] : null,
					'weight'           => isset( $specs['weight'] ) ? (int) $specs['weight'] : null,
					'mpg_city'         => isset( $specs['mpg_city'] ) ? (float) $specs['mpg_city'] : null,
					'mpg_highway'      => isset( $specs['mpg_highway'] ) ? (float) $specs['mpg_highway'] : null,
					'mpg_combined'     => isset( $specs['mpg_combined'] ) ? (float) $specs['mpg_combined'] : null,
					'co2_emissions'    => isset( $specs['co2_emissions'] ) ? (float) $specs['co2_emissions'] : null,
					'battery_capacity' => isset( $specs['battery_capacity'] ) ? (float) $specs['battery_capacity'] : null,
					'electric_range'   => isset( $specs['electric_range'] ) ? (int) $specs['electric_range'] : null,
					'charge_time'      => $specs['charge_time'] ?? '',
					'price_on_request' => ! empty( $specs['price_on_request'] ),
					'accident_free'    => ! empty( $specs['accident_free'] ),
				)
			);

			// Include gallery images.
			$gallery_ids = get_post_meta( $post_id, TRX_AD_PREFIX . 'gallery', true );
			$gallery     = array();

			if ( is_array( $gallery_ids ) ) {
				foreach ( $gallery_ids as $attachment_id ) {
					$url = wp_get_attachment_image_url( (int) $attachment_id, 'large' );
					if ( $url ) {
						$gallery[] = array(
							'id'  => (int) $attachment_id,
							'url' => $url,
						);
					}
				}
			}

			$data['gallery'] = $gallery;

			// Include features.
			$features         = wp_get_post_terms( $post_id, 'trx_ad_feature', array( 'fields' => 'names' ) );
			$data['features'] = is_array( $features ) ? $features : array();

			// Include dealer info.
			$dealer_id = (int) get_post_meta( $post_id, TRX_AD_PREFIX . 'dealer_id', true );
			if ( $dealer_id > 0 ) {
				$data['dealer'] = array(
					'id'   => $dealer_id,
					'name' => get_the_title( $dealer_id ),
					'meta' => \ThemeREX\AutoDealer\getDealerMeta( $dealer_id ),
				);
			}

			$data['content'] = wp_kses_post( (string) get_the_content( null, false, $post_id ) );
		}

		return $data;
	}

	/**
	 * Get the query params for collections.
	 *
	 * @return array<string, array<string, mixed>> Collection parameters.
	 */
	public function get_collection_params(): array {
		return array(
			'page'       => array(
				'description'       => __( 'Current page of the collection.', 'trx-auto-dealer' ),
				'type'              => 'integer',
				'default'           => 1,
				'minimum'           => 1,
				'sanitize_callback' => 'absint',
			),
			'per_page'   => array(
				'description'       => __( 'Maximum number of items per page.', 'trx-auto-dealer' ),
				'type'              => 'integer',
				'default'           => 12,
				'minimum'           => 1,
				'maximum'           => 100,
				'sanitize_callback' => 'absint',
			),
			'make'       => array(
				'description'       => __( 'Filter by vehicle make.', 'trx-auto-dealer' ),
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			),
			'model'      => array(
				'description'       => __( 'Filter by vehicle model.', 'trx-auto-dealer' ),
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			),
			'year_from'  => array(
				'description'       => __( 'Minimum year.', 'trx-auto-dealer' ),
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			),
			'year_to'    => array(
				'description'       => __( 'Maximum year.', 'trx-auto-dealer' ),
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			),
			'price_from' => array(
				'description'       => __( 'Minimum price.', 'trx-auto-dealer' ),
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			),
			'price_to'   => array(
				'description'       => __( 'Maximum price.', 'trx-auto-dealer' ),
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			),
			'condition'  => array(
				'description'       => __( 'Filter by condition (new, used, certified).', 'trx-auto-dealer' ),
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			),
			'body_style' => array(
				'description'       => __( 'Filter by body style.', 'trx-auto-dealer' ),
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			),
			'fuel_type'  => array(
				'description'       => __( 'Filter by fuel type.', 'trx-auto-dealer' ),
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			),
			'status'     => array(
				'description'       => __( 'Filter by listing status.', 'trx-auto-dealer' ),
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			),
			'orderby'    => array(
				'description'       => __( 'Sort collection by field.', 'trx-auto-dealer' ),
				'type'              => 'string',
				'default'           => 'date',
				'enum'              => array( 'date', 'price', 'year', 'mileage', 'title', 'price_reduced' ),
				'sanitize_callback' => 'sanitize_text_field',
			),
			'order'      => array(
				'description'       => __( 'Order sort direction.', 'trx-auto-dealer' ),
				'type'              => 'string',
				'default'           => 'DESC',
				'enum'              => array( 'ASC', 'DESC' ),
				'sanitize_callback' => 'sanitize_text_field',
			),
		);
	}
}
