<?php

namespace Fotogenic_AI;

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

final class Service_Experiences {
	private const PRE_AUTH_CONTENT_VERSION        = 'pre-auth-welcome-v2';
	private const POST_AUTH_CONTENT_VERSION       = 'post-auth-grant-v1';
	private const CREDIT_CONTENT_VERSION          = 'credit-depletion-v1';
	private const PRIORITY_WELCOME                = 300;
	private const PRIORITY_ZERO                   = 200;
	private const PRIORITY_LOW                    = 100;
	private const DEFAULT_PRICING_URL             = 'https://fotogenic.ai/pricing/';
	private const DEFAULT_MANAGE_URL              = 'https://account.fotogenic.ai/?entry_context=wp&destination=pricing';
	private const ALLOWED_OUTCOMES                = [
		'dismissed',
		'primary',
		'secondary',
	];

	private Experience_State_Store $state_store;

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

	public function handle_claim( \WP_REST_Request $request ) {
		$params = $request->get_json_params();
		$params = is_array( $params ) ? $params : [];
		if ( ! empty( $params ) ) {
			return $this->invalid_request( __( 'Experience eligibility is determined by the server.', 'fotogenic-ai' ) );
		}

		$result = $this->claim();

		return is_wp_error( $result ) ? $result : rest_ensure_response( $result );
	}

	public function handle_dismiss( \WP_REST_Request $request ) {
		$params = $request->get_json_params();
		$params = is_array( $params ) ? $params : [];
		$allowed_keys = [ 'claimId', 'outcome' ];
		if ( ! empty( array_diff( array_keys( $params ), $allowed_keys ) ) ) {
			return $this->invalid_request( __( 'Unexpected experience dismissal data was provided.', 'fotogenic-ai' ) );
		}

		$claim_id = (string) ( $params['claimId'] ?? '' );
		$outcome  = (string) ( $params['outcome'] ?? '' );
		$result   = $this->dismiss( $claim_id, $outcome );

		return is_wp_error( $result ) ? $result : rest_ensure_response( $result );
	}

	/** @return array|\WP_Error */
	public function claim( int $user_id = 0 ) {
		$user_id = $this->resolve_current_user_id( $user_id );
		if ( is_wp_error( $user_id ) ) {
			return $user_id;
		}

		$owner = $this->state_store->acquire_claim_lock( $user_id );
		if ( null === $owner ) {
			return new \WP_Error(
				'fotogenic_ai_experience_busy',
				__( 'Another experience request is already being processed. Please try again.', 'fotogenic-ai' ),
				[ 'status' => 409 ]
			);
		}

		try {
			return $this->claim_locked( $user_id );
		} finally {
			$this->state_store->release_claim_lock( $user_id, $owner );
		}
	}

	/** @return array|\WP_Error */
	public function dismiss( string $claim_id, string $outcome, int $user_id = 0 ) {
		$user_id = $this->resolve_current_user_id( $user_id );
		if ( is_wp_error( $user_id ) ) {
			return $user_id;
		}

		$claim_id = $this->sanitize_claim_id( $claim_id );
		$outcome  = sanitize_key( $outcome );
		if ( '' === $claim_id || ! in_array( $outcome, self::ALLOWED_OUTCOMES, true ) ) {
			return $this->invalid_request( __( 'A valid claim ID and dismissal outcome are required.', 'fotogenic-ai' ) );
		}

		$owner = $this->state_store->acquire_claim_lock( $user_id );
		if ( null === $owner ) {
			return new \WP_Error(
				'fotogenic_ai_experience_busy',
				__( 'Another experience request is already being processed. Please try again.', 'fotogenic-ai' ),
				[ 'status' => 409 ]
			);
		}

		try {
			return $this->dismiss_locked( $user_id, $claim_id, $outcome );
		} finally {
			$this->state_store->release_claim_lock( $user_id, $owner );
		}
	}

