<?php
/**
 * Create booking + seat decrement.
 *
 * @package DatvetaucaotocBooking
 */

declare(strict_types=1);

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class Datvetau_Booking_Service {

	/**
	 * @return array{success:bool,code?:string,booking_id?:int,errors?:string[],data?:array}
	 */
	public static function create_from_payload( array $payload ): array {
		$errors = Datvetau_Booking_Validator::validate_booking_payload( $payload );
		if ( $errors ) {
			return array( 'success' => false, 'errors' => $errors );
		}

		$trip_type   = (string) $payload['tripType'];
		$seat_class  = (string) $payload['seatClass'];
		$out_id      = (int) $payload['outboundTripId'];
		$in_id       = ! empty( $payload['inboundTripId'] ) ? (int) $payload['inboundTripId'] : null;
		$passengers  = (array) $payload['passengers'];
		$booker      = (array) $payload['booker'];
		$count       = count( $passengers );

		$out_trip = Datvetau_Booking_Trip_Repository::find_by_id( $out_id );
		if ( ! $out_trip || 'active' !== $out_trip['status'] ) {
			return array( 'success' => false, 'errors' => array( 'Chuyến chiều đi không hợp lệ' ) );
		}

		$in_trip = null;
		if ( 'round-trip' === $trip_type ) {
			$in_trip = $in_id ? Datvetau_Booking_Trip_Repository::find_by_id( $in_id ) : null;
			if ( ! $in_trip || 'active' !== $in_trip['status'] ) {
				return array( 'success' => false, 'errors' => array( 'Chuyến chiều về không hợp lệ' ) );
			}
		}

		if ( (int) $out_trip['seats_remaining'] < $count ) {
			return array( 'success' => false, 'errors' => array( 'Chuyến chiều đi không đủ chỗ' ) );
		}
		if ( $in_trip && (int) $in_trip['seats_remaining'] < $count ) {
			return array( 'success' => false, 'errors' => array( 'Chuyến chiều về không đủ chỗ' ) );
		}

		$pricing = Datvetau_Booking_Pricing::compute_total( $trip_type, $seat_class, $passengers, $out_trip, $in_trip );

		global $wpdb;
		$wpdb->query( 'START TRANSACTION' );

		try {
			if ( ! Datvetau_Booking_Trip_Repository::decrement_seats( $out_id, $count ) ) {
				throw new RuntimeException( 'decrement_outbound_failed' );
			}
			if ( $in_trip && ! Datvetau_Booking_Trip_Repository::decrement_seats( (int) $in_trip['id'], $count ) ) {
				throw new RuntimeException( 'decrement_inbound_failed' );
			}

			$route = Datvetau_Booking_Route_Repository::find_by_id( (int) $out_trip['route_id'] );
			if ( ! $route ) {
				throw new RuntimeException( 'route_missing' );
			}

			$code = Datvetau_Booking_Booking_Repository::generate_booking_code();

			$booking_row = array(
				'booking_code'      => $code,
				'status'            => 'pending_payment',
				'trip_type'         => $trip_type,
				'route_id'          => (int) $route['id'],
				'outbound_trip_id'  => $out_id,
				'inbound_trip_id'   => $in_trip ? (int) $in_trip['id'] : null,
				'seat_class'        => $seat_class,
				'ticket_count'      => $count,
				'total_vnd'         => (int) $pricing['total_vnd'],
				'booker_name'       => sanitize_text_field( (string) ( $booker['fullName'] ?? '' ) ),
				'booker_phone'      => sanitize_text_field( (string) ( $booker['phone'] ?? '' ) ),
				'booker_email'      => sanitize_email( (string) ( $booker['email'] ?? '' ) ),
				'booker_note'       => sanitize_textarea_field( (string) ( $booker['note'] ?? '' ) ),
			);

			$p_rows = array();
			foreach ( $passengers as $i => $p ) {
				$p = (array) $p;
				$pr = $pricing['passenger_rows'][ $i ];
				$p_rows[] = array(
					'full_name'       => sanitize_text_field( (string) ( $p['fullName'] ?? '' ) ),
					'birth_date'      => sanitize_text_field( (string) ( $p['birthDate'] ?? '' ) ),
					'nationality'     => sanitize_text_field( (string) ( $p['nationality'] ?? '' ) ),
					'id_number'       => sanitize_text_field( (string) ( $p['idNumber'] ?? '' ) ),
					'hometown'        => sanitize_text_field( (string) ( $p['hometown'] ?? '' ) ),
					'fare_category'   => (string) $pr['fare_category'],
					'unit_price_vnd'  => (int) $pr['unit_price_vnd'],
					'legs_count'      => (int) $pr['legs_count'],
				);
			}

			$booking_id = Datvetau_Booking_Booking_Repository::insert_booking( $booking_row, $p_rows );

			$wpdb->query( 'COMMIT' );

			Datvetau_Booking_Notifier::on_booking_created( $booking_id );

			return array(
				'success'    => true,
				'code'       => $code,
				'booking_id' => $booking_id,
				'data'       => array(
					'bookingCode' => $code,
					'totalVnd'    => (int) $pricing['total_vnd'],
				),
			);
		} catch ( Throwable $e ) {
			$wpdb->query( 'ROLLBACK' );
			return array( 'success' => false, 'errors' => array( 'Không thể tạo đơn. Vui lòng thử lại.' ) );
		}
	}

	public static function cancel_booking( int $booking_id ): bool {
		$booking = Datvetau_Booking_Booking_Repository::find_by_id( $booking_id );
		if ( ! $booking || 'cancelled' === $booking['status'] ) {
			return false;
		}

		$count = (int) $booking['ticket_count'];
		Datvetau_Booking_Trip_Repository::increment_seats( (int) $booking['outbound_trip_id'], $count );
		if ( ! empty( $booking['inbound_trip_id'] ) ) {
			Datvetau_Booking_Trip_Repository::increment_seats( (int) $booking['inbound_trip_id'], $count );
		}
		Datvetau_Booking_Booking_Repository::update_status( $booking_id, 'cancelled' );
		return true;
	}
}
