<?php

namespace Fotogenic_AI;

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

final class Service_Configuration {
    public function clear_cache(): void {
        $this->clear_cache_for_identity( Auth_Session::instance()->get_cache_identity() );
    }

    public function clear_cache_for_identity( string $identity ): void {
        delete_transient( self::get_configuration_cache_key( $identity ) );
        Config_Provider::clear_memory();
    }

	public function handle_configuration( \WP_REST_Request $request ) {
		unset( $request );
		$cache_key = self::get_configuration_cache_key();
		$cached = get_transient( $cache_key );
		if ( is_array( $cached ) && isset( $cached['data'] ) && $this->is_configuration_complete( $cached['data'] ) ) {
			return rest_ensure_response( $this->present_studio_configuration( $cached['data'] ) );
		}
        if ( is_array( $cached ) ) {
            delete_transient( $cache_key );
        }

        $response = $this->get_authoritative_configuration();
        if ( is_wp_error( $response ) ) {
            return $response;
        }
		return rest_ensure_response( $this->present_studio_configuration( $response ) );
    }

    public function handle_configuration_refresh( \WP_REST_Request $request ) {
        $this->clear_cache();

		return $this->handle_configuration( $request );
    }

    public function get_supported_selection_keys( ?array $payload = null ): array {
        $selection_ids = $this->get_selection_ids( $payload );
        if ( empty( $selection_ids ) ) {
            $cache_key = $this->get_configuration_cache_key();
            $cached = get_transient( $cache_key );
            $selection_ids = $this->get_selection_ids( $cached );
        }
        if ( empty( $selection_ids ) ) {
            return Selection_Schema::get_selection_keys();
        }
        return array_keys( $selection_ids );
    }

    public function is_configuration_complete( $payload ): bool {
        $selections = $this->get_selection_ids( is_array( $payload ) ? $payload : null );
        foreach ( Selection_Schema::get_required_keys() as $key ) {
            if ( empty( $selections[ $key ] ) ) {
                return false;
            }
        }
        return ! empty( $selections );
    }

    /**
     * Fetch and persist a configuration confirmed by the current account now.
     *
     * @return array|\WP_Error
     */
    public function get_authoritative_configuration() {
        if ( ! Auth_Session::instance()->is_connected() ) {
            return Messages::error( 'missing_auth_session', 400 );
        }

        $response = Api_Client::instance()->request( 'GET', 'configuration' );
        if ( is_wp_error( $response ) || ! is_array( $response ) || ! $this->is_configuration_complete( $response ) ) {
            return $this->configuration_unavailable();
        }

		$payload = [
			'data' => $response,
		];
        set_transient( self::get_configuration_cache_key(), $payload, 7 * DAY_IN_SECONDS );
        Config_Provider::clear_memory();

        return $response;
    }

    /**
     * Extract the exact catalog IDs accepted for each Generate selection key.
     *
     * @return array<string,string[]>
     */
    public function get_selection_ids( ?array $payload = null ): array {
        $selections = $this->extract_configuration_selections( $payload );
        $available  = [];
        foreach ( $selections as $key => $options ) {
            if ( ! is_string( $key ) || ! Selection_Schema::is_valid_key( $key ) || ! is_array( $options ) ) {
                continue;
            }
            $ids = [];
            foreach ( $options as $option ) {
                $raw = is_array( $option ) ? ( $option['id'] ?? $option['value'] ?? '' ) : $option;
                $id  = sanitize_text_field( (string) $raw );
                if ( '' !== $id && ! in_array( $id, $ids, true ) ) {
                    $ids[] = $id;
                }
            }
            if ( ! empty( $ids ) ) {
                $available[ $key ] = $ids;
            }
        }

        return $available;
    }

    /**
     * Return the Generate quality values currently allowed by the account configuration.
     *
     * The endpoint values are fixed by the current Generate Images multipart contract;
     * account access remains dynamic through the configuration free-trial policy.
     *
     * @return array<int,array{id:string,label:string}>
     */
	public function get_image_generation_quality_options( ?array $payload = null ): array {
		return $this->get_workflow_quality_options( 'product_images', $payload );
	}