	/** @return array|\WP_Error */
	private function claim_locked( int $user_id ) {
		$auth      = Auth_Session::instance();
		$connected = $auth->is_connected();
		$scope_key = $connected
			? $this->state_store->fingerprint_account( $this->get_account_identity( $auth ) )
			: 'guest';
		$document  = $this->state_store->get( $user_id );
		$scope     = $this->state_store->get_scope( $document, $scope_key );
		$candidate = null;
		$changed   = false;

		if ( ! $connected ) {
			$candidate = $this->get_pre_auth_welcome_candidate( $scope );
		} else {
			$credits       = $this->get_authoritative_credit_state();
			$config_result = Config_Provider::get_config();
			$config        = isset( $config_result['data'] ) && is_array( $config_result['data'] ) ? $config_result['data'] : [];
			$free_trial    = $this->get_authoritative_free_trial( $credits, $config );
			$has_plan     = ! empty( $credits['hasPlan'] );
			$threshold    = $this->resolve_low_credit_threshold( $config, $has_plan );
			$rearm        = $this->resolve_rearm_threshold( $config, $threshold );
			$old_episode  = $scope['creditEpisode'];

			$scope['creditEpisode'] = $this->update_credit_episode( $old_episode, $credits, $threshold, $rearm );
			$changed                  = $scope['creditEpisode'] !== $old_episode;

			$candidate = $this->get_post_auth_welcome_candidate( $scope, $free_trial );
			if ( null === $candidate ) {
				$candidate = $this->get_zero_credit_candidate( $scope, $credits, $has_plan, $auth );
			}
			if ( null === $candidate ) {
				$candidate = $this->get_low_credit_candidate( $scope, $credits, $has_plan, $threshold, $auth );
			}
		}

		if ( null === $candidate ) {
			if ( $changed ) {
				$document = $this->state_store->set_scope( $document, $scope_key, $scope );
				if ( ! $this->state_store->save( $user_id, $document, $scope_key ) ) {
					return $this->state_write_error();
				}
			}

			return [
				'claimed'    => false,
				'experience' => null,
			];
		}

		return $this->commit_claim( $user_id, $document, $scope_key, $scope, $candidate );
	}

	/** @return array|\WP_Error */
	private function dismiss_locked( int $user_id, string $claim_id, string $outcome ) {
		$document = $this->state_store->get( $user_id );
		$claim    = $this->state_store->get_claim( $document, $claim_id );
		if ( null === $claim ) {
			return new \WP_Error(
				'fotogenic_ai_experience_claim_not_found',
				__( 'This experience claim could not be found.', 'fotogenic-ai' ),
				[ 'status' => 404 ]
			);
		}

		$existing_outcome = sanitize_key( (string) ( $claim['outcome'] ?? '' ) );
		if ( '' !== $existing_outcome ) {
			return [
				'dismissed' => true,
			];
		}

		$claim['outcome']     = $outcome;
		$claim['dismissedAt'] = time();
		$scope_key             = (string) $claim['scope'];
		$scope                 = $this->state_store->get_scope( $document, $scope_key );
		$scope                 = $this->apply_outcome_to_scope( $scope, $claim_id, $claim );
		$document              = $this->state_store->set_scope( $document, $scope_key, $scope );
		$document              = $this->state_store->set_claim( $document, $claim_id, $claim );

		if ( ! $this->state_store->save( $user_id, $document, $scope_key ) ) {
			return $this->state_write_error();
		}

		return [
			'dismissed' => true,
		];
	}

	/** @return array|\WP_Error */
	private function commit_claim( int $user_id, array $document, string $scope_key, array $scope, array $candidate ) {
		$claim_id  = wp_generate_uuid4();
		$shown_at  = time();
		$type      = (string) $candidate['payload']['type'];
		$variant   = (string) $candidate['payload']['variant'];
		$state_key = sanitize_key( (string) $candidate['stateKey'] );

		$scope = $this->mark_scope_shown( $scope, $claim_id, $shown_at, $candidate );
		$document = $this->state_store->set_scope( $document, $scope_key, $scope );
		$document = $this->state_store->set_claim(
			$document,
			$claim_id,
			[
				'scope'       => $scope_key,
				'type'        => $type,
				'variant'     => $variant,
				'stateKey'    => $state_key,
				'shownAt'     => $shown_at,
				'outcome'     => '',
				'dismissedAt' => 0,
			]
		);

		if ( ! $this->state_store->save( $user_id, $document, $scope_key ) ) {
			return $this->state_write_error();
		}

		$experience            = array_intersect_key(
			$candidate['payload'],
			array_fill_keys(
				[
					'kind',
					'balance',
					'grantedCredits',
					'hasPlan',
					'primaryAction',
					'secondaryAction',
				],
				true
			)
		);
		$experience['claimId'] = $claim_id;

		return [
			'claimed'    => true,
			'experience' => $experience,
		];
	}

