<?php
/**
 * Google Merchant Feed REST API
 *
 * Provides REST API endpoints for Google Merchant feeds.
 *
 * @package GGM_Commerce
 * @since 1.0.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class GGM_Commerce_Google_Merchant_REST_API
 *
 * Handles REST API endpoints for serving and managing feeds.
 */
class GGM_Commerce_Google_Merchant_REST_API {

	/**
	 * API namespace.
	 *
	 * @var string
	 */
	private $namespace = 'ggm-commerce/v1';

	/**
	 * Singleton instance.
	 *
	 * @var GGM_Commerce_Google_Merchant_REST_API|null
	 */
	private static $instance = null;

	/**
	 * Get singleton instance.
	 *
	 * @return GGM_Commerce_Google_Merchant_REST_API
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Private constructor for singleton.
	 */
	private function __construct() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	/**
	 * Register REST API routes.
	 */
	public function register_routes() {
		// Public feed endpoint (for Google to fetch).
		register_rest_route(
			$this->namespace,
			'/google-feed/(?P<feed_id>[a-z0-9-]+)',
			array(
				'methods'             => 'GET',
				'callback'            => array( $this, 'serve_feed' ),
				'permission_callback' => '__return_true', // Public access for Google.
				'args'                => array(
					'feed_id' => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
				),
			)
		);

		// Admin endpoints (require authentication).
		register_rest_route(
			$this->namespace,
			'/google-feed/(?P<feed_id>[a-z0-9-]+)/regenerate',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'regenerate_feed' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
				'args'                => array(
					'feed_id' => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
				),
			)
		);

