<?php
/**
 * Admin scheduling date/time helpers.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Admin;

use ScheduledChanges\Domain\Shared\NamedTimezone;
use ScheduledChanges\Domain\Shared\UtcTimestamp;

/**
 * Parses and formats admin schedule times in the site timezone.
 */
final class AdminScheduleClock {
	/**
	 * Returns default modal scheduling values in the site timezone.
	 *
	 * @return array<string,string>
	 */
	public function scheduleDefaults(): array {
		$timezone     = new \DateTimeZone( $this->siteTimezoneName() );
		$current_time = new \DateTimeImmutable( 'now', $timezone );
		$default_time = $current_time->modify( '+1 hour' );

		return array(
			'currentDate' => $current_time->format( 'Y-m-d' ),
			'defaultDate' => $default_time->format( 'Y-m-d' ),
			'defaultTime' => $default_time->format( 'H:i' ),
			'timezone'    => $this->siteTimezoneName(),
		);
	}

	/**
	 * Parses Calendar modal date/time input into a UTC timestamp.
	 */
	public function scheduledTimestamp( string $date, string $time, NamedTimezone $timezone ): UtcTimestamp {
		$timezone_name = $timezone->value();

		if ( ! NamedTimezone::isValid( $timezone_name ) ) {
			$timezone_name = $this->siteTimezoneName();
		}

		$local  = \DateTimeImmutable::createFromFormat(
			'!Y-m-d H:i',
			$date . ' ' . $time,
			new \DateTimeZone( $timezone_name )
		);
		$errors = \DateTimeImmutable::getLastErrors();

		if (
			false === $local
			|| ( is_array( $errors ) && ( $errors['warning_count'] > 0 || $errors['error_count'] > 0 ) )
		) {
			throw new \InvalidArgumentException( 'Choose a valid go-live date and time.' );
		}

		$scheduled_at = new UtcTimestamp( $local->setTimezone( new \DateTimeZone( 'UTC' ) ) );

		if ( $scheduled_at->native() <= UtcTimestamp::now()->native() ) {
			throw new \InvalidArgumentException( 'Choose a go-live time in the future.' );
		}

		return $scheduled_at;
	}

	/**
	 * Formats a scheduled timestamp for client-facing dashboard notices.
	 */
	public function scheduledNoticeTime( UtcTimestamp $timestamp, NamedTimezone $timezone ): string {
		$format = trim(
			(string) get_option( 'date_format', 'F j, Y' ) . ' ' . (string) get_option( 'time_format', 'g:i a' )
		);

		if ( '' === $format ) {
			$format = 'F j, Y g:i a';
		}

		return sprintf(
			/* translators: 1: localized date and time, 2: timezone name. */
			__( '%1$s · %2$s', 'jjs-post-scheduler' ),
			wp_date( $format, $timestamp->native()->getTimestamp(), $timezone->native() ),
			$timezone->value()
		);
	}

	/**
	 * Returns the site timezone name with a UTC fallback.
	 */
	public function siteTimezoneName(): string {
		$timezone = wp_timezone_string();

		return NamedTimezone::isValid( $timezone ) ? $timezone : 'UTC';
	}
}