	private function get_pre_auth_welcome_candidate( array $scope ): ?array {
		$state_key = sanitize_key( self::PRE_AUTH_CONTENT_VERSION );
		$shown     = (int) ( $scope['welcomeOffers'][ $state_key ]['shownAt'] ?? 0 );
		if ( $shown > 0 ) {
			return null;
		}

		return [
			'category' => 'welcomeOffers',
			'stateKey' => $state_key,
			'payload'  => [
				'type'            => 'welcome',
				'kind'            => 'welcome_disconnected',
				'variant'         => 'pre_auth_offer',
				'priority'        => self::PRIORITY_WELCOME,
				'contentVersion'  => self::PRE_AUTH_CONTENT_VERSION,
				'connected'       => false,
				'primaryAction'   => [
					'id' => 'connect',
				],
			],
		];
	}

	private function get_post_auth_welcome_candidate( array $scope, array $free_trial ): ?array {
		$granted_credits = $this->normalize_non_negative_number( $free_trial['grantedCredits'] ?? null );
		$notice          = isset( $free_trial['grantNotice'] ) && is_array( $free_trial['grantNotice'] ) ? $free_trial['grantNotice'] : [];
		$eligible        = true === ( $notice['eligible'] ?? null );
		$notice_id       = trim( (string) ( $notice['id'] ?? '' ) );
		if ( ! $eligible || null === $granted_credits || $granted_credits <= 0 || '' === $notice_id ) {
			return null;
		}

		$state_key = $this->state_store->fingerprint_identifier( 'grant|' . $notice_id );
		if ( '' === $state_key || (int) ( $scope['grantNotices'][ $state_key ]['shownAt'] ?? 0 ) > 0 ) {
			return null;
		}

		$content_version = sanitize_key( (string) ( $free_trial['contentVersion'] ?? self::POST_AUTH_CONTENT_VERSION ) );
		$content_version = '' !== $content_version ? $content_version : self::POST_AUTH_CONTENT_VERSION;

		return [
			'category' => 'grantNotices',
			'stateKey' => $state_key,
			'payload'  => [
				'type'            => 'welcome',
				'kind'            => 'welcome_connected',
				'variant'         => 'free_trial_grant',
				'priority'        => self::PRIORITY_WELCOME,
				'contentVersion' => $content_version,
				'grantedCredits' => $granted_credits,
				'connected'       => true,
				'primaryAction'   => [
					'id'  => 'open_studio',
					'url' => esc_url_raw( fotogenic_ai_get_studio_url() ),
				],
			],
		];
	}

	private function get_zero_credit_candidate(
		array $scope,
		array $credits,
		bool $has_plan,
		Auth_Session $auth
	): ?array {
		$balance = $this->get_fresh_balance( $credits );
		$episode = $scope['creditEpisode'];
		if ( null === $balance || $balance > 0 || empty( $episode['id'] ) || ! empty( $episode['zeroShown'] ) ) {
			return null;
		}

		return [
			'category' => 'creditEpisode',
			'stateKey' => (string) $episode['id'],
			'payload'  => $this->build_credit_experience_payload(
				'zero',
				self::PRIORITY_ZERO,
				$balance,
				$has_plan,
				$auth
			),
		];
	}

	private function get_low_credit_candidate(
		array $scope,
		array $credits,
		bool $has_plan,
		float $threshold,
		Auth_Session $auth
	): ?array {
		$balance = $this->get_fresh_balance( $credits );
		$episode = $scope['creditEpisode'];
		if (
			null === $balance
			|| $balance <= 0
			|| $balance > $threshold
			|| empty( $episode['id'] )
			|| ! empty( $episode['lowShown'] )
			|| ! empty( $episode['zeroShown'] )
		) {
			return null;
		}

		return [
			'category' => 'creditEpisode',
			'stateKey' => (string) $episode['id'],
			'payload'  => $this->build_credit_experience_payload(
				'low',
				self::PRIORITY_LOW,
				$balance,
				$has_plan,
				$auth
			),
		];
	}