	/**
	 * Return Campaign Set qualities allowed by both the API contract and account policy.
	 *
	 * @return array<int,array{id:string,label:string}>
	 */
	public function get_campaign_set_quality_options( ?array $payload = null ): array {
		return $this->get_workflow_quality_options( 'campaign_set', $payload );
	}

	/**
	 * Add the normalized server-owned Generate quality catalog to the
	 * browser-only configuration response. Internal callers continue to consume
	 * the untouched upstream configuration document.
	 */
	public function present_studio_configuration( array $configuration ): array {
		$configuration['imageGenerationQualities'] = $this->get_image_generation_quality_options( $configuration );
		$configuration['campaignSetQualities'] = $this->get_campaign_set_quality_options( $configuration );

		return $configuration;
	}

	/** @return array<int,array{id:string,label:string}> */
	private function get_workflow_quality_options( string $workflow, ?array $payload ): array {
		if ( ! is_array( $payload ) || ! $this->is_configuration_complete( $payload ) ) {
			return [];
		}

		$configuration = isset( $payload['data'] ) && is_array( $payload['data'] )
			? $payload['data']
			: $payload;
		$free_trial = isset( $configuration['freeTrial'] ) && is_array( $configuration['freeTrial'] )
			? $configuration['freeTrial']
			: [];
		$is_enrolled = true === ( $free_trial['isEnrolled'] ?? false );
		$maximum = strtolower( trim( (string) ( $free_trial['maxImageQuality'] ?? '' ) ) );
		$include_4k = ! ( $is_enrolled && in_array( $maximum, [ '2k', 'high' ], true ) );

		return Workflow_Quality_Catalog::options_for( $workflow, $include_4k );
	}

    /**
     * Return current style identifiers and browser-safe labels.
     *
     * @return array<int,array{id:string,label:string}>
     */
    public function get_style_options( ?array $payload = null ): array {
        if ( ! is_array( $payload ) || ! $this->is_configuration_complete( $payload ) ) {
            return [];
        }

        $configuration = isset( $payload['data'] ) && is_array( $payload['data'] )
            ? $payload['data']
            : $payload;
        $styles = isset( $configuration['styles'] ) && is_array( $configuration['styles'] )
            ? $configuration['styles']
            : [];
        $options = [];
        $seen = [];
        foreach ( $styles as $style ) {
            if ( ! is_array( $style ) ) {
                continue;
            }
            $id = sanitize_text_field( (string) ( $style['id'] ?? $style['value'] ?? $style['key'] ?? $style['slug'] ?? '' ) );
            if ( '' === $id || isset( $seen[ $id ] ) ) {
                continue;
            }
            $label = sanitize_text_field( (string) ( $style['label'] ?? $style['name'] ?? $style['title'] ?? $id ) );
            $seen[ $id ] = true;
            $options[] = [
                'id'    => $id,
                'label' => '' !== $label ? $label : $id,
            ];
            if ( count( $options ) >= 200 ) {
                break;
            }
        }

        return $options;
    }

    private function extract_configuration_selections( $payload ): array {
        if ( ! is_array( $payload ) ) {
            return [];
        }
        if ( isset( $payload['selections'] ) && is_array( $payload['selections'] ) ) {
            return $payload['selections'];
        }
        if ( isset( $payload['data'] ) && is_array( $payload['data'] ) && isset( $payload['data']['selections'] ) ) {
            return is_array( $payload['data']['selections'] ) ? $payload['data']['selections'] : [];
        }
        return [];
    }

    public static function get_configuration_cache_key( ?string $identity = null ): string {
        $options = Settings::instance()->get_options();
        $env = isset( $options['api_environment'] ) ? (string) $options['api_environment'] : 'production';
        $identity = null !== $identity ? sanitize_key( $identity ) : Auth_Session::instance()->get_cache_identity();
        if ( '' === $identity ) {
            $identity = 'guest';
        }
        return 'fotogenic_ai_config_' . sanitize_key( $env ) . '_' . $identity;
    }

    private function configuration_unavailable(): \WP_Error {
        return new \WP_Error(
            'fotogenic_ai_configuration_unavailable',
            __( 'Current Generate configuration is unavailable. Please refresh and try again.', 'fotogenic-ai' ),
            [ 'status' => 503 ]
        );
    }
}
