<?php
/**
 * Shared utility helpers used across multiple plugin classes.
 *
 * @package WooEquipmentRental
 */

declare( strict_types=1 );

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

/**
 * Class WCRent_Utils
 */
class WCRent_Utils {

	/**
	 * Order statuses considered active rentals.
	 *
	 * @return string[]
	 */
	public static function active_statuses(): array {
		return array( 'wc-processing', 'wc-on-hold', 'wc-completed' );
	}

	/**
	 * Returns true when WooCommerce HPOS is enabled.
	 */
	public static function hpos_is_enabled(): bool {
		return class_exists( \Automattic\WooCommerce\Utilities\OrderUtil::class )
			&& \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
	}

	/**
	 * Returns the orders table name and status column for the current storage mode.
	 *
	 * @return array{table: string, status_col: string}
	 */
	public static function orders_table(): array {
		global $wpdb;

		if ( self::hpos_is_enabled() ) {
			return array(
				'table'      => $wpdb->prefix . 'wc_orders',
				'status_col' => 'o.status',
				'date_col'   => 'o.date_created_gmt',
			);
		}

		return array(
			'table'      => $wpdb->prefix . 'posts',
			'status_col' => 'o.post_status',
			'date_col'   => 'o.post_date_gmt',
		);
	}

	/**
	 * Returns the order meta table name and order foreign-key column for the
	 * current storage mode.
	 *
	 * @return array{table: string, fk_col: string}
	 */
	public static function orders_meta_table(): array {
		global $wpdb;

		if ( self::hpos_is_enabled() ) {
			return array(
				'table'  => $wpdb->prefix . 'wc_orders_meta',
				'fk_col' => 'order_id',
			);
		}

		return array(
			'table'  => $wpdb->postmeta,
			'fk_col' => 'post_id',
		);
	}

	/**
	 * Returns true when a product has rental enabled.
	 *
	 * @param int $product_id Product post ID.
	 */
	public static function is_rental_product( int $product_id ): bool {
		return 'yes' === get_post_meta( $product_id, '_rental_enabled', true );
	}

	/**
	 * Returns a string of %s placeholders for use in a SQL IN clause, one per
	 * entry in the given array.
	 *
	 * @param array<string> $items Array whose count determines placeholder count.
	 */
	public static function status_placeholders( array $items ): string {
		return implode( ', ', array_fill( 0, count( $items ), '%s' ) );
	}

	/**
	 * Validates a YYYY-MM-DD date string using both format check and calendar validity.
	 *
	 * @param string $date Date string to validate.
	 */
	public static function is_valid_date( string $date ): bool {
		if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date ) ) {
			return false;
		}

		[ $y, $m, $d ] = explode( '-', $date );

		return checkdate( (int) $m, (int) $d, (int) $y );
	}

	/**
	 * Formats a Y-m-d date string using the site's date_format option.
	 *
	 * @param string $date Y-m-d date string.
	 * @return string Formatted date, or empty string on invalid input.
	 */
	public static function format_date( string $date ): string {
		if ( ! self::is_valid_date( $date ) ) {
			return '';
		}

		$ts = strtotime( $date );

		if ( false === $ts ) {
			return '';
		}

		return (string) wp_date( get_option( 'date_format', 'F j, Y' ), $ts );
	}

	/**
	 * Returns the configured billing method: 'calendar_days' (inclusive) or 'rental_nights' (exclusive end).
	 */
	public static function billing_method(): string {
		return (string) get_option( 'wcrent_billing_method', 'calendar_days' );
	}

	/**
	 * Calculates rental days from start and end date strings.
	 *
	 * @param string $start_date Y-m-d start date.
	 * @param string $end_date   Y-m-d end date.
	 * @return int Number of rental days, or 0 on invalid input.
	 */
	public static function calc_rental_days( string $start_date, string $end_date ): int {
		if ( ! self::is_valid_date( $start_date ) || ! self::is_valid_date( $end_date ) ) {
			return 0;
		}

		try {
			$start = new DateTimeImmutable( $start_date );
			$end   = new DateTimeImmutable( $end_date );
		} catch ( \Exception $e ) {
			return 0;
		}

		if ( $end < $start ) {
			return 0;
		}

		$diff = (int) $start->diff( $end )->days;

		if ( 'calendar_days' === self::billing_method() ) {
			return $diff + 1;
		}

		return max( 1, $diff );
	}
}
