<?php

namespace Fotogenic_AI;

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

final class Service_Increase_Resolution_Start {
    private const WORKFLOW = 'increase_resolution';

    private Workflow_Start_Coordinator $coordinator;

    public function __construct( ?Workflow_Start_Coordinator $coordinator = null ) {
        $this->coordinator = $coordinator ?? new Workflow_Start_Coordinator();
    }

	/** @return array|\WP_Error */
	public function start_command( int $user_id, array $command, array $options = [] ) {
		if ( $user_id <= 0 || get_current_user_id() !== $user_id ) {
			return Messages::error( 'forbidden', 403 );
		}
		if ( ! empty( array_diff( array_keys( $command ), [ 'target', 'subjectId', 'requestId', 'sourceAttachmentId' ] ) ) ) {
			return Messages::error( 'invalid_request', 400 );
		}
		$universal_fingerprint = (string) ( $options['universal_fingerprint'] ?? '' );
		$trusted_bulk_context  = (array) ( $options['bulk_context'] ?? [] );
		$trusted_item_context  = (array) ( $options['item_identity'] ?? [] );
		$trusted_pricing       = (array) ( $options['trusted_pricing'] ?? [] );
        $connected = $this->coordinator->ensure_connected();
        if ( is_wp_error( $connected ) ) {
            return $connected;
        }

		$request_id = $this->coordinator->validate_request_id( (string) ( $command['requestId'] ?? '' ) );
        if ( is_wp_error( $request_id ) ) {
            return $request_id;
        }
		$target = sanitize_key( (string) ( $command['target'] ?? '' ) );
		$subject_id = (int) ( $command['subjectId'] ?? 0 );
		$context = $this->coordinator->resolve_target_context( $target, $subject_id );
        if ( is_wp_error( $context ) ) {
            return $context;
        }
        $context = $this->coordinator->attach_item_identity_context( $context, $trusted_item_context );
        if ( is_wp_error( $context ) ) {
            return $context;
        }

		$source_attachment_id = (int) ( $command['sourceAttachmentId'] ?? 0 );
        $allowed = $this->coordinator->validate_editable_image_attachment( $source_attachment_id );
        if ( is_wp_error( $allowed ) ) {
            return $allowed;
        }
        if ( 'media' === $target && $subject_id !== $source_attachment_id ) {
            return new \WP_Error(
                'fotogenic_ai_invalid_enhance_source',
                __( 'The Media target must match the source attachment.', 'fotogenic-ai' ),
                [ 'status' => 400 ]
            );
        }

        $fingerprint_payload = [
            'target'             => (string) $context['run_target'],
            'subjectId'          => (int) $context['subject_id'],
            'sourceAttachmentId' => $source_attachment_id,
        ];
        if ( ! empty( $context['run_item_uuid'] ) ) {
            $fingerprint_payload['itemIdentity'] = [
                'runItemId'       => (string) $context['run_item_uuid'],
                'campaignGroupId' => (string) ( $context['campaign_group_uuid'] ?? '' ),
                'itemOrdinal'     => (int) ( $context['item_ordinal'] ?? 0 ),
                'target'          => Workflow_Item_Identity::target_hint( (array) $context['target_snapshot'] ),
            ];
        }
        $fingerprint = $this->coordinator->fingerprint_payload( self::WORKFLOW, $fingerprint_payload );
        if ( is_wp_error( $fingerprint ) ) {
            return $fingerprint;
        }
        $replay = $this->coordinator->replay_request( $user_id, self::WORKFLOW, $request_id, $fingerprint );
        if ( null !== $replay ) {
			return $replay;
        }
        $subject_guard = $this->coordinator->guard_subject_admission( $user_id, self::WORKFLOW, $request_id, $context );
        if ( is_wp_error( $subject_guard ) ) {
            return $subject_guard;
        }

		$pricing = [] !== $trusted_pricing
			? Workflow_Preflight::normalize_trusted_pricing( $trusted_pricing, self::WORKFLOW, 1 )
			: Price_Service::instance()->get_enhance_pricing( true );
		if ( is_wp_error( $pricing ) ) {
			return $pricing;
		}
		$price_per_output = [] !== $trusted_pricing
			? (float) $pricing['creditsPerOutput']
			: (float) $pricing['credits'];
        $source_image = Image_Source_Resolver::instance()->get_enhance_image_file_for_attachment( $source_attachment_id );
        if ( is_wp_error( $source_image ) ) {
            return $source_image;
        }
        $multipart = ( new Increase_Resolution_Multipart_Builder() )->build( [ 'source_image' => $source_image ] );
        if ( is_wp_error( $multipart ) ) {
            return $multipart;
        }

        $metadata = [
            'source_attachment_id'  => $source_attachment_id,
            'source_attachment_ids' => [ $source_attachment_id ],
            'expected_output_count' => 1,
			'estimated_cost'        => $price_per_output,
            'images_count'          => 1,
            'quality'               => '2K',
        ];
        $metadata = array_merge( $metadata, $this->coordinator->item_identity_metadata( $context ) );
        $bulk_run_uuid = strtolower( trim( (string) ( $trusted_bulk_context['bulk_run_uuid'] ?? '' ) ) );
        $bulk_item_id  = (int) ( $trusted_bulk_context['bulk_item_id'] ?? 0 );
        if ( wp_is_uuid( $bulk_run_uuid ) && $bulk_item_id > 0 ) {
            $metadata['bulk_run_uuid'] = $bulk_run_uuid;
            $metadata['bulk_item_id']  = $bulk_item_id;
        }
        $admission = $this->coordinator->admit_request(
            $user_id,
            self::WORKFLOW,
            $request_id,
            $fingerprint,
            $context,
            $metadata,
            $universal_fingerprint
        );
        if ( is_wp_error( $admission ) ) {
            return $admission;
        }
        if ( ! empty( $admission['replayed'] ) ) {
            $result = $admission['result'] ?? Messages::error( 'request_failed', 500 );
			return $result;
        }
		$idempotency_key = $this->coordinator->get_upstream_idempotency_key( $admission );
		if ( is_wp_error( $idempotency_key ) ) {
			return $idempotency_key;
		}

        $start = $this->coordinator->begin_start( $user_id, self::WORKFLOW, $request_id, $context, $metadata, $admission );
        if ( is_wp_error( $start ) ) {
            return $start;
        }
		$prepared_start = $this->coordinator->prepare_upstream_dispatch( $start );
		if ( is_wp_error( $prepared_start ) ) {
			return $this->coordinator->handle_upstream_error( $prepared_start, self::WORKFLOW, $request_id, $context, $start );
		}
		$start = $prepared_start;

        $api_response = Api_Client::instance()->request_multipart(
            'enhance_images',
            $multipart['fields'],
            $multipart['files'],
            [
				'request_id'      => $request_id,
				'run_id'          => (string) $start['run_id'],
				'idempotency_key' => $idempotency_key,
            ]
        );
        if ( is_wp_error( $api_response ) ) {
            return $this->coordinator->handle_upstream_error( $api_response, self::WORKFLOW, $request_id, $context, $start );
        }

		$captured = $this->coordinator->capture_upstream_start_response( self::WORKFLOW, $start, $api_response );
		if ( is_wp_error( $captured ) ) {
			return $this->coordinator->handle_upstream_error( $captured, self::WORKFLOW, $request_id, $context, $start );
		}
		$start['request_record'] = $captured['request_record'];
		$job_ids = $captured['job_ids'];
		$result = $this->coordinator->complete_start( $user_id, self::WORKFLOW, $request_id, $context, $start, $job_ids, $metadata );
        if ( is_wp_error( $result ) ) {
            return $result;
        }
		$result['acceptedOutputCount'] = (int) $captured['accepted_output_count'];
		return $result;
    }
}
