<?php

namespace Fotogenic_AI;

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

/**
 * Strictly binds one batch-poll response to the requested upstream job set.
 */
final class Generate_Batch_Response_Parser {
	private const STATUSES = [ 'processing', 'completed', 'failed', 'not_found' ];

	/**
	 * @param mixed  $payload           Decoded response object.
	 * @param array  $requested_job_ids Exact requested upstream identities.
	 * @return array{statuses:array<string,string>,errors:array<string,array{errorCode:string,error:string}>}|\WP_Error
	 */
	public static function parse( $payload, array $requested_job_ids ) {
		$requested = self::normalize_requested_ids( $requested_job_ids );
		$jobs = is_array( $payload ) ? ( $payload['jobs'] ?? null ) : null;
		if (
			empty( $requested )
			|| ! is_array( $jobs )
			|| ! fotogenic_ai_array_is_list( $jobs )
			|| count( $jobs ) !== count( $requested )
		) {
			return self::error();
		}

		$statuses = [];
		$errors   = [];
		foreach ( $jobs as $position => $job ) {
			$job_id = is_array( $job ) ? Upstream_Identifier::normalize( $job['jobId'] ?? null ) : '';
			$status = is_array( $job ) ? ( $job['status'] ?? null ) : null;
			if (
				'' === $job_id
				|| ! is_string( $status )
				|| ! in_array( $status, self::STATUSES, true )
				|| ! isset( $requested[ $position ] )
				|| ! hash_equals( $requested[ $position ], $job_id )
				|| isset( $statuses[ $job_id ] )
			) {
				return self::error();
			}
			$statuses[ $job_id ] = $status;
			if ( in_array( $status, [ 'failed', 'not_found' ], true ) ) {
				$error_code = is_string( $job['errorCode'] ?? null )
					? substr( sanitize_key( $job['errorCode'] ), 0, 64 )
					: '';
				$error_message = is_string( $job['error'] ?? null )
					? substr( sanitize_text_field( $job['error'] ), 0, 500 )
					: '';
				$errors[ $job_id ] = [
					'errorCode' => '' !== $error_code ? $error_code : $status,
					'error'     => $error_message,
				];
			}
		}

		return [
			'statuses' => $statuses,
			'errors'   => $errors,
		];
	}

	/** @return string[] */
	private static function normalize_requested_ids( array $job_ids ): array {
		$normalized = [];
		foreach ( $job_ids as $job_id ) {
			$job_id = Upstream_Identifier::normalize( $job_id );
			if ( '' === $job_id || in_array( $job_id, $normalized, true ) ) {
				return [];
			}
			$normalized[] = $job_id;
		}
		return $normalized;
	}

	private static function error(): \WP_Error {
		return new \WP_Error(
			'fotogenic_ai_invalid_batch_response',
			__( 'The upstream job response could not be verified.', 'fotogenic-ai' ),
			[ 'status' => 502 ]
		);
	}
}