	private function build_credit_experience_payload(
		string $type,
		int $priority,
		float $balance,
		bool $has_plan,
		Auth_Session $auth
	): array {
		$manage_url    = $this->get_safe_fotogenic_url( $auth->get_manage_url(), self::DEFAULT_MANAGE_URL );
		$pricing_url   = $this->get_safe_fotogenic_url( $auth->get_pricing_url(), self::DEFAULT_PRICING_URL );
		$action_id     = $has_plan ? 'add_credits' : 'view_plans';
		$action_url    = $has_plan ? $manage_url : $pricing_url;
		$secondary_id  = $has_plan ? 'view_plans' : 'add_credits';
		$secondary_url = $has_plan ? $pricing_url : $manage_url;

		return [
			'type'            => $type,
			'kind'            => $type,
			'variant'         => $type . '_credits',
			'priority'        => $priority,
			'contentVersion'  => self::CREDIT_CONTENT_VERSION,
			'balance'         => $balance,
			'hasPlan'         => $has_plan,
			'primaryAction'   => [
				'id'  => $action_id,
				'url' => $action_url,
			],
			'secondaryAction' => [
				'id'  => $secondary_id,
				'url' => $secondary_url,
			],
		];
	}

	private function mark_scope_shown( array $scope, string $claim_id, int $shown_at, array $candidate ): array {
		$category  = (string) $candidate['category'];
		$state_key = sanitize_key( (string) $candidate['stateKey'] );
		$payload   = $candidate['payload'];

		if ( 'welcomeOffers' === $category || 'grantNotices' === $category ) {
			$scope[ $category ][ $state_key ] = [
				'contentVersion' => sanitize_key( (string) ( $payload['contentVersion'] ?? '' ) ),
				'credits'        => $this->normalize_non_negative_number( $payload['grantedCredits'] ?? null ),
				'shownAt'        => $shown_at,
				'claimId'        => $claim_id,
				'outcome'        => '',
				'dismissedAt'    => 0,
			];

			return $scope;
		}

		if ( 'creditEpisode' !== $category ) {
			return $scope;
		}

		if ( 'zero' === $payload['type'] ) {
			$scope['creditEpisode']['zeroShown']   = true;
			$scope['creditEpisode']['zeroClaimId'] = $claim_id;
			$scope['creditEpisode']['lowShown']    = true;
		} else {
			$scope['creditEpisode']['lowShown']   = true;
			$scope['creditEpisode']['lowClaimId'] = $claim_id;
		}
		$scope['creditEpisode']['updatedAt'] = $shown_at;

		return $scope;
	}

	private function apply_outcome_to_scope( array $scope, string $claim_id, array $claim ): array {
		$variant   = (string) $claim['variant'];
		$state_key = sanitize_key( (string) $claim['stateKey'] );
		$outcome   = sanitize_key( (string) $claim['outcome'] );
		$dismissed = (int) $claim['dismissedAt'];

		if ( 'pre_auth_offer' === $variant && isset( $scope['welcomeOffers'][ $state_key ] ) ) {
			$scope['welcomeOffers'][ $state_key ]['outcome']     = $outcome;
			$scope['welcomeOffers'][ $state_key ]['dismissedAt'] = $dismissed;
		} elseif ( 'free_trial_grant' === $variant && isset( $scope['grantNotices'][ $state_key ] ) ) {
			$scope['grantNotices'][ $state_key ]['outcome']     = $outcome;
			$scope['grantNotices'][ $state_key ]['dismissedAt'] = $dismissed;
		} elseif ( 'low_credits' === $variant && $claim_id === (string) $scope['creditEpisode']['lowClaimId'] ) {
			$scope['creditEpisode']['lowOutcome'] = $outcome;
		} elseif ( 'zero_credits' === $variant && $claim_id === (string) $scope['creditEpisode']['zeroClaimId'] ) {
			$scope['creditEpisode']['zeroOutcome'] = $outcome;
		}

		return $scope;
	}

