<?php

namespace CommerceBird\API;

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

use WP_REST_Response;
use WP_REST_Server;
use WP_REST_Controller;
use WP_REST_Request;
use ReflectionClass;
use WP_Query;
use WC_Product;

class Exact extends WP_REST_Controller {

	protected $prefix    = 'wc/v3';
	protected $rest_base = 'exact-webhooks';

	public function __construct() {

		register_rest_route(
			$this->prefix,
			'/' . $this->rest_base . '/process/',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'process_webhook' ),
				'permission_callback' => function () {
					return current_user_can( 'manage_woocommerce' );
				},
			)
		);
	}

	public function process_webhook( WP_REST_Request $request ) {
		// $fd = fopen( __DIR__ . '/debug_exact_webhook.txt', 'a+' );
		// Access the protected body property using reflection.
		$reflection = new ReflectionClass( $request );
		$property   = $reflection->getProperty( 'body' );
		// $property->setAccessible( true );
		$body = $property->getValue( $request );
		// Decode the JSON body.
		$data = json_decode( $body, true );
		// fwrite( $fd, print_r( $data, true ) . "\n" );
		// fclose( $fd );

		if ( empty( $data ) ) {
			return new WP_REST_Response( 'Invalid JSON data', 400 );
		}

		// use php switch case to handle different webhook types. e.g. Invoice, Item and StockPositions.
		// code starts here.
		switch ( $data['type'] ) {
			case 'Items':
				// process Item webhook. Find the product based on the $data['Code'] which is the sku or post_id.
				$args        = array(
					'limit'  => 1,
					'sku'    => $data['Code'],
					'status' => array( 'publish', 'draft', 'pending', 'private' ),
					'type'   => array( 'simple', 'variable', 'variation' ),
					'return' => 'ids',
				);
				$product_ids = wc_get_products( $args );
				$product_id  = $product_ids ? $product_ids[0] : null;
				// Check if category exists with $item['ItemGroupDescription'], else create it and get the ID.
				if ( isset( $data['ItemGroupDescription'] ) ) {
					$term    = get_term_by( 'name', $data['ItemGroupDescription'], 'product_cat' );
					$term_id = $term->term_id;
					if ( empty( $term_id ) ) {
						$term    = wp_insert_term(
							$data['ItemGroupDescription'],
							'product_cat',
							array(
								'parent' => 0,
							)
						);
						$term_id = $term['term_id'];
					}
				} else {
					$term_id = 0;
				}
				$product = wc_get_product( $product_id );
				if ( $product ) {
					$product->set_name( $data['Description'] );
					$product->set_stock_quantity( $data['Stock'] );
					// update the product price if needed.
					$product->set_price( $data['StandardSalesPrice'] );
					$product->set_regular_price( $data['StandardSalesPrice'] );
					if ( $data['Stock'] > 0 ) {
						$product->set_manage_stock( true );
						$product->set_stock_quantity( $data['Stock'] );
						$product->set_stock_status( 'instock' );
					} else {
						$stock_status = $product->backorders_allowed() ? 'onbackorder' : 'outofstock';
						$product->set_stock_status( $stock_status );
					}
					// add meta data cost_price.
					$product->update_meta_data( '_cogs_total_value', $data['CostPriceStandard'] );
					// set the category.
					$product->set_category_ids( array_map( 'intval', array( $term_id ) ) );
					$product->save();
					// Clear cache.
					wc_delete_product_transients( $product_id );
				} else {
					// if product not found, create a new product if the $data['Webshop'] is set to true.
					if ( 0 === $data['IsWebshopItem'] ) {
						return new WP_REST_Response( 'Product is not a webshop item', 404 );
					}
					$product = new WC_Product();
					$product->set_name( $data['Description'] );
					$product->set_sku( $data['Code'] );
					$product->set_price( $data['StandardSalesPrice'] );
					$product->set_regular_price( $data['StandardSalesPrice'] );
					if ( $data['Stock'] > 0 ) {
						$product->set_manage_stock( true );
						$product->set_stock_quantity( $data['Stock'] );
						$product->set_stock_status( 'instock' );
					}
					// set the category.
					$product->set_category_ids( array_map( 'intval', array( $term_id ) ) );
					$status = get_option( 'cmbird_enable_eo_webhook_publish', false ) ? 'publish' : 'draft';
					$product->set_status( $status );
					$product->save();
				}
				break;
			case 'StockPositions':
				// process StockPositions webhook.
				// get the "ItemId" from $data['ItemId'] and find the product based on product meta key "eo_item_id".
				$item_id = $data['ItemId'];
				// find the product id based on meta key "eo_item_id" which has the value of $item_id using WP query.
				$args  = array(
					'post_type'              => array( 'product', 'product_variation' ),
					'post_status'            => array( 'publish', 'draft', 'pending', 'private' ),
					'posts_per_page'         => -1,
					'fields'                 => 'ids',
					'no_found_rows'          => true,
					'update_post_meta_cache' => false,
					'update_post_term_cache' => false,
					'meta_query'             => array(
						array(
							'key'   => 'eo_item_id',
							'value' => (string) $item_id,
						),
					),
				);
				$query = new WP_Query( $args );

				if ( ! empty( $query->posts ) ) {
					foreach ( $query->posts as $product_id ) {
						$product = wc_get_product( $product_id );
						if ( ! $product ) {
							continue;
						}
						$product->set_manage_stock( true );
						$product->set_stock_quantity( absint( $data['FreeStock'] ?? 0 ) );
						$product->set_stock_status(
							$product->get_stock_quantity() > 0
								? 'instock'
								: ( $product->backorders_allowed() ? 'onbackorder' : 'outofstock' )
						);
						$product->save();
						wc_delete_product_transients( $product_id );
					}
				}
				break;
			default:
				// process default webhook.
				break;
		}
		// code ends here.
		return new WP_REST_Response( 'Webhook processed', 200 );
	}
}
