<?php
/**
 * Postomatic Plugin - Credit Handler class.
 *
 * PHP Version 5.6
 *
 * @package  Postomatic
 * @category Plugin
 * @license  GPL-2.0-or-later https://www.gnu.org/licenses/gpl-2.0.html
 * @link     https://buildomatics.com/postomatics
 * @since    1.0.0
 */

namespace Postomatic\Api;

use Postomatic\Constants;
use Postomatic\Utils;
use Postomatic\Core\Activator;

/**
 * Credit Handler class.
 *
 * This class handles the credit data AJAX functionality.
 *
 * @category Plugin
 * @license  GPL-2.0-or-later https://www.gnu.org/licenses/gpl-2.0.html
 * @link     https://buildomatics.com/postomatics
 * @since    1.0.0
 */
class Credit_Handler {

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'wp_ajax_postomatic_get_credits', array( $this, 'get_credits' ) );
	}



	/**
	 * Get sample credit data.
	 *
	 * This method returns sample credit data when the API is not available.
	 *
	 * @return array An array of sample credit data.
	 */
	private function get_sample_credit_data() {
		// Create sample data for credits.
		$sample_data = array();

		return $sample_data;
	}

	/**
	 * Get credits.
	 *
	 * This method returns the credit data.
	 *
	 * @return void
	 */
	public function get_credits() {
		$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
		// Check nonce for security.
		if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'postomatic_admin_nonce' ) ) {
			wp_send_json_error( 'Invalid nonce', 403 );

			return;
		}

		// Check if user has permission.
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( 'Permission denied', 403 );

			return;
		}

		// Get credit data.
		$credit_data = $this->get_credit_data();

		wp_send_json_success( $credit_data );
	}

	/**
	 * Get credits using a REST request.
	 *
	 * This method creates a mock WP_REST_Request and uses it to get credit data.
	 *
	 * @return array Credit data
	 */
	public function postomatic_get_credits() {
		// Create a mock request object.
		$request = new \WP_REST_Request( 'GET', Constants::API_CREDIT_ACCESS_CREDIT_AMOUNT_DETAILS );
		$request->set_header( 'Api-Key', Utils::get_api_service_key() );

		// Get credit data using the handle_credit_data_request method.
		$response = $this->handle_credit_data_request( $request );

		// Get the data from the response.
		if ( $response instanceof \WP_REST_Response ) {
			$data = $response->get_data();
			if ( isset( $data['data'] ) ) {
				return $data['data'];
			}

			return $data;
		}

		// Return empty data if there was an error.
		return array();
	}

	/**
	 * Handle credit request.
	 *
	 * @param  \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response The response object.
	 */
	public function handle_credit_request( $request ) {
		// Validate the API key.
		$api_key = $request->get_header( 'Api-Key' );
		if ( empty( $api_key ) || Utils::get_api_service_key() !== $api_key ) {
			return new \WP_REST_Response(
				array(
					'status'  => false,
					'message' => 'Invalid or missing API key.',
				),
				403
			);
		}

		// Get credit data.
		$credit_data = $this->get_credit_data();

		// Structure the response.
		$response = array(
			'status' => true,
			'data'   => $credit_data,
		);

		// Return the structured response.
		return new \WP_REST_Response( $response, 200 );
	}

	/**
	 * Get credit data.
	 *
	 * @return array An array of credit data.
	 */
	private function get_credit_data() {

		$default_data = array();

		// Get API key.
		$api_key = Utils::get_api_service_key();

		// Create a mock request object similar to how it's done in Languages_Handler::get_languages_data().
		$request = new \WP_REST_Request( 'GET', Constants::API_RE_ACTIVE );
		$request->set_header( 'Api-Key', $api_key );

		// Make the request.
		$response = $this->handle_credit_data_request( $request );

		// If we got a WP_Error, return default credit data.
		if ( is_wp_error( $response ) ) {
			// Log the error for debugging purposes only.
			// error_log('Postomatic Credit API Error: ' . $response->get_error_message()).
			return $default_data;
		}

		// Get the data from the response.
		$result = $response->get_data();
		// error_log('Postomatic Credit API Result: ' . print_r($result, true)).
		// Check if response is successful.
		if ( empty( $result ) || ! isset( $result['data'] ) ) {
			// Log the error for debugging purposes only.
			// error_log('Postomatic Credit API Error: Unexpected response structure').
			return $default_data;
		}

		// Ensure the result has all the expected properties.
		$credit_data = $result['data'];

		// Return the credit data.
		return $credit_data;
	}

	/**
	 * Handle credit data request.
	 *
	 * @param  \WP_REST_Request $request     The request object.
	 * @param  int              $retry_count Number of retry attempts (default: 0).
	 * @return \WP_REST_Response|\WP_Error The response object or error.
	 */
	public function handle_credit_data_request( $request, $retry_count = 0 ) {
		// Validate the API key.
		$api_key = $request->get_header( 'Api-Key' );
		if ( empty( $api_key ) || Utils::get_api_service_key() !== $api_key ) {
			return new \WP_Error(
				'invalid_api_key',
				'Invalid or missing API key.',
				array( 'status' => 403 )
			);
		}

		// Set API URL.
		$api_url = Constants::API_RE_ACTIVE;

		// Send request to API.
		$response = wp_remote_get(
			$api_url,
			array(
				'method'      => 'GET',
				'timeout'     => 45,
				'redirection' => 5,
				'httpversion' => '1.0',
				'blocking'    => true,
				'headers'     => array(
					'Content-Type' => 'application/json',
					'Api-Key'      => $api_key,
				),
				'cookies'     => array(),
			)
		);

		// Check for errors.
		if ( is_wp_error( $response ) ) {
			return $response;
		}

		// Get response code.
		$response_code = wp_remote_retrieve_response_code( $response );

		// Check for 401 Unauthorized error.
		if ( 401 === $response_code ) {
			// Call Activator::activate() to refresh the API key.
			Activator::activate();

			// Sleep for 15 seconds.
			sleep( 10 );

			// Retry up to 2 times (retry_count < 2).
			if ( $retry_count < 2 ) {
				// Update the API key in the request with the refreshed one.
				$request->set_header( 'Api-Key', Utils::get_api_service_key() );

				// Retry the request with incremented retry count.
				return $this->handle_credit_data_request( $request, $retry_count + 1 );
			}

			// If we've already retried twice, return an error.
			return new \WP_Error(
				'authorization_failed',
				esc_html__( 'Authorization failed after multiple attempts.', 'postomatic' ),
				array( 'status' => 401 )
			);
		}

		// Get response body.
		$body   = wp_remote_retrieve_body( $response );
		$result = json_decode( $body, true );

		// Check if response is successful.
		if ( 200 !== $response_code || JSON_ERROR_NONE !== json_last_error() ) {
			return new \WP_Error(
				'invalid_response',
				'Invalid response from API (code: ' . $response_code . ')',
				array( 'status' => $response_code )
			);
		}

		// Structure the response.
		$response_data = array(
			'status' => true,
			'data'   => $result,
		);

		// Return the structured response.
		return new \WP_REST_Response( $response_data, 200 );
	}
}
