<?php

declare( strict_types=1 );

namespace Simplyin\Simplyin_W_Plugin\Tests\Unit;

use Brain\Monkey;
use Brain\Monkey\Functions;
use PHPUnit\Framework\TestCase;
use Simplyin\Simplyin_W_Plugin\Dto\Order\Order_DTO_Factory;
use Simplyin\Simplyin_W_Plugin\Dto\Order\Order_Items_DTO;

/**
 * orderDate: the backend needs the *original* order-placement date on
 * import, not the last-modified date (get_date_modified()), which updated_at already
 * carries. This must stay independent of updated_at even when both differ.
 */
final class Order_Date_Test extends TestCase {

	protected function setUp(): void {
		parent::setUp();
		Monkey\setUp();
		Functions\when( 'wc_format_decimal' )->alias(
			static function ( $value, $dp = 2 ) {
				return number_format( round( (float) $value, (int) $dp ), (int) $dp, '.', '' );
			}
		);
		Functions\when( 'get_bloginfo' )->justReturn( 'Test Shop' );
		Functions\when( 'sanitize_text_field' )->returnArg();
	}

	protected function tearDown(): void {
		Monkey\tearDown();
		parent::tearDown();
	}

	/**
	 * @param ?\WC_DateTime $date_created
	 * @param ?\WC_DateTime $date_modified
	 * @return \WC_Order
	 */
	private function makeOrder( ?\WC_DateTime $date_created, ?\WC_DateTime $date_modified ) {
		// Anonymous class extending the WC_Order stub aliased in tests/bootstrap.php;
		// provides only the getters create_order_data_dto() reads.
		return new class( $date_created, $date_modified ) extends \WC_Order {
			private $date_created;
			private $date_modified;

			public function __construct( $date_created, $date_modified ) {
				$this->date_created  = $date_created;
				$this->date_modified = $date_modified;
			}

			public function get_order_number() { return '1001'; }
			public function get_items( $types = 'line_item' ) { return []; }
			public function get_subtotal() { return 100.0; }
			public function get_shipping_total() { return 0.0; }
			public function get_shipping_tax() { return 0.0; }
			public function get_total_discount( $ex_tax = true ) { return 0.0; }
			public function get_total_tax() { return 23.0; }
			public function get_total() { return 123.0; }
			public function get_currency() { return 'PLN'; }
			public function get_billing_first_name() { return 'Jan'; }
			public function get_billing_last_name() { return 'Kowalski'; }
			public function get_billing_address_1() { return ''; }
			public function get_billing_address_2() { return ''; }
			public function get_billing_city() { return ''; }
			public function get_billing_postcode() { return ''; }
			public function get_billing_country() { return 'PL'; }
			public function get_billing_state() { return ''; }
			public function get_billing_company() { return ''; }
			public function get_customer_ip_address() { return '127.0.0.1'; }
			public function get_status() { return 'processing'; }
			public function get_date_created() { return $this->date_created; }
			public function get_date_modified() { return $this->date_modified; }
		};
	}

	public function test_order_date_reflects_original_creation_not_modification(): void {
		$created  = new \WC_DateTime( '2026-01-05 10:00:00', new \DateTimeZone( 'UTC' ) );
		$modified = new \WC_DateTime( '2026-01-15 18:30:00', new \DateTimeZone( 'UTC' ) );
		$order    = $this->makeOrder( $created, $modified );

		$dto = Order_DTO_Factory::create_order_data_dto( $order, new Order_Items_DTO(), [ 'method' => 'card', 'title' => 'Card' ], '1.0.0', '9.0.0', 'shop@example.com' );
		$array = $dto->to_array();

		$this->assertSame( '2026-01-05T10:00:00Z', $array['orderDate'] );
		$this->assertSame( '2026-01-15T18:30:00Z', $array['updatedAt'] );
		$this->assertNotSame( $array['orderDate'], $array['updatedAt'] );
	}

	public function test_order_date_omitted_when_date_created_is_null(): void {
		// date_modified stays non-null (WC always sets it) so build_status_info()'s existing
		// updatedAt/statusInfo wiring is unaffected; only date_created (orderDate's source) is null.
		$modified = new \WC_DateTime( '2026-01-15 18:30:00', new \DateTimeZone( 'UTC' ) );
		$order    = $this->makeOrder( null, $modified );

		$dto   = Order_DTO_Factory::create_order_data_dto( $order, new Order_Items_DTO(), [ 'method' => 'card', 'title' => 'Card' ], '1.0.0', '9.0.0', 'shop@example.com' );
		$array = $dto->to_array();

		$this->assertArrayNotHasKey( 'orderDate', $array );
	}
}
