<?php
/**
 * Connection REST API Controller
 *
 * @category   WordPress_Plugin
 * @package    Common
 * @subpackage Controllers\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\Controllers\Rest_API;

use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use MOWCPS\Common\Abstracts\Base_Rest_Controller;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Handlers\Rest_API\Connection_Handler;
use MOWCPS\Common\Utils\Response_Builder;
use MOWCPS\Common\Utils\Utils;

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

/**
 * Class Connection_Rest_Controller
 *
 * Handles connection REST API callbacks
 */
class Connection_Rest_Controller extends Base_Rest_Controller {
	/**
	 * Handler instance
	 *
	 * @var Connection_Handler
	 */
	private $handler;

	/**
	 * Constructor
	 */
	public function __construct() {
		$this->handler = new Connection_Handler();
	}

	/**
	 * Get all connections for a supplier
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function get_items( $request ) {
		$supplier_uuid = sanitize_key( wp_unslash( $request->get_param( 'supplier_uuid' ) ) );
		$params        = $request->get_params();
		$connections   = $this->handler->get_all_by_supplier_uuid( $supplier_uuid, $params );

		if ( is_wp_error( $connections ) ) {
			return Response_Builder::from_wp_error( $connections );
		}

		return Response_Builder::success( $connections );
	}

	/**
	 * Get connection by UUID
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function get_item( $request ) {
		$connection_uuid = sanitize_key( wp_unslash( $request->get_param( 'connection_uuid' ) ) );

		$connection = $this->handler->get_by_uuid( $connection_uuid );

		if ( is_wp_error( $connection ) ) {
			return Response_Builder::from_wp_error( $connection );
		}

		return Response_Builder::success( $connection );
	}

	/**
	 * Create connection for a supplier
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function create_item( $request ) {
		$supplier_uuid = sanitize_key( wp_unslash( $request->get_param( 'supplier_uuid' ) ) );
		$data          = $request->get_json_params();

		// Validate priority if provided.
		if ( isset( $data['priority'] ) ) {
			$priority = intval( $data['priority'] );
			if ( $priority <= 0 ) {
				return Response_Builder::error(
					'invalid_priority',
					'Priority must be a positive integer.',
					400
				);
			}
		}

		$connection = $this->handler->create( $supplier_uuid, $data );

		if ( is_wp_error( $connection ) ) {
			return Response_Builder::from_wp_error( $connection );
		}

		return Response_Builder::success( $connection, 201 );
	}

	/**
	 * Update connection
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function update_item( $request ) {
		$connection_uuid = sanitize_key( wp_unslash( $request->get_param( 'connection_uuid' ) ) );
		$data            = $request->get_json_params();

		// Validate priority if provided.
		if ( isset( $data['priority'] ) ) {
			$priority = intval( $data['priority'] );
			if ( $priority <= 0 ) {
				return Response_Builder::error(
					'invalid_priority',
					'Priority must be a positive integer.',
					400
				);
			}
		}

		$connection = $this->handler->update( $connection_uuid, $data );

		if ( is_wp_error( $connection ) ) {
			return Response_Builder::from_wp_error( $connection );
		}

		return Response_Builder::success( $connection );
	}

	/**
	 * Delete connection
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function delete_item( $request ) {
		$connection_uuid = sanitize_key( wp_unslash( $request->get_param( 'connection_uuid' ) ) );

		$result = $this->handler->delete( $connection_uuid );

		if ( is_wp_error( $result ) ) {
			return Response_Builder::from_wp_error( $result );
		}

		return Response_Builder::deleted();
	}

	/**
	 * Test connection configuration
	 *
	 * Tests a connection based on its type. For FILE connections, accepts optional file_content
	 * in request body. For API/FTP connections, makes API calls to test connectivity.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function test_connection( $request ) {
		$connection_uuid = sanitize_key( wp_unslash( $request->get_param( 'connection_uuid' ) ) );
		$request_body    = $request->get_json_params();

		$result = $this->handler->test_connection( $connection_uuid, $request_body );

		if ( is_wp_error( $result ) ) {
			return Response_Builder::from_wp_error( $result );
		}

		// FILE connections return array directly, API/FTP connections return wp_remote response.
		if ( is_array( $result ) && ! isset( $result['body'] ) ) {
			// This is a FILE connection response (formatted file data).
			return Response_Builder::success( $result, 200 );
		}

		// This is an API/FTP connection response (wp_remote response).
		$status_code = wp_remote_retrieve_response_code( $result );

		if ( Utils::is_status_success( $result ) ) {
			return Response_Builder::success( $result['body'], $status_code );
		}

		return Response_Builder::error(
			Constants::NOT_2XX_API_RESPONSE,
			$result,
			$status_code
		);
	}

	/**
	 * Handle chunked file upload
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function chunked_upload( $request ) {
		$connection_uuid = sanitize_key( wp_unslash( $request->get_param( 'connection_uuid' ) ) );

		// Handle multipart/form-data: get form fields from request params
		$chunk_number = intval( $request->get_param( 'chunk_number' ) ?? 0 );
		$total_chunks = intval( $request->get_param( 'total_chunks' ) ?? 0 );
		$file_name    = sanitize_file_name( $request->get_param( 'file_name' ) ?? '' );
		$file_size    = intval( $request->get_param( 'file_size' ) ?? 0 );

		// Get uploaded file from $_FILES
		if ( ! isset( $_FILES['chunk_data'] ) || $_FILES['chunk_data']['error'] !== UPLOAD_ERR_OK ) {
			return Response_Builder::error(
				'chunk_upload_failed',
				'Failed to upload chunk file.',
				400
			);
		}

		$request_data = array(
			'chunk_number' => $chunk_number,
			'total_chunks' => $total_chunks,
			'file_name'    => $file_name,
			'file_size'    => $file_size,
			'chunk_file'   => $_FILES['chunk_data'], // File upload data
		);

		$result = $this->handler->handle_chunked_upload( $connection_uuid, $request_data );

		if ( is_wp_error( $result ) ) {
			return Response_Builder::from_wp_error( $result );
		}

		return Response_Builder::success( $result, 200 );
	}
}
