<?php
/**
 * QR Code API methods.
 *
 * @package GoValid_QR
 */

defined( 'ABSPATH' ) || exit;

class GoValid_QR_API {

	/** @var GoValid_API_Client */
	private $client;

	/** @var GoValid_Cache */
	private $cache;

	public function __construct() {
		$this->client = new GoValid_API_Client();
		$this->cache  = GoValid_Cache::get_instance();
	}

	/**
	 * List QR codes.
	 *
	 * @param int    $page     Page number.
	 * @param int    $per_page Items per page.
	 * @param string $search   Search query.
	 * @return array|WP_Error
	 */
	public function list_qr_codes( int $page = 1, int $per_page = 20, string $search = '' ) {
		$cache_key = 'qr_list_' . md5( $page . $per_page . $search );
		$cached    = $this->cache->get( $cache_key );
		if ( false !== $cached ) {
			return $cached;
		}

		$query = array(
			'page'   => $page,
			'limit'  => $per_page,
			'source' => 8, // WordPress only.
		);
		if ( ! empty( $search ) ) {
			$query['search'] = $search;
		}

		$result = $this->client->get( '/api/v1/qr/', $query );
		if ( ! is_wp_error( $result ) ) {
			$this->cache->set( $cache_key, $result, 5 * MINUTE_IN_SECONDS );
		}

		return $result;
	}

	/**
	 * Get QR code detail.
	 *
	 * @param string $uuid QR code UUID.
	 * @return array|WP_Error
	 */
	public function get_qr_detail( string $uuid ) {
		$cache_key = 'qr_detail_' . $uuid;
		$cached    = $this->cache->get( $cache_key );
		if ( false !== $cached ) {
			return $cached;
		}

		$result = $this->client->get( '/api/v1/qr/' . rawurlencode( $uuid ) . '/' );
		if ( ! is_wp_error( $result ) ) {
			$this->cache->set( $cache_key, $result, 10 * MINUTE_IN_SECONDS );
		}

		return $result;
	}

	/**
	 * Create a QR code.
	 *
	 * @param string $type QR code type.
	 * @param string $name Display name.
	 * @param array  $data Additional data fields.
	 * @return array|WP_Error
	 */
	public function create_qr_code( string $type, string $name, array $data = array() ) {
		$body = array(
			'qr_type'        => $type,
			'qr_name'        => $name,
			'security_level' => isset( $data['security_level'] ) ? $data['security_level'] : 'SMART',
		);

		if ( ! empty( $data['metadata'] ) ) {
			$body['metadata'] = $data['metadata'];
		}

		// Send custom verify domain when the setting is enabled.
		if ( get_option( 'govalid_qr_custom_verify_domain', '' ) === '1' ) {
			$body['custom_verify_domain'] = home_url();
		}

		// Collect all file attachments.
		// Each entry: array( 'path' => temp path, 'name' => original filename ).
		$files = array();

		// Certificate single attachment.
		if ( ! empty( $data['attachment_path'] ) ) {
			$files['attachment'] = array(
				'path' => $data['attachment_path'],
				'name' => ! empty( $data['attachment_name'] ) ? $data['attachment_name'] : 'attachment',
			);
		}

		// Timeline entry media files.
		if ( ! empty( $data['metadata']['timeline_entries'] ) && is_array( $data['metadata']['timeline_entries'] ) ) {
			foreach ( $data['metadata']['timeline_entries'] as $i => $entry ) {
				if ( ! empty( $entry['media_path'] ) ) {
					$files[ 'timeline_media_' . $i ] = array(
						'path' => $entry['media_path'],
						'name' => ! empty( $entry['media_name'] ) ? $entry['media_name'] : 'media_' . $i,
					);
					// Remove temp path and name from metadata before sending as JSON.
					unset( $body['metadata']['timeline_entries'][ $i ]['media_path'] );
					unset( $body['metadata']['timeline_entries'][ $i ]['media_name'] );
				}
			}
		}

		// Use multipart upload if any files are present.
		if ( ! empty( $files ) ) {
			return $this->client->post_multipart( '/api/v1/qr/', $body, $files );
		}

		return $this->client->post( '/api/v1/qr/', $body );
	}

	/**
	 * Get scan analytics for a QR code.
	 *
	 * @param string $uuid QR code UUID.
	 * @return array|WP_Error
	 */
	public function get_scans( string $uuid ) {
		$cache_key = 'qr_scans_' . $uuid;
		$cached    = $this->cache->get( $cache_key );
		if ( false !== $cached ) {
			return $cached;
		}

		$result = $this->client->get( '/api/v1/qr/' . rawurlencode( $uuid ) . '/scans/' );
		if ( ! is_wp_error( $result ) ) {
			$this->cache->set( $cache_key, $result, 5 * MINUTE_IN_SECONDS );
		}

		return $result;
	}

