<?php

namespace Fotogenic_AI;

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

final class Auth_Client {
    private const PLATFORM = 'wp';

    /** @return array|\WP_Error */
    public function start_login( string $redirect_uri, string $state, string $source = '' ) {
        $payload = [
            'redirectUri' => $redirect_uri,
            'platform'    => self::PLATFORM,
            'state'       => $state,
        ];
        if ( '' !== $source ) {
            $payload['source'] = $source;
        }

        return $this->request(
            'POST',
            '/auth/start',
            $payload
        );
    }

    /** @return array|\WP_Error */
    public function exchange_code( string $code, string $redirect_uri, string $state, string $source = '' ) {
        $payload = [
            'code'        => $code,
            'redirectUri' => $redirect_uri,
            'platform'    => self::PLATFORM,
            'state'       => $state,
        ];
        if ( '' !== $source ) {
            $payload['source'] = $source;
        }

        return $this->request(
            'POST',
            '/auth/exchange',
            $payload,
            200
        );
    }

    /** @return array|\WP_Error */
    public function refresh_session( string $refresh_token ) {
        return $this->request(
            'POST',
            '/auth/refresh',
            [
                'refreshToken' => $refresh_token,
            ],
            200
        );
    }

    /** @return array|\WP_Error */
    public function revoke_session( string $refresh_token ) {
        return $this->request(
            'POST',
            '/auth/revoke',
            [
                'platform'     => self::PLATFORM,
                'refreshToken' => $refresh_token,
            ]
        );
    }

    /** @return array|\WP_Error */
    private function request( string $method, string $endpoint, array $payload = [], ?int $expected_success_status = null ) {
        $url = $this->build_url( $endpoint );
        $headers = [
            'Accept'       => 'application/json',
            'Content-Type' => 'application/json',
        ];
        $logger = Logger::instance();
        $start  = microtime( true );

        $response = wp_remote_request(
            $url,
            [
                'method'      => strtoupper( $method ),
                'headers'     => $headers,
                'body'        => wp_json_encode( $payload ),
				'timeout'            => Workflow_Operational_Limits::AUTH_HTTP_TIMEOUT_SECONDS,
                'redirection' => 0,
                'reject_unsafe_urls' => true,
                'user-agent'  => sprintf( 'FotogenicAI/%s; WordPress/%s', FOTOGENIC_AI_VERSION, get_bloginfo( 'version' ) ),
            ]
        );

        if ( is_wp_error( $response ) ) {
            if ( $logger->enabled() ) {
                $logger->api(
                    [
                        'request_type'    => 'auth',
                        'endpoint'        => $endpoint,
                        'method'          => strtoupper( $method ),
                        'status'          => 0,
                        'duration_ms'     => (int) round( ( microtime( true ) - $start ) * 1000 ),
                        'request_meta'    => $this->build_log_request_meta( $payload ),
                        'error'           => [
                            'code'    => $response->get_error_code(),
                            'message' => $response->get_error_message(),
                        ],
                    ]
                );
                $logger->warn(
                    'auth_http_transport_failed',
                    [
                        'endpoint' => $endpoint,
                        'status'   => 0,
                    ]
                );
            }
            return Messages::error( 'request_failed', 500 );
        }

        $status = (int) wp_remote_retrieve_response_code( $response );
        $body   = trim( (string) wp_remote_retrieve_body( $response ) );
        $data   = [];

        if ( '' !== $body ) {
            $decoded = json_decode( $body, true );
            if ( is_array( $decoded ) ) {
                $data = $decoded;
            }
        }

        if ( $status >= 400 || ( null !== $expected_success_status && $expected_success_status !== $status ) ) {
            $message = $this->get_safe_http_message( $status );
            $cause   = $status >= 400 ? 'http_error' : 'unexpected_status';

            if ( $logger->enabled() ) {
                $logger->api(
                    [
                        'request_type'    => 'auth',
                        'endpoint'        => $endpoint,
                        'method'          => strtoupper( $method ),
                        'status'          => $status,
                        'duration_ms'     => (int) round( ( microtime( true ) - $start ) * 1000 ),
                        'request_meta'    => $this->build_log_request_meta( $payload ),
                        'response_message'=> $message,
                    ]
                );
                $logger->warn(
                    'auth_http_error',
                    [
                        'endpoint' => $endpoint,
                        'status'   => $status,
                    ]
                );
            }

            return new \WP_Error(
                'fotogenic_ai_auth_http_error',
                $message,
                [
                    'status' => $status,
                    'code'   => 'fotogenic_ai_auth_http_error',
                    'cause'  => $cause,
                ]
            );
        }

        if ( $logger->enabled() ) {
            $logger->api(
                [
                    'request_type' => 'auth',
                    'endpoint'     => $endpoint,
                    'method'       => strtoupper( $method ),
                    'status'       => $status,
                    'duration_ms'  => (int) round( ( microtime( true ) - $start ) * 1000 ),
                    'request_meta' => $this->build_log_request_meta( $payload ),
                ]
            );
        }

        return $data;
    }


    private function build_log_request_meta( array $payload ): array {
        return [
            'platform'        => isset( $payload['platform'] ) ? sanitize_text_field( (string) $payload['platform'] ) : '',
            'hasRedirectUri'  => ! empty( $payload['redirectUri'] ),
            'hasState'        => ! empty( $payload['state'] ),
            'hasCode'         => ! empty( $payload['code'] ),
            'hasSource'       => ! empty( $payload['source'] ),
            'hasRefreshToken' => ! empty( $payload['refreshToken'] ),
        ];
    }

    private function build_url( string $endpoint ): string {
        $settings  = Settings::instance();
        $base_url  = rtrim( $settings->get_api_base_url(), '/' );
        $base_path = trim( (string) $settings->get_api_base_path(), '/' );

        if ( '' !== $base_path ) {
            $base_url .= '/' . $base_path;
        }

        return $base_url . '/' . ltrim( $endpoint, '/' );
    }

    private function get_safe_http_message( int $status ): string {
		$messages = [
			400 => 'bad_request',
			401 => 'unauthorized',
			403 => 'forbidden',
			500 => 'server_error',
			503 => 'service_unavailable',
		];

		return Messages::t( $messages[ $status ] ?? 'unexpected_api_error' );
    }
}