	private function update_credit_episode( array $episode, array $credits, float $threshold, float $rearm ): array {
		$balance = $this->get_fresh_balance( $credits );
		if ( null === $balance ) {
			return $episode;
		}

		$now             = time();
		$original        = $episode;
		$previous_update = (int) ( $episode['updatedAt'] ?? 0 );
		if ( $balance > $rearm ) {
			$recovered_at = empty( $episode['id'] ) ? (int) ( $episode['recoveredAt'] ?? 0 ) : $now;
			$episode      = $this->new_credit_episode( $balance, $threshold, $rearm );
			$episode['recoveredAt'] = $recovered_at;
		} else {
			if ( empty( $episode['id'] ) && $balance <= $threshold ) {
				$episode = $this->new_credit_episode( $balance, $threshold, $rearm, wp_generate_uuid4(), $now );
			}

			if ( $balance <= 0 ) {
				$episode['status'] = 'zero';
			} elseif ( $balance <= $threshold ) {
				$episode['status'] = 'low';
			} elseif ( ! empty( $episode['id'] ) ) {
				$episode['status'] = 'recovering';
			} else {
				$episode['status'] = 'normal';
			}
			$episode['lastBalance']    = $balance;
			$episode['threshold']      = $threshold;
			$episode['rearmThreshold'] = $rearm;
		}

		$episode['updatedAt'] = $previous_update;
		if ( $episode !== $original ) {
			$episode['updatedAt'] = $now;
		}

		return $episode;
	}

	private function new_credit_episode(
		float $balance,
		float $threshold,
		float $rearm,
		string $episode_id = '',
		int $started_at = 0
	): array {
		return [
			'id'             => $episode_id,
			'status'         => 'normal',
			'lowShown'       => false,
			'zeroShown'      => false,
			'lowClaimId'     => '',
			'zeroClaimId'    => '',
			'lowOutcome'     => '',
			'zeroOutcome'    => '',
			'lastBalance'    => $balance,
			'threshold'      => $threshold,
			'rearmThreshold' => $rearm,
			'startedAt'      => $started_at,
			'recoveredAt'    => 0,
			'updatedAt'      => 0,
		];
	}

	private function get_authoritative_credit_state(): array {
		$credits_service = Credits_Service::instance();
		$status          = $credits_service->get_status( 0 );
		if ( is_array( $status ) && 'fresh' === ( $status['provenance'] ?? '' ) ) {
			return $status;
		}

		$refreshed = $credits_service->refresh( 0 );
		if ( is_array( $refreshed ) ) {
			return $refreshed;
		}

		$status = $credits_service->get_status( 0 );
		if ( is_array( $status ) ) {
			$status['refreshError'] = true;

			return $status;
		}

		return [
			'balance'     => null,
			'hasPlan'     => null,
			'provenance'  => 'unavailable',
			'fetchedAt'   => null,
			'ttlSeconds'  => Credits_Service::TTL_SECONDS,
		];
	}

	private function get_authoritative_free_trial( array $credits, array $config ): array {
		$credits_service = Credits_Service::instance();
		$from_config     = $credits_service->get_safe_free_trial_data( $config );
		$from_credits    = isset( $credits['freeTrial'] ) && is_array( $credits['freeTrial'] )
			? $credits_service->get_safe_free_trial_data( [ 'freeTrial' => $credits['freeTrial'] ] )
			: [];

		return array_replace_recursive( $from_config, $from_credits );
	}

	private function resolve_low_credit_threshold( array $config, bool $has_plan ): float {
		$threshold = $this->find_config_number(
			$config,
			[
				[ 'credits', 'lowThreshold' ],
				[ 'credits', 'lowCreditThreshold' ],
				[ 'creditPolicy', 'lowThreshold' ],
				[ 'creditPolicy', 'lowCreditThreshold' ],
				[ 'lowCreditThreshold' ],
			]
		);

		if ( null === $threshold || $threshold <= 0 ) {
			$prices    = Price_Service::instance()->get_status();
			$unit_cost = $this->normalize_non_negative_number( $prices['tiers']['imageGenerationHighQuality'] ?? null );
			$threshold = null !== $unit_cost && $unit_cost > 0 ? $unit_cost * ( $has_plan ? 3 : 1 ) : 1.0;
		}

		$filtered = apply_filters( 'fotogenic_ai_low_credit_threshold', $threshold, $has_plan );
		$filtered = $this->normalize_non_negative_number( $filtered );

		return null !== $filtered && $filtered > 0 ? $filtered : $threshold;
	}