		// Get feed status.
		register_rest_route(
			$this->namespace,
			'/google-feed/(?P<feed_id>[a-z0-9-]+)/status',
			array(
				'methods'             => 'GET',
				'callback'            => array( $this, 'get_feed_status' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
				'args'                => array(
					'feed_id' => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
				),
			)
		);

		// Get validation report.
		register_rest_route(
			$this->namespace,
			'/google-feed/(?P<feed_id>[a-z0-9-]+)/validate',
			array(
				'methods'             => 'GET',
				'callback'            => array( $this, 'validate_feed' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
				'args'                => array(
					'feed_id' => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
				),
			)
		);

		// List all feeds.
		register_rest_route(
			$this->namespace,
			'/google-feeds',
			array(
				'methods'             => 'GET',
				'callback'            => array( $this, 'list_feeds' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
			)
		);

		// Create feed.
		register_rest_route(
			$this->namespace,
			'/google-feeds',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'create_feed' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
			)
		);

		// Update feed.
		register_rest_route(
			$this->namespace,
			'/google-feed/(?P<feed_id>[a-z0-9-]+)',
			array(
				'methods'             => 'PUT',
				'callback'            => array( $this, 'update_feed' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
				'args'                => array(
					'feed_id' => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
				),
			)
		);

		// Delete feed.
		register_rest_route(
			$this->namespace,
			'/google-feed/(?P<feed_id>[a-z0-9-]+)',
			array(
				'methods'             => 'DELETE',
				'callback'            => array( $this, 'delete_feed' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
				'args'                => array(
					'feed_id' => array(
						'required'          => true,
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
				),
			)
		);
	}

	/**
	 * Check admin permission.
	 *
	 * @return bool
	 */
	public function check_admin_permission() {
		return current_user_can( 'manage_options' );
	}

	/**
	 * Serve a feed (public endpoint for Google).
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function serve_feed( $request ) {
		$feed_id = $request->get_param( 'feed_id' );

		// Check if feature is activated.
		if ( ! GGM_Commerce_Google_Merchant_Feed::is_activated() ) {
			return new WP_Error(
				'feature_not_activated',
				__( 'Google Merchant Feed feature is not activated.', 'ggm-commerce' ),
				array( 'status' => 403 )
			);
		}

		$feed_manager = GGM_Commerce_Google_Merchant_Feed_Manager::instance();
		$feed         = $feed_manager->get_feed( $feed_id );

		if ( ! $feed ) {
			return new WP_Error(
				'feed_not_found',
				__( 'Feed not found.', 'ggm-commerce' ),
				array( 'status' => 404 )
			);
		}

		// Check if feed is active.
		if ( 'paused' === $feed['status'] ) {
			return new WP_Error(
				'feed_paused',
				__( 'This feed is currently paused.', 'ggm-commerce' ),
				array( 'status' => 503 )
			);
		}

		$file_path = $feed_manager->get_feed_file_path( $feed_id );

		// If file doesn't exist or is old, regenerate.
		if ( ! file_exists( $file_path ) ) {
			$generator = GGM_Commerce_Google_Merchant_Feed::instance();
			$result    = $generator->generate_feed( $feed_id );

			if ( is_wp_error( $result ) ) {
				return $result;
			}
		}

		// Read and serve the file.
		$xml = file_get_contents( $file_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents

		if ( false === $xml ) {
			return new WP_Error(
				'read_error',
				__( 'Failed to read feed file.', 'ggm-commerce' ),
				array( 'status' => 500 )
			);
		}

		// Serve raw XML directly (bypassing WP_REST_Response JSON encoding).
		header( 'Content-Type: application/xml; charset=utf-8' );
		header( 'Cache-Control: public, max-age=3600' );
		echo $xml; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- XML content is generated by us
		exit;
	}

	/**
	 * Regenerate a feed.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function regenerate_feed( $request ) {
		$feed_id = $request->get_param( 'feed_id' );

		if ( ! GGM_Commerce_Google_Merchant_Feed::is_activated() ) {
			return new WP_Error(
				'feature_not_activated',
				__( 'Google Merchant Feed feature is not activated.', 'ggm-commerce' ),
				array( 'status' => 403 )
			);
		}

		$generator = GGM_Commerce_Google_Merchant_Feed::instance();
		$validator = GGM_Commerce_Google_Merchant_Validator::instance();
		$validator->reset();
		$generator->set_validator( $validator );

		$result = $generator->generate_feed( $feed_id );

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		$feed_manager = GGM_Commerce_Google_Merchant_Feed_Manager::instance();

		return new WP_REST_Response(
			array(
				'success'       => true,
				'message'       => __( 'Feed regenerated successfully.', 'ggm-commerce' ),
				'product_count' => $result['product_count'],
				'error_count'   => $result['error_count'],
				'feed_url'      => $feed_manager->get_feed_url( $feed_id ),
			)
		);
	}

	/**
	 * Get feed status.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function get_feed_status( $request ) {
		$feed_id = $request->get_param( 'feed_id' );

		$feed_manager = GGM_Commerce_Google_Merchant_Feed_Manager::instance();
		$feed         = $feed_manager->get_feed( $feed_id );

		if ( ! $feed ) {
			return new WP_Error(
				'feed_not_found',
				__( 'Feed not found.', 'ggm-commerce' ),
				array( 'status' => 404 )
			);
		}

		$file_path   = $feed_manager->get_feed_file_path( $feed_id );
		$file_exists = file_exists( $file_path );
		$file_size   = $file_exists ? filesize( $file_path ) : 0;

		return new WP_REST_Response(
			array(
				'feed'        => $feed,
				'feed_url'    => $feed_manager->get_feed_url( $feed_id ),
				'file_exists' => $file_exists,
				'file_size'   => $file_size,
			)
		);
	}

	/**
	 * Validate a feed (pre-generation check).
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function validate_feed( $request ) {
		$feed_id = $request->get_param( 'feed_id' );

		$feed_manager = GGM_Commerce_Google_Merchant_Feed_Manager::instance();
		$feed         = $feed_manager->get_feed( $feed_id );

		if ( ! $feed ) {
			return new WP_Error(
				'feed_not_found',
				__( 'Feed not found.', 'ggm-commerce' ),
				array( 'status' => 404 )
			);
		}

		$generator = GGM_Commerce_Google_Merchant_Feed::instance();
		$validator = GGM_Commerce_Google_Merchant_Validator::instance();

		// Get products for this feed.
		$products = $generator->get_products_for_feed( $feed );

		// Run batch validation.
		$report = $validator->validate_products_batch( $products );

		// Add detailed lists.
		$report['products_with_errors']   = $validator->get_products_with_errors_details( 20 );
		$report['products_with_warnings'] = $validator->get_products_with_warnings_details( 20 );

		return new WP_REST_Response( $report );
	}

	/**
	 * List all feeds.
	 *
	 * @return WP_REST_Response
	 */
	public function list_feeds() {
		$feed_manager = GGM_Commerce_Google_Merchant_Feed_Manager::instance();
		$feeds        = $feed_manager->get_feeds();

		// Add URLs to each feed.
		foreach ( $feeds as $feed_id => &$feed ) {
			$feed['url'] = $feed_manager->get_feed_url( $feed_id );
		}

		return new WP_REST_Response(
			array(
				'feeds'     => $feeds,
				'activated' => GGM_Commerce_Google_Merchant_Feed::is_activated(),
			)
		);
	}

	/**
	 * Create a new feed.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function create_feed( $request ) {
		$data = $request->get_json_params();

		if ( empty( $data['name'] ) ) {
			return new WP_Error(
				'missing_name',
				__( 'Feed name is required.', 'ggm-commerce' ),
				array( 'status' => 400 )
			);
		}

		$feed_manager = GGM_Commerce_Google_Merchant_Feed_Manager::instance();
		$result       = $feed_manager->create_feed( $data );

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		return new WP_REST_Response(
			array(
				'success' => true,
				'feed'    => $result,
				'url'     => $feed_manager->get_feed_url( $result['id'] ),
			),
			201
		);
	}

	/**
	 * Update a feed.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function update_feed( $request ) {
		$feed_id = $request->get_param( 'feed_id' );
		$data    = $request->get_json_params();

		$feed_manager = GGM_Commerce_Google_Merchant_Feed_Manager::instance();
		$result       = $feed_manager->update_feed( $feed_id, $data );

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		return new WP_REST_Response(
			array(
				'success' => true,
				'feed'    => $result,
			)
		);
	}

	/**
	 * Delete a feed.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function delete_feed( $request ) {
		$feed_id = $request->get_param( 'feed_id' );

		$feed_manager = GGM_Commerce_Google_Merchant_Feed_Manager::instance();
		$result       = $feed_manager->delete_feed( $feed_id );

		if ( ! $result ) {
			return new WP_Error(
				'delete_failed',
				__( 'Failed to delete feed.', 'ggm-commerce' ),
				array( 'status' => 500 )
			);
		}

		return new WP_REST_Response(
			array(
				'success' => true,
				'message' => __( 'Feed deleted successfully.', 'ggm-commerce' ),
			)
		);
	}
}