	/**
	 * Get dashboard stats.
	 *
	 * @return array|WP_Error
	 */
	public function get_dashboard_stats() {
		$cache_key = 'dashboard_stats';
		$cached    = $this->cache->get( $cache_key );
		if ( false !== $cached ) {
			return $cached;
		}

		$result = $this->client->get( '/api/v1/dashboard/stats/' );
		if ( ! is_wp_error( $result ) ) {
			$this->cache->set( $cache_key, $result, 15 * MINUTE_IN_SECONDS );
		}

		return $result;
	}

	/**
	 * Get institution numbering patterns.
	 *
	 * @return array|WP_Error
	 */
	public function get_numbering_patterns() {
		$cache_key = 'numbering_patterns';
		$cached    = $this->cache->get( $cache_key );
		if ( false !== $cached ) {
			return $cached;
		}

		$result = $this->client->get( '/api/v1/numbering/patterns/' );
		if ( ! is_wp_error( $result ) ) {
			$this->cache->set( $cache_key, $result, 10 * MINUTE_IN_SECONDS );
		}

		return $result;
	}

	/**
	 * Generate numbers from an institution pattern.
	 *
	 * @param int $pattern_id Pattern ID.
	 * @param int $quantity   Number of IDs to generate.
	 * @return array|WP_Error
	 */
	public function generate_numbering( int $pattern_id, int $quantity = 1 ) {
		return $this->client->post( '/api/v1/numbering/generate/', array(
			'pattern_id' => $pattern_id,
			'quantity'   => $quantity,
		) );
	}

	/**
	 * Get aggregate WordPress analytics.
	 *
	 * @return array|WP_Error
	 */
	public function get_wp_analytics() {
		$cache_key = 'wp_analytics';
		$cached    = $this->cache->get( $cache_key );
		if ( false !== $cached ) {
			return $cached;
		}

		$result = $this->client->get( '/api/v1/dashboard/wp-analytics/', array( 'source' => 8 ) );
		if ( ! is_wp_error( $result ) ) {
			$this->cache->set( $cache_key, $result, 10 * MINUTE_IN_SECONDS );
		}

		return $result;
	}

	/**
	 * Get analytics for a specific QR code.
	 *
	 * @param string $uuid QR code UUID.
	 * @return array|WP_Error
	 */
	public function get_qr_analytics( string $uuid ) {
		$cache_key = 'qr_analytics_' . $uuid;
		$cached    = $this->cache->get( $cache_key );
		if ( false !== $cached ) {
			return $cached;
		}

		$result = $this->client->get( '/api/v1/qr/' . rawurlencode( $uuid ) . '/analytics/' );
		if ( ! is_wp_error( $result ) ) {
			$this->cache->set( $cache_key, $result, 5 * MINUTE_IN_SECONDS );
		}

		return $result;
	}

	/**
	 * Delete a QR code.
	 *
	 * @param string $uuid QR code UUID.
	 * @return array|WP_Error
	 */
	public function delete_qr_code( string $uuid ) {
		$result = $this->client->delete( '/api/v1/qr/' . rawurlencode( $uuid ) . '/' );

		if ( ! is_wp_error( $result ) ) {
			$this->cache->flush_prefix( 'qr_list_' );
			$this->cache->delete( 'qr_detail_' . $uuid );
		}

		return $result;
	}

	/**
	 * Get current user subscription and quota information.
	 *
	 * @return array|WP_Error
	 */
	public function get_subscription() {
		$cache_key = 'subscription_info';
		$cached    = $this->cache->get( $cache_key );
		if ( false !== $cached ) {
			return $cached;
		}

		$result = $this->client->get( '/api/v1/financial/subscription/' );
		if ( ! is_wp_error( $result ) ) {
			$this->cache->set( $cache_key, $result, 5 * MINUTE_IN_SECONDS );
		}

		return $result;
	}

	/**
	 * Get the QR code image URL (local cached path).
	 *
	 * @param string $uuid      QR code UUID.
	 * @param string $image_url Remote image URL from API.
	 * @return string Local cached URL or original URL.
	 */
	public function get_cached_image_url( string $uuid, string $image_url ): string {
		return $this->cache->get_cached_image( $uuid, $image_url );
	}
}
