<?php

/**
 * REST Class
 *
 * @package ApproveOrders
 * @since 1.0.4
 */

namespace ApproveOrders;

use ApproveOrders\Traits\Get_Instance;
use ApproveOrders\Helper;

class Rest_API extends \WP_REST_Controller {

	use Get_Instance;

	protected $namespace = 'aofwc-api';
	protected $rest_base = 'action';
	protected $option    = 'aofwc-rules';
	protected $response  = array(
		'success' => false,
		'message' => 'Error Processing data!',
	);

	/**
	 * Init REST API
	 *
	 * @return void
	 */
	public function __construct() {
		// Init API Routes
		add_action( 'rest_api_init', array( $this, 'init_admin' ) );
	}

	/**
	 * Init REST API Admin
	 *
	 * @return void
	 */
	public function init_admin() {

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/save-settings',
			array(
				array(
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'save_settings' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
					'args'                => array(
						'settings' => array(
							'description'       => __( 'Plugin settings', 'approve-orders' ),
							'type'              => 'json',
							'validate_callback' => 'rest_validate_request_arg',
							'sanitize_callback' => array( $this, 'sanitize_request' ),
						),
					),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/reset-settings',
			array(
				array(
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'reset_settings' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
					'args'                => array(
						'settings' => array(
							'description'       => __( 'Plugin settings', 'approve-orders' ),
							'type'              => 'json',
							'validate_callback' => 'rest_validate_request_arg',
							'sanitize_callback' => array( $this, 'sanitize_request' ),
						),
					),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/fetch-product',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'fetch_products' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
					'args'                => array(
						'term' => array(
							'description'       => __( 'Term', 'approve-orders' ),
							'type'              => 'json',
							'validate_callback' => 'rest_validate_request_arg',
							'sanitize_callback' => array( $this, 'sanitize_request' ),
						),
					),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/tyrules/save',
			array(
				array(
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'save_rules' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
					'args'                => array(
						'settings' => array(
							'description'       => __( 'Thank You Rules', 'wc-thanks-redirect' ),
							'type'              => 'json',
							'validate_callback' => 'rest_validate_request_arg',
							'sanitize_callback' => array( $this, 'sanitize_request' ),
						),
					),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/tyrules/fetch',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'fetch_rules' ),
					'permission_callback' => '__return_true',
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/tyrules/search-product',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'search_product' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/tyrules/search-category',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'search_category' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/tyrules/search-tag',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'search_tags' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/tyrules/products/details',
			array(
				array(
					'methods'             => \WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'product_details' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/tyrules/post/terms',
			array(
				array(
					'methods'             => \WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'get_postterms' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/tyrules/search-users',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'search_users' ),
					'permission_callback' => array( $this, 'get_write_api_permission_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			$this->rest_base . '/export/manager-meta',
			array(
				array(
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'export_manager_meta' ),
					'permission_callback' => function () {
						return current_user_can( 'list_users' );
					},
					'args'                => array(
						'fprmat' => array(
							'description'       => __( 'Format for file generation', 'approve-orders' ),
							'type'              => 'string',
							'validate_callback' => 'rest_validate_request_arg',
							'sanitize_callback' => array( $this, 'sanitize_request' ),
						),
					),
				),
			)
		);
	}

	/**
	 * Fetch Products
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function fetch_products( \WP_REST_Request $request ) {

		$default_settings = \WPOWP\WPOWP_Admin::get_instance()->get_settings( '', true );
		$posted_data      = $this->sanitize_clean( $request->get_param( 'settings' ) );
		$settings         = wp_parse_args( $posted_data, $default_settings );

		WPOWP_Admin::get_instance()->set_option( 'wpowp_settings', ( $settings ) );

		$this->response['success'] = true;
		$this->response['message'] = __( 'Settings Saved', 'approve-orders' );

		return rest_ensure_response( $this->response );
	}

	/**
	 * Sanitize Request
	 *
	 * @param $data
	 *
	 * @return mixed
	 */
	public function sanitize_request( $data, $skip_clean = 0 ) {
		return ( 0 === $skip_clean ) ? json_decode( $data, true ) : wc_clean( json_decode( $data, true ) );
	}

	/**
	 * Sanitize Clean
	 *
	 * @param $posted_data
	 *
	 * @return array|mixed|string
	 */
	private function sanitize_clean( $posted_data ) {
		$data = array();
		if ( is_array( $posted_data ) ) {
			foreach ( $posted_data as $post_array ) {
				$data[ str_replace( WPOWP_FORM_PREFIX, '', $post_array['name'] ) ] = sanitize_text_field( $post_array['value'] );
			}
			return $data;
		} else {
			return sanitize_text_field( $data );
		}
	}

	/**
	 * Save Rules
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function save_rules( \WP_REST_Request $request ) {

		$posted_data = $request->get_params();
		$tyrules     = isset( $posted_data['rules'] ) ? $posted_data['rules'] : '';

		update_option( $this->option, $tyrules );

		return new \WP_REST_Response( $tyrules, 200 );
	}

	/**
	 * Search Product
	 *
	 * @return array
	 */
	public function search_product() {

		$keyword         = isset( $_GET['search'] ) ? sanitize_text_field( $_GET['search'] ) : ''; // phpcs:ignore
		$variations_only = isset( $_GET['variations_only'] ) ? sanitize_text_field( $_GET['variations_only'] ) : false; // phpcs:ignore

		$products = Helper::search_product( $keyword, $variations_only );
		return $products;
	}

	/**
	 * Search Category
	 *
	 * @return array
	 */
	public function search_category() {

		$keyword   = isset( $_GET['search'] ) ? sanitize_text_field( $_GET['search'] ) : ''; //phpcs:ignore
		$post_type = isset( $_GET['post_type'] ) ? sanitize_text_field( $_GET['post_type'] ) : 'post'; //phpcs:ignore

		$products = Helper::search_categories( $keyword, $post_type );
		return $products;
	}

	/**
	 * Search Tag
	 *
	 * @return array
	 */
	public function search_tags() {

		$keyword   = isset( $_GET['search'] ) ? sanitize_text_field( $_GET['search'] ) : ''; // phpcs:ignore
		$post_type = isset( $_GET['post_type'] ) ? sanitize_text_field( $_GET['post_type'] ) : 'post'; // phpcs:ignore

		$products = Helper::search_tags( $keyword, $post_type );
		return $products;
	}

	/**
	 * Product Details
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function product_details( \WP_REST_Request $request ) {
		// Get the product IDs from the request
		$product_ids = $request->get_param( 'ids' );

		// Check if product_ids is provided and is an array
		if ( empty( $product_ids ) || ! is_array( $product_ids ) ) {
			return new \WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Invalid product IDs provided.',
				),
				400
			);
		}

		// Initialize an empty array to store product details
		$products = Helper::product_details( $product_ids );

		// Return the response
		return new \WP_REST_Response(
			array(
				'success' => true,
				'data'    => $products,
			),
			200
		);
	}

	/**
	 * Get Post Terms
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function get_postterms( \WP_REST_Request $request ) {
		// Get the product IDs from the request
		$term_ids = $request->get_param( 'ids' );
		$taxonomy = $request->get_param( 'taxonomy' );

		// Check if product_ids is provided and is an array
		if ( empty( $term_ids ) || ! is_array( $term_ids ) ) {
			return new \WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Invalid term IDs provided.',
				),
				400
			);
		}

		// Initialize an empty array to store product details
		$terms = Helper::term_details( $term_ids, $taxonomy );

		// Return the response
		return new \WP_REST_Response(
			array(
				'success' => true,
				'data'    => $terms,
			),
			200
		);
	}

	/**
	 * Fetch Rules
	 *
	 * @param int $rest_response
	 *
	 * @return \WP_REST_Response
	 */
	public function fetch_rules( $rest_response = 1 ) {

		$tyrules = get_option( $this->option, array() );

		if ( $rest_response ) {
			return new \WP_REST_Response( array( 'data' => $tyrules ), 200 );
		} else {
			return $tyrules;
		}
	}

	/**
	 * Search Users
	 *
	 * @return array
	 */
	public function search_users( \WP_REST_Request $request ) {

		$users       = array();
		$posted_data = $request->get_params();
		$keyword = isset( $posted_data['search'] )?$posted_data['search'] : '';  // phpcs:ignore		

		$user_lookup = isset( $posted_data['user_lookup'] ) ? sanitize_text_field( $posted_data['user_lookup'] ) : 0;

		if ( ! empty( $keyword ) ) {
			$keyword = is_array( $keyword ) ? array_map( 'sanitize_text_field', $keyword ) : sanitize_text_field( $keyword );
			$users   = Helper::search_users( $keyword, $user_lookup );
		}
		return $users;
	}

	/**
	 * Option Name
	 *
	 * @return string
	 */
	public function option_name() {
		return $this->option;
	}

	/**
	 * Check user has write permission
	 *
	 * @return void
	 */
	public function get_write_api_permission_check() {
		return current_user_can( 'manage_options' ) ? true : false;
	}

	/**
	 * Save Rules
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function export_manager_meta() {

		global $wpdb;

		// Quick check if any user exists
		$total_users = (int) $wpdb->get_var( "SELECT COUNT(ID) FROM {$wpdb->users}" ); // phpcs:ignore
		if ( $total_users === 0 ) {
			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => __( 'No users found for export.', 'approve-orders' ),
				),
				200
			);
		}

		// Setup headers for CSV
		$filename = 'users-export-' . date( 'Y-m-d-His' ) . '.csv'; // phpcs:ignore
		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
		header( 'Pragma: no-cache' );
		header( 'Expires: 0' );

		$output = fopen( 'php://output', 'w' );

		// Header row
		fputcsv( $output, array( 'User ID', 'Username', 'Email', 'Role', 'Line Manager', 'Second Approver' ) ); // phpcs:ignore

		// Cursor pagination
		$last_id = 0;
		$batch   = 5000;

		while ( true ) {
			$users = $wpdb->get_results( // phpcs:ignore
				$wpdb->prepare( "SELECT ID, user_login, user_email FROM {$wpdb->users} WHERE ID > %d ORDER BY ID ASC LIMIT %d", $last_id, $batch ) // phpcs:ignore
			);

			if ( empty( $users ) ) {
				break;
			}

			foreach ( $users as $user ) {
				$userdata = get_userdata( $user->ID );
				$roles    = $userdata ? implode( ',', $userdata->roles ) : '';

				$line_manager    = get_user_meta( $user->ID, 'line_manager', true );
				$second_approver = get_user_meta( $user->ID, 'second_approver', true );

				fputcsv( // phpcs:ignore
					$output,
					array(
						$user->ID,
						$user->user_login,
						$user->user_email,
						$roles,
						$line_manager,
						$second_approver,
					)
				);

				$last_id = $user->ID;
			}

			flush();
		}

		fclose( $output ); // phpcs:ignore
		exit;
	}
}
