<?php
/**
 * Date logic — done correctly with the store timezone.
 *
 * This is the part competitors get wrong: customers buying "after cutoff" still got
 * today's date, or the date shifted because UTC was used instead of the store timezone.
 * Everything here is computed against wp_timezone() so it matches what the merchant sees.
 *
 * @package Datery
 */

defined( 'ABSPATH' ) || exit;

class Datery_Dates {

	const FORMAT = 'Y-m-d';

	/**
	 * "Now" in the store timezone.
	 */
	public static function now() {
		return new DateTimeImmutable( 'now', wp_timezone() );
	}

	/**
	 * Earliest selectable date (Y-m-d), accounting for lead time + same-day cutoff.
	 */
	public static function min_date() {
		$lead = (int) Datery_Settings::get( 'min_lead_days', 1 );

		// Cutoff: if we're past it, add one more day of lead time.
		$cutoff = Datery_Settings::get( 'cutoff_time', '' );
		if ( '' !== $cutoff && self::is_past_cutoff( $cutoff ) ) {
			$lead += 1;
		}

		$date = self::now()->setTime( 0, 0, 0 );
		if ( $lead > 0 ) {
			$date = $date->modify( '+' . $lead . ' days' );
		}

		return $date->format( self::FORMAT );
	}

	/**
	 * Latest selectable date (Y-m-d).
	 */
	public static function max_date() {
		$max  = max( 1, (int) Datery_Settings::get( 'max_days', 30 ) );
		$date = self::now()->setTime( 0, 0, 0 )->modify( '+' . $max . ' days' );
		return $date->format( self::FORMAT );
	}

	/**
	 * Are we currently past the HH:MM cutoff in the store timezone?
	 */
	public static function is_past_cutoff( $cutoff ) {
		if ( ! preg_match( '/^([01]\d|2[0-3]):([0-5]\d)$/', (string) $cutoff, $m ) ) {
			return false;
		}
		$now    = self::now();
		$cutoff = $now->setTime( (int) $m[1], (int) $m[2], 0 );
		return $now > $cutoff;
	}

	/**
	 * Validate a submitted Y-m-d string. Returns true or a WP_Error.
	 *
	 * @return true|WP_Error
	 */
	public static function validate( $value ) {
		$value = trim( (string) $value );

		$date = DateTimeImmutable::createFromFormat( '!' . self::FORMAT, $value, wp_timezone() );
		if ( ! $date || $date->format( self::FORMAT ) !== $value ) {
			return new WP_Error( 'datery_invalid', __( 'Please choose a valid delivery date.', 'datery-delivery-date-for-woocommerce' ) );
		}

		if ( $value < self::min_date() ) {
			return new WP_Error( 'datery_too_early', __( 'The delivery date you chose is too soon. Please pick a later date.', 'datery-delivery-date-for-woocommerce' ) );
		}

		if ( $value > self::max_date() ) {
			return new WP_Error( 'datery_too_late', __( 'The delivery date you chose is too far ahead. Please pick an earlier date.', 'datery-delivery-date-for-woocommerce' ) );
		}

		/**
		 * Pro hooks in here to reject blocked weekdays / holidays / full slots.
		 *
		 * @param true|WP_Error $result Current validation result.
		 * @param string        $value  The submitted Y-m-d date.
		 */
		return apply_filters( 'datery_validate_date', true, $value );
	}

	/**
	 * All selectable dates (Y-m-d) between min and max.
	 *
	 * Pro filters `datery_available_dates` to strip blocked weekdays, holidays and full days —
	 * used to build the block-checkout date dropdown (which has no native date type).
	 *
	 * @return string[]
	 */
	public static function available_dates() {
		$out = array();
		$cur = DateTimeImmutable::createFromFormat( '!' . self::FORMAT, self::min_date(), wp_timezone() );
		$max = DateTimeImmutable::createFromFormat( '!' . self::FORMAT, self::max_date(), wp_timezone() );

		if ( ! $cur || ! $max ) {
			return $out;
		}

		while ( $cur <= $max ) {
			$out[] = $cur->format( self::FORMAT );
			$cur   = $cur->modify( '+1 day' );
		}

		/**
		 * @param string[] $out List of selectable Y-m-d dates.
		 */
		return array_values( apply_filters( 'datery_available_dates', $out ) );
	}

	/**
	 * Format a stored Y-m-d date for display using the site's date format.
	 */
	public static function display( $value ) {
		$value = trim( (string) $value );
		$date  = DateTimeImmutable::createFromFormat( '!' . self::FORMAT, $value, wp_timezone() );
		if ( ! $date ) {
			return $value;
		}
		return wp_date( get_option( 'date_format', 'F j, Y' ), $date->getTimestamp(), wp_timezone() );
	}
}
