<?php
/**
 * Trips CRUD + search.
 *
 * @package DatvetaucaotocBooking
 */

declare(strict_types=1);

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class Datvetau_Booking_Trip_Repository {

	public static function find_by_id( int $id ): ?array {
		global $wpdb;
		$table = Datvetau_Booking_Database::table( 'trips' );
		$row   = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table} WHERE id = %d", $id ), ARRAY_A );
		return $row ?: null;
	}

	public static function list_for_admin( ?int $route_id, ?string $month_ym ): array {
		global $wpdb;
		$table = Datvetau_Booking_Database::table( 'trips' );
		$where = array( '1=1' );
		$args  = array();

		if ( $route_id ) {
			$where[] = 'route_id = %d';
			$args[]  = $route_id;
		}
		if ( $month_ym && preg_match( '/^\d{4}-\d{2}$/', $month_ym ) ) {
			$where[] = 'trip_date >= %s AND trip_date < %s';
			$args[]  = $month_ym . '-01';
			$args[]  = gmdate( 'Y-m-d', strtotime( $month_ym . '-01 +1 month' ) );
		}

		$sql = "SELECT * FROM {$table} WHERE " . implode( ' AND ', $where ) . ' ORDER BY trip_date ASC, departure_time ASC, id ASC LIMIT 500';
		if ( $args ) {
			$sql = $wpdb->prepare( $sql, ...$args );
		}
		return $wpdb->get_results( $sql, ARRAY_A ) ?: array();
	}

	/**
	 * Các ngày (Y-m-d) có ít nhất một chuyến active trong tháng.
	 *
	 * @return list<string>
	 */
	public static function list_trip_dates_in_month( int $route_id, string $month_ym, string $seat_class ): array {
		if ( ! preg_match( '/^\d{4}-\d{2}$/', $month_ym ) ) {
			return array();
		}
		global $wpdb;
		$table   = Datvetau_Booking_Database::table( 'trips' );
		$start   = $month_ym . '-01';
		$end     = gmdate( 'Y-m-d', strtotime( $month_ym . '-01 +1 month' ) );
		$sql     = $wpdb->prepare(
			"SELECT DISTINCT trip_date FROM {$table}
			WHERE route_id = %d AND trip_date >= %s AND trip_date < %s
			AND seat_class = %s AND status = 'active'
			ORDER BY trip_date ASC",
			$route_id,
			$start,
			$end,
			$seat_class
		);
		$rows = $wpdb->get_col( $sql );
		return $rows ? array_map( 'strval', $rows ) : array();
	}

	public static function search( int $route_id, string $trip_date, string $seat_class ): array {
		global $wpdb;
		$table = Datvetau_Booking_Database::table( 'trips' );
		$sql   = $wpdb->prepare(
			"SELECT * FROM {$table} WHERE route_id = %d AND trip_date = %s AND seat_class = %s AND status = 'active' ORDER BY departure_time ASC",
			$route_id,
			$trip_date,
			$seat_class
		);
		return $wpdb->get_results( $sql, ARRAY_A ) ?: array();
	}

	public static function save( array $data, ?int $id = null ): int {
		global $wpdb;
		$table = Datvetau_Booking_Database::table( 'trips' );

		$capacity = max( 0, (int) ( $data['capacity'] ?? 0 ) );
		$remaining = isset( $data['seats_remaining'] ) ? (int) $data['seats_remaining'] : $capacity;

		$row = array(
			'route_id'            => (int) ( $data['route_id'] ?? 0 ),
			'trip_date'           => (string) ( $data['trip_date'] ?? '' ),
			'departure_time'      => (string) ( $data['departure_time'] ?? '00:00:00' ),
			'arrival_time'        => (string) ( $data['arrival_time'] ?? '00:00:00' ),
			'operator_name'       => sanitize_text_field( (string) ( $data['operator_name'] ?? '' ) ),
			'operator_logo_url'   => esc_url_raw( (string) ( $data['operator_logo_url'] ?? '' ) ),
			'seat_class'          => in_array( $data['seat_class'] ?? '', array( 'eco', 'vip' ), true ) ? $data['seat_class'] : 'eco',
			'price_adult'         => (int) ( $data['price_adult'] ?? $data['price_adult_eco_base'] ?? 0 ),
			'price_adult_eco_base'=> (int) ( $data['price_adult'] ?? $data['price_adult_eco_base'] ?? 0 ),
			'price_child'         => (int) ( $data['price_child'] ?? 0 ),
			'price_senior'        => (int) ( $data['price_senior'] ?? 0 ),
			'capacity'            => $capacity,
			'seats_remaining'     => min( $remaining, $capacity ),
			'status'              => ( $data['status'] ?? 'active' ) === 'cancelled' ? 'cancelled' : 'active',
		);

		if ( $id ) {
			$wpdb->update( $table, $row, array( 'id' => $id ) );
			return $id;
		}

		$wpdb->insert( $table, $row );
		return (int) $wpdb->insert_id;
	}

	public static function delete( int $id ): void {
		global $wpdb;
		$table = Datvetau_Booking_Database::table( 'trips' );
		$wpdb->delete( $table, array( 'id' => $id ) );
	}

	/**
	 * @param list<int|string> $ids
	 */
	public static function delete_many( array $ids ): int {
		$ids = array_values(
			array_unique(
				array_filter(
					array_map( 'intval', $ids ),
					static fn( int $id ): bool => $id > 0
				)
			)
		);
		if ( ! $ids ) {
			return 0;
		}
		global $wpdb;
		$table   = Datvetau_Booking_Database::table( 'trips' );
		$deleted = 0;
		foreach ( $ids as $id ) {
			$deleted += (int) $wpdb->delete( $table, array( 'id' => $id ) );
		}
		return $deleted;
	}

	/**
	 * Trừ ghế nếu đủ chỗ. Trả về false nếu không đủ.
	 */
	public static function decrement_seats( int $trip_id, int $count ): bool {
		global $wpdb;
		$table = Datvetau_Booking_Database::table( 'trips' );
		$updated = $wpdb->query(
			$wpdb->prepare(
				"UPDATE {$table} SET seats_remaining = seats_remaining - %d WHERE id = %d AND status = 'active' AND seats_remaining >= %d",
				$count,
				$trip_id,
				$count
			)
		);
		return $updated === 1;
	}

	public static function increment_seats( int $trip_id, int $count ): void {
		global $wpdb;
		$table = Datvetau_Booking_Database::table( 'trips' );
		$wpdb->query(
			$wpdb->prepare(
				"UPDATE {$table} SET seats_remaining = LEAST(capacity, seats_remaining + %d) WHERE id = %d",
				$count,
				$trip_id
			)
		);
	}

	public static function to_api_trip( array $trip, array $route ): array {
		$dep = substr( (string) $trip['departure_time'], 0, 5 );
		$arr = substr( (string) $trip['arrival_time'], 0, 5 );
		$date_display = gmdate( 'd-m-Y', strtotime( (string) $trip['trip_date'] ) );

		$logo = (string) ( $trip['operator_logo_url'] ?: Datvetau_Booking_Settings::all()['default_operator_logo'] );

		return array(
			'id'           => (string) $trip['id'],
			'routeId'      => (string) $route['slug'],
			'routeLabel'   => (string) $route['label'],
			'date'         => $date_display,
			'dateIso'      => (string) $trip['trip_date'],
			'departure'    => $dep,
			'arrival'      => $arr,
			'operator'     => (string) $trip['operator_name'],
			'operatorLogo' => $logo,
			'priceVnd'        => (int) ( $trip['price_adult'] ?? $trip['price_adult_eco_base'] ?? 0 ),
			'priceChildVnd'   => (int) ( $trip['price_child'] ?? 0 ),
			'priceSeniorVnd'  => (int) ( $trip['price_senior'] ?? 0 ),
			'availability' => ( (int) $trip['seats_remaining'] > 0 && 'active' === $trip['status'] ) ? 'available' : 'sold_out',
			'seatsRemaining' => (int) $trip['seats_remaining'],
		);
	}
}
