<?php
/**
 * WooCommerce product download codec.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChangesWooCommerce\CoreCompat\WooCommerce\Downloads;

use RuntimeException;

/**
 * Converts protected download objects without logging file values.
 */
final class DownloadCodec {
	/**
	 * @param array<string,\WC_Product_Download> $downloads Product downloads.
	 * @return array<int,array{id:string,name:string,file:string,enabled:bool}>
	 */
	public function encode( array $downloads ): array {
		$encoded = array();

		foreach ( $downloads as $download ) {
			if ( ! $download instanceof \WC_Product_Download ) {
				continue;
			}

			$encoded[] = array(
				'id'      => $download->get_id(),
				'name'    => $download->get_name(),
				'file'    => $download->get_file(),
				'enabled' => $download->get_enabled(),
			);
		}

		usort(
			$encoded,
			static fn ( array $left, array $right ): int => strcmp( $left['id'], $right['id'] )
		);

		return $encoded;
	}

	/**
	 * @param array<int,array<string,mixed>> $downloads Canonical downloads.
	 * @return array<string,\WC_Product_Download>
	 */
	public function decode( array $downloads ): array {
		$decoded = array();

		foreach ( $downloads as $download ) {
			$name = (string) ( $download['name'] ?? '' );
			$file = (string) ( $download['file'] ?? '' );

			if ( '' === trim( $name ) || '' === trim( $file ) ) {
				throw new RuntimeException( 'Download name and file are required.' );
			}

			$object = new \WC_Product_Download();
			$id     = (string) ( $download['id'] ?? '' );

			$object->set_id( '' === $id ? wp_generate_uuid4() : $id );
			$object->set_name( $name );
			$object->set_file( $file );
			$object->set_enabled( (bool) ( $download['enabled'] ?? true ) );
			$decoded[ $object->get_id() ] = $object;
		}

		return $decoded;
	}

	/**
	 * Returns audit-safe metadata without paths or signed URLs.
	 *
	 * @param array<int,array<string,mixed>> $downloads Canonical downloads.
	 * @return array<int,array{id:string,name:string,enabled:bool}>
	 */
	public function redact( array $downloads ): array {
		return array_values(
			array_map(
				static fn ( array $download ): array => array(
					'id'      => (string) ( $download['id'] ?? '' ),
					'name'    => (string) ( $download['name'] ?? '' ),
					'enabled' => (bool) ( $download['enabled'] ?? true ),
				),
				$downloads
			)
		);
	}
}