	private function resolve_rearm_threshold( array $config, float $low_threshold ): float {
		$rearm = $this->find_config_number(
			$config,
			[
				[ 'credits', 'rearmThreshold' ],
				[ 'credits', 'recoveryThreshold' ],
				[ 'creditPolicy', 'rearmThreshold' ],
				[ 'creditPolicy', 'recoveryThreshold' ],
			]
		);
		$rearm = null !== $rearm ? max( $low_threshold, $rearm ) : $low_threshold;

		$filtered = apply_filters( 'fotogenic_ai_credit_rearm_threshold', $rearm, $low_threshold );
		$filtered = $this->normalize_non_negative_number( $filtered );

		return null !== $filtered ? max( $low_threshold, $filtered ) : $rearm;
	}

	private function find_config_number( array $config, array $paths ): ?float {
		foreach ( $paths as $path ) {
			$value = $config;
			foreach ( $path as $key ) {
				if ( ! is_array( $value ) || ! array_key_exists( $key, $value ) ) {
					$value = null;
					break;
				}
				$value = $value[ $key ];
			}

			$value = $this->normalize_non_negative_number( $value );
			if ( null !== $value ) {
				return $value;
			}
		}

		return null;
	}

	private function get_fresh_balance( array $credits ): ?float {
		if ( 'fresh' !== ( $credits['provenance'] ?? '' ) ) {
			return null;
		}

		return $this->normalize_non_negative_number( $credits['balance'] ?? null );
	}

	private function get_account_identity( Auth_Session $auth ): string {
		$session = $auth->get_session();
		$user_uid = trim( (string) ( $session['userUid'] ?? '' ) );
		if ( '' !== $user_uid ) {
			return 'uid|' . $user_uid;
		}

		$email = strtolower( trim( (string) ( $session['userEmail'] ?? '' ) ) );
		if ( '' !== $email ) {
			return 'email|' . $email;
		}

		$connected_at = max( 0, (int) ( $session['connectedAt'] ?? 0 ) );

		return 'connected|' . $connected_at;
	}

	private function get_safe_fotogenic_url( string $candidate, string $fallback ): string {
		$candidate = esc_url_raw( trim( $candidate ) );
		$host      = strtolower( (string) wp_parse_url( $candidate, PHP_URL_HOST ) );
		$scheme    = strtolower( (string) wp_parse_url( $candidate, PHP_URL_SCHEME ) );
		$allowed   = 'fotogenic.ai' === $host || fotogenic_ai_str_ends_with( $host, '.fotogenic.ai' );

		return 'https' === $scheme && $allowed ? $candidate : $fallback;
	}

	private function normalize_non_negative_number( $value ): ?float {
		if ( ! is_numeric( $value ) ) {
			return null;
		}

		$value = (float) $value;

		return is_finite( $value ) && $value >= 0 ? $value : null;
	}

	/** @return int|\WP_Error */
	private function resolve_current_user_id( int $requested_user_id ) {
		$current_user_id = get_current_user_id();
		if ( $current_user_id <= 0 ) {
			return new \WP_Error(
				'fotogenic_ai_experience_auth_required',
				__( 'You must be logged in to access Fotogenic experiences.', 'fotogenic-ai' ),
				[ 'status' => 401 ]
			);
		}

		if ( ( $requested_user_id > 0 && $requested_user_id !== $current_user_id ) || ! fotogenic_ai_user_can_access() ) {
			return new \WP_Error(
				'fotogenic_ai_experience_forbidden',
				__( 'You are not allowed to access Fotogenic experiences.', 'fotogenic-ai' ),
				[ 'status' => 403 ]
			);
		}

		return $current_user_id;
	}

	private function sanitize_claim_id( string $claim_id ): string {
		$claim_id = trim( $claim_id );
		if ( 1 !== preg_match( '/^[A-Za-z0-9-]{16,64}$/', $claim_id ) ) {
			return '';
		}

		return $claim_id;
	}

	private function invalid_request( string $message ): \WP_Error {
		return new \WP_Error(
			'fotogenic_ai_invalid_experience_request',
			$message,
			[ 'status' => 400 ]
		);
	}

	private function state_write_error(): \WP_Error {
		return new \WP_Error(
			'fotogenic_ai_experience_state_error',
			__( 'The experience state could not be saved. Please try again.', 'fotogenic-ai' ),
			[ 'status' => 500 ]
		);
	}
}
