<?php
/**
 * Preview Handler
 *
 * @category   WordPress_Plugin
 * @package    Common
 * @subpackage Handlers\Rest_API
 * @author     miniOrange <info@miniorange.com>
 * @license    MIT/Expat
 * @link       https://plugins.miniorange.com/woocommerce-api-product-sync-with-woocommerce-rest-apis
 */

namespace MOWCPS\Common\Handlers\Rest_API;

use WP_Error;
use MOWCPS\Common\Models\Supplier_Model;
use MOWCPS\Common\Models\Preview_Filters_Model;
use MOWCPS\Common\Models\Connection_Model;
use MOWCPS\Common\Models\Setting_Model;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Services\Preview\Preview_Service;
use MOWCPS\Common\Services\Preview\Preview_Cache_Service;
use MOWCPS\Common\Services\Logging\Supplier_Logger;
use MOWCPS\Common\Controllers\Cron_Controller;
use MOWCPS\Common\Constants\Plugin_Filters;

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

/**
 * Class Preview_Handler
 *
 * Handles preview REST API operations
 */
class Preview_Handler {

	/**
	 * Constructor
	 */
	public function __construct() {
	}

	/**
	 * Get preview products from supplier
	 *
	 * @param string $supplier_uuid Supplier UUID.
	 * @param array  $params Query parameters including page, per_page, attribute_mapping_ids.
	 * @return array|WP_Error
	 */
	public function get_preview_products( $supplier_uuid, $params = array() ) {
		$supplier = Supplier_Model::get_by_uuid( $supplier_uuid );
		if ( ! $supplier ) {
			return new WP_Error(
				Constants::ERROR_SUPPLIER_NOT_FOUND,
				Constants::MSG_SUPPLIER_NOT_FOUND,
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		$supplier_id = $supplier['id'];
		$app_type    = $supplier['app_type'] ?? '';

		$current_default_app_handler = Cron_Controller::instantiate_vendor_hook_class( $app_type );

		$ui_page     = isset( $params['page'] ) ? intval( $params['page'] ) : 1;
		$per_page    = isset( $params['per_page'] ) ? intval( $params['per_page'] ) : 25;
		$mapping_ids = isset( $params['attribute_mapping_ids'] ) ? $params['attribute_mapping_ids'] : array();

		Supplier_Logger::debug( $supplier_id, "Preview request: UI page={$ui_page}, per_page={$per_page}" );

		$preview_service = new Preview_Service( $supplier_id, $mapping_ids );
		$cache_service   = new Preview_Cache_Service( $supplier_id );

		$cached_data = $cache_service->get_paginated_from_cache( $ui_page, $per_page );

		if ( ! is_wp_error( $cached_data ) ) {
			Supplier_Logger::debug( $supplier_id, 'Returning products from cache (UI page: ' . $ui_page . ')' );

			$cached_data['columns'] = $preview_service->get_column_definitions();

			return $cached_data;
		}

		$connection = Connection_Model::get_by_supplier_id(
			$supplier_id,
			array(
				'is_primary'    => true,
				'resource_type' => 'product',
			)
		);
		if ( is_array( $connection ) && ! empty( $connection ) && isset( $connection[0]['id'] ) ) {
			$connection_type = $connection[0]['type'] ?? Constants::API_CONNECTION;
		} else {
			$connection_type = Constants::API_CONNECTION;
		}

		$file_sync_details  = Setting_Model::get_by_connection_and_operation(
			$connection[0]['id'] ?? 0,
			'file-sync',
			array( 'configuration' => true )
		);
		$is_file_connection = ( Constants::CONNECTION_TYPE_FILE === $connection_type );
		$is_file_sync       = ( '1' === ( $file_sync_details['is_active'] ?? '0' ) ) || ( Constants::FTP_CONNECTION === $connection_type ) || $is_file_connection;

		if ( ! is_wp_error( $cached_data ) ) {
			Supplier_Logger::debug( $supplier_id, 'Returning products from cache (UI page: ' . $ui_page . ')' );
			$cached_data['columns'] = $preview_service->get_column_definitions();
			return $cached_data;
		}

		if ( $is_file_connection ) {
			Supplier_Logger::debug( $supplier_id, 'FILE connection type: fetching from uploaded file' );
		} elseif ( $is_file_sync ) {
			Supplier_Logger::debug( $supplier_id, 'File-based sync: fetching large batch for deduplication' );
		} else {
			Supplier_Logger::debug( $supplier_id, 'API-based sync: fetching from API' );
		}

		$cache_metadata   = $cache_service->get_cache_metadata();
		$current_api_page = 1;

		if ( ! is_wp_error( $cache_metadata ) && isset( $cache_metadata['api_page'] ) ) {
			$current_api_page = intval( $cache_metadata['api_page'] ) + 1;
			Supplier_Logger::debug( $supplier_id, "Cache exhausted, fetching next batch: {$current_api_page}" );
		} else {
			Supplier_Logger::debug( $supplier_id, 'No cache found, fetching batch 1' );
		}

		$preview_data = apply_filters(
			Plugin_Filters::FILTER_PREVIEW_PRODUCTS_FETCH,
			array(
				'skip_default_fetch' => false,
				'products'           => array(),
				'pagination_info'    => array(),
				'supplier_id'        => $supplier_id,
				'app_type'           => $app_type,
				'current_page'       => $current_api_page,
				'mapping_ids'        => $mapping_ids,
				'is_file_sync'       => $is_file_sync,
				'is_file_connection' => $is_file_connection,
			)
		);

		if ( $preview_data['skip_default_fetch'] && ! empty( $preview_data['products'] ) ) {
			$api_products    = $preview_data['products'];
			$pagination_info = $preview_data['pagination_info'] ?? array( 'has_pagination' => true );
		} else {
			$api_products = $preview_service->fetch_products_from_api( $current_api_page );

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

			$pagination_info = $preview_service->get_pagination_info( $current_api_page );
		}

		if ( empty( $api_products ) || ! is_array( $api_products ) || 0 === count( $api_products ) ) {
			$cache_metadata = $cache_service->get_cache_metadata();
			$last_page      = 1;

			if ( ! is_wp_error( $cache_metadata ) && isset( $cache_metadata['total_products'] ) ) {
				$last_page = ceil( $cache_metadata['total_products'] / $per_page );
			}

			Supplier_Logger::debug( $supplier_id, "Source returned no products for batch {$current_api_page}. All products fetched." );

			return new WP_Error(
				'no_more_products',
				'All available products have been loaded. Showing the last page.',
				array(
					'status'        => 200,
					'last_page'     => $last_page,
					'api_exhausted' => true,
				)
			);
		}

		$formatted_products = $preview_service->format_products( $api_products );

		if ( $is_file_sync || $is_file_connection ) {
			$pagination_info['has_pagination'] = true;
			Supplier_Logger::debug( $supplier_id, 'File-based sync: forcing has_pagination=true to enable next batch fetching' );
		}

		if ( ! is_wp_error( $cache_metadata ) && $current_api_page > 1 ) {
			$cache_result = $cache_service->append_to_cache( $formatted_products, $pagination_info, $current_api_page );
			Supplier_Logger::debug( $supplier_id, 'Appended ' . count( $formatted_products ) . ' unique products to cache (after deduplication)' );
		} else {
			$metadata     = array(
				'api_page'        => $current_api_page,
				'pagination_info' => $pagination_info,
				'columns'         => $preview_service->get_column_definitions(),
			);
			$cache_result = $cache_service->save_to_cache( $formatted_products, $metadata );
			Supplier_Logger::debug( $supplier_id, 'Created new cache with ' . count( $formatted_products ) . ' unique products (after deduplication)' );
		}

		if ( is_wp_error( $cache_result ) ) {
			Supplier_Logger::debug( $supplier_id, 'ERROR: Failed to save to cache: ' . $cache_result->get_error_message() );
		}

		$result = $cache_service->get_paginated_from_cache( $ui_page, $per_page );

		if ( is_wp_error( $result ) ) {
			$total_products = count( $formatted_products );
			$total_pages    = ceil( $total_products / $per_page );
			$offset         = ( $ui_page - 1 ) * $per_page;
			$paginated      = array_slice( $formatted_products, $offset, $per_page );

			$has_more = ! empty( $pagination_info['next_page'] ) || ( $pagination_info['has_pagination'] ?? false );

			$result = array(
				'products'   => $paginated,
				'pagination' => array(
					'current_page'     => $ui_page,
					'per_page'         => $per_page,
					'total_products'   => $total_products,
					'total_pages'      => $total_pages,
					'current_api_page' => $current_api_page,
					'has_more'         => $has_more,
					'has_pagination'   => $pagination_info['has_pagination'] ?? false,
				),
				'columns'    => $preview_service->get_column_definitions(),
			);
		}

		$result['columns'] = $preview_service->get_column_definitions();

		return $result;
	}

	/**
	 * Save preview filter
	 *
	 * @param string $supplier_uuid Supplier UUID.
	 * @param array  $data Filter data including filter_skus, is_revert_mode, is_active.
	 * @return array|WP_Error
	 */
	public function save_preview_filter( $supplier_uuid, $data ) {
		$supplier = Supplier_Model::get_by_uuid( $supplier_uuid );
		if ( ! $supplier ) {
			return new WP_Error(
				Constants::ERROR_SUPPLIER_NOT_FOUND,
				Constants::MSG_SUPPLIER_NOT_FOUND,
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		$filter_data = array(
			'supplier_id'    => $supplier['id'],
			'filter_skus'    => isset( $data['filter_skus'] ) ? $data['filter_skus'] : array(),
			'is_revert_mode' => isset( $data['is_revert_mode'] ) ? (bool) $data['is_revert_mode'] : false,
			'is_active'      => isset( $data['is_active'] ) ? (bool) $data['is_active'] : false,
		);
		$result      = Preview_Filters_Model::upsert( $filter_data );

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

		return array(
			'message' => 'Preview filter saved successfully',
			'filter'  => $result,
		);
	}

	/**
	 * Get existing preview filter
	 *
	 * @param string $supplier_uuid Supplier UUID.
	 * @return array|WP_Error
	 */
	public function get_preview_filter( $supplier_uuid ) {
		$supplier = Supplier_Model::get_by_uuid( $supplier_uuid );
		if ( ! $supplier ) {
			return new WP_Error(
				Constants::ERROR_SUPPLIER_NOT_FOUND,
				Constants::MSG_SUPPLIER_NOT_FOUND,
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		$filter = Preview_Filters_Model::get_by_supplier_id( $supplier['id'] );

		if ( ! $filter ) {
			return new WP_Error(
				Constants::ERROR_RECORD_NOT_FOUND,
				'No preview filter found for this supplier',
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		return $filter;
	}

	/**
	 * Delete preview filter and cache
	 *
	 * @param string $supplier_uuid Supplier UUID.
	 * @return array|WP_Error
	 */
	public function delete_preview_filter( $supplier_uuid ) {
		$supplier = Supplier_Model::get_by_uuid( $supplier_uuid );
		if ( ! $supplier ) {
			return new WP_Error(
				Constants::ERROR_SUPPLIER_NOT_FOUND,
				Constants::MSG_SUPPLIER_NOT_FOUND,
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		$supplier_id = $supplier['id'];

		$cache_service = new Preview_Cache_Service( $supplier_id );
		$cache_service->delete_cache();

		Preview_Filters_Model::delete_by_supplier_id( $supplier_id );

		Supplier_Logger::debug( $supplier_id, 'Preview cache and filter deleted' );

		return array(
			'message' => 'Preview cache deleted successfully',
		);
	}

	/**
	 * Delete only preview cache (keep database filter)
	 *
	 * @param string $supplier_uuid Supplier UUID.
	 * @return array|WP_Error
	 */
	public function delete_preview_cache( $supplier_uuid ) {
		$supplier = Supplier_Model::get_by_uuid( $supplier_uuid );
		if ( ! $supplier ) {
			return new WP_Error(
				Constants::ERROR_SUPPLIER_NOT_FOUND,
				Constants::MSG_SUPPLIER_NOT_FOUND,
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		$supplier_id = $supplier['id'];

		$cache_service = new Preview_Cache_Service( $supplier_id );
		$cache_service->delete_cache();

		Supplier_Logger::debug( $supplier_id, 'Preview cache deleted (filter kept)' );

		return array(
			'message' => 'Preview cache deleted successfully',
		);
	}
}
