<?php

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

/**
 * Simple read-only order functionality for FinalPOS
 */

/**
 * Check if an order is read-only
 *
 * @param int|WC_Order $order Order ID or order object
 * @return bool Whether the order is read-only
 */
function finalpos_is_order_readonly( $order ) {
	// If we received an ID instead of an order object, get the order object
	if ( is_numeric( $order ) ) {
		$order = wc_get_order( $order );
		if ( ! $order ) {
			return false;
		}
	}

	// Support new and legacy meta keys
	$readonly_meta = $order->get_meta( FINALPOS_META_KEY_READONLY ) ?: $order->get_meta( FINALPOS_META_KEY_READONLY_LEGACY );
	return $readonly_meta === FINALPOS_READONLY_VALUE;
}

if ( ! function_exists( 'finalpos_is_order_woo_outlet' ) ) {
	function finalpos_is_order_woo_outlet( $order ) {
		// If we received an ID instead of an order object, get the order object
		if ( is_numeric( $order ) ) {
			$order = wc_get_order( $order );
			if ( ! $order ) {
				return false;
			}
		}

		// Support new and legacy meta keys
		$outlet_is_woo = $order->get_meta( FINALPOS_META_KEY_IS_WOO_OUTLET ) ?: $order->get_meta( FINALPOS_META_KEY_IS_WOO_OUTLET_LEGACY );
		return $outlet_is_woo === FINALPOS_READONLY_VALUE;
	}
}

/**
 * Add readonly column to orders list - support both HPOS and legacy order tables
 */
function finalpos_add_readonly_column( $columns ) {
	$new_columns = array();
	foreach ( $columns as $key => $value ) {
		if ( $key === 'order_number' ) {
			$new_columns[ $key ]     = $value;
			$new_columns['readonly'] = __( 'Read-only', 'finalpos' );
		} else {
			$new_columns[ $key ] = $value;
		}
	}
	return $new_columns;
}
// Legacy order table support
add_filter( 'manage_edit-shop_order_columns', 'finalpos_add_readonly_column' );
// HPOS order table support
add_filter( 'manage_woocommerce_page_wc-orders_columns', 'finalpos_add_readonly_column' );

/**
 * Add readonly column content - support both HPOS and legacy order tables
 */
function finalpos_add_readonly_column_content( $column, $order ) {
	if ( $column === 'readonly' ) {
		// If we received an ID instead of an order object, get the order object
		if ( is_numeric( $order ) ) {
			$order = wc_get_order( $order );
			if ( ! $order ) {
				return;
			}
		}

		if ( finalpos_is_order_readonly( $order ) ) {
			echo '<span class="finalpos-readonly-badge">' . esc_html__( 'Read-only', 'finalpos' ) . '</span>';
		}
	}
}
// Legacy order table support
add_action( 'manage_shop_order_posts_custom_column', 'finalpos_add_readonly_column_content', 10, 2 );
// HPOS order table support
add_action( 'manage_woocommerce_page_wc-orders_custom_column', 'finalpos_add_readonly_column_content', 10, 2 );

/**
 * Add admin notice for readonly orders
 */
function finalpos_add_readonly_notice() {
	$screen = get_current_screen();
	if ( ! $screen ) {
		return;
	}

	// Check if we're on an order edit page
	if ( $screen->base !== 'woocommerce_page_wc-orders' && $screen->base !== 'post' ) {
		return;
	}

	// Get order ID
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
	$order_id = isset( $_GET['id'] ) ? absint( $_GET['id'] ) : ( isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0 );
	if ( ! $order_id ) {
		return;
	}

	// Load order
	$order = wc_get_order( $order_id );
	if ( ! $order ) {
		return;
	}

	// Check readonly status and display notice
	if ( finalpos_is_order_readonly( $order ) ) {
		echo '<div class="notice notice-warning"><p><strong>' . esc_html__( 'Notice:', 'finalpos' ) . '</strong> ' . esc_html__( 'This order is read-only and cannot be modified.', 'finalpos' ) . '</p></div>';
	}
}
add_action( 'admin_notices', 'finalpos_add_readonly_notice' );

/**
 * Handle readonly action
 */
function finalpos_handle_readonly_action( $order ) {
	if ( ! current_user_can( 'edit_shop_orders' ) ) {
		return;
	}
	$order->update_meta_data( FINALPOS_META_KEY_READONLY, FINALPOS_READONLY_VALUE );

	$order->save();
	wc_add_notice( __( 'Order marked as read-only.', 'finalpos' ) );
}
add_action( 'woocommerce_order_action_make_readonly', 'finalpos_handle_readonly_action' );

/**
 * Add readonly class to order page
 */
function finalpos_add_readonly_class( $classes ) {
	global $post;

	if ( ! $post || get_post_type( $post ) !== 'shop_order' ) {
		return $classes;
	}

	$order = wc_get_order( $post->ID );
	if ( ! $order ) {
		return $classes;
	}

	if ( finalpos_is_order_readonly( $order ) ) {
		return $classes . ' readonly-order';
	}

	return $classes;
}
add_filter( 'admin_body_class', 'finalpos_add_readonly_class' );

/**
 * Add readonly class to order posts
 */
function finalpos_add_readonly_post_class( $classes ) {
	global $post;

	if ( ! $post || get_post_type( $post ) !== 'shop_order' ) {
		return $classes;
	}

	$order = wc_get_order( $post->ID );
	if ( ! $order ) {
		return $classes;
	}

	if ( finalpos_is_order_readonly( $order ) ) {
		$classes[] = 'readonly-order';
	}

	return $classes;
}
add_filter( 'post_class', 'finalpos_add_readonly_post_class' );

/**
 * Load stylesheet for readonly orders and add direct JS to apply class
 */
function finalpos_enqueue_readonly_styles() {
	// Get the current screen
	$screen = get_current_screen();

	// Only enqueue CSS on order-related pages
	if ( $screen && ( $screen->base === 'woocommerce_page_wc-orders' || $screen->post_type === 'shop_order' ) ) {
		// Enqueue the CSS
		wp_enqueue_style(
			FINALPOS_HANDLE_READONLY_ORDERS,
			plugin_dir_url( __FILE__ ) . '../assets/css/finalpos-readonly-orders.css',
			array(),
			FINALPOS_VERSION
		);
	}

	// Only run the rest of the function on specific order edit pages
	if ( ! $screen || ( $screen->base !== 'woocommerce_page_wc-orders' && $screen->base !== 'post' && $screen->post_type !== 'shop_order' ) ) {
		return;
	}

	// Get order ID
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
	$order_id = isset( $_GET['id'] ) ? absint( $_GET['id'] ) : ( isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0 );
	if ( ! $order_id ) {
		return;
	}

	// Check if order is readonly
	$order = wc_get_order( $order_id );
	if ( ! $order || ! finalpos_is_order_readonly( $order ) ) {
		return;
	}

	// Make sure jQuery is loaded
	wp_enqueue_script( 'jquery' );

	// Add inline script to directly apply the class
	wp_add_inline_script(
		'jquery',
		'
        jQuery(document).ready(function($) {
            $("body").addClass("readonly-order");
            $("#post").addClass("readonly-order");

            // Display warning
            if ($(".finalpos-readonly-notice").length === 0) {
                $(".wrap h1, .woocommerce-layout__header").after(\'<div class="finalpos-readonly-notice"><p class="finalpos-readonly-message">This order is read-only and cannot be modified.</p></div>\');
            }
        });
    '
	);
}
add_action( 'admin_enqueue_scripts', 'finalpos_enqueue_readonly_styles' );

/**
 * Prevent saving readonly orders (but allow API requests)
 */
function finalpos_prevent_readonly_save( $order_id ) {
	// Allow API requests to modify read-only orders
	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
		return;
	}

	if ( finalpos_is_order_readonly( $order_id ) ) {
		wp_die(
			__( 'This order is read-only and cannot be modified.', 'finalpos' ),
			__( 'Order is Read-only', 'finalpos' ),
			array( 'back_link' => true )
		);
	}
}
add_action( 'woocommerce_before_order_object_save', 'finalpos_prevent_readonly_save', 5 );

/**
 * Prevent editing order meta for readonly orders (but allow API requests)
 */
function finalpos_prevent_order_meta_update( $meta_id, $object_id, $meta_key ) {
	// Allow API requests to modify read-only orders meta
	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
		return;
	}

	if ( get_post_type( $object_id ) !== 'shop_order' ) {
		return;
	}

	if ( finalpos_is_order_readonly( $object_id ) ) {
		wp_die(
			__( 'This order is read-only and cannot be modified.', 'finalpos' ),
			__( 'Order is Read-only', 'finalpos' ),
			array( 'back_link' => true )
		);
	}
}

add_action( 'add_post_meta', 'finalpos_prevent_order_meta_update', 5, 4 );
add_action( 'delete_post_meta', 'finalpos_prevent_order_meta_update', 5, 4 );

/**
 * Prevent trashing or deleting readonly orders (but allow API requests)
 */
function finalpos_prevent_readonly_delete( $post_id ) {
	// Allow API requests to delete read-only orders
	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
		return;
	}

	if ( get_post_type( $post_id ) !== 'shop_order' ) {
		return;
	}

	if ( finalpos_is_order_readonly( $post_id ) ) {
		wp_die(
			__( 'This order is read-only and cannot be deleted.', 'finalpos' ),
			__( 'Order is Read-only', 'finalpos' ),
			array( 'back_link' => true )
		);
	}
}
add_action( 'wp_trash_post', 'finalpos_prevent_readonly_delete', 5, 1 );
add_action( 'before_delete_post', 'finalpos_prevent_readonly_delete', 5, 1 );

/**
 * Alternative approach to prevent deleting readonly orders (but allow API requests)
 * This is a more direct approach that will completely block deletion
 */
function finalpos_block_readonly_order_deletion( $post_id ) {
	// Allow API requests to delete read-only orders
	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
		return;
	}

	if ( get_post_type( $post_id ) !== 'shop_order' ) {
		return;
	}

	if ( finalpos_is_order_readonly( $post_id ) ) {
		wp_die(
			__( 'You are not authorized to delete this read-only order.', 'finalpos' ),
			__( 'Order is Read-only', 'finalpos' ),
			array( 'back_link' => true )
		);
		exit; // Ensure we stop execution
	}
}
// Use a higher priority (1) to ensure this runs before other handlers
add_action( 'wp_trash_post', 'finalpos_block_readonly_order_deletion', 1, 1 );
add_action( 'before_delete_post', 'finalpos_block_readonly_order_deletion', 1, 1 );
add_action( 'trashed_post', 'finalpos_block_readonly_order_deletion', 1, 1 );

/**
 * Disable bulk actions for readonly orders
 */
function finalpos_disable_bulk_actions_for_readonly( $actions ) {
	// Only disable bulk actions on the edit order screen when viewing a specific read-only order.
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameter for display logic.
	$post_id = isset( $_GET['post'] ) && is_numeric( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;

	if ( $post_id && finalpos_is_order_readonly( $post_id ) ) {
		if ( isset( $actions['trash'] ) ) {
			unset( $actions['trash'] );
		}
		if ( isset( $actions['delete'] ) ) {
			unset( $actions['delete'] );
		}
	}
	return $actions;
}
add_filter( 'bulk_actions-edit-shop_order', 'finalpos_disable_bulk_actions_for_readonly' );
add_filter( 'woocommerce_bulk_actions', 'finalpos_disable_bulk_actions_for_readonly' );

/**
 * Block WooCommerce order delete action (but allow API requests)
 */
function finalpos_block_wc_order_delete( $order_id ) {
	// Allow API requests to delete read-only orders
	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
		return;
	}

	if ( finalpos_is_order_readonly( $order_id ) ) {
		wp_die(
			__( 'This order is read-only and cannot be deleted.', 'finalpos' ),
			__( 'Order is Read-only', 'finalpos' ),
			array( 'back_link' => true )
		);
	}
}
add_action( 'woocommerce_before_delete_order', 'finalpos_block_wc_order_delete', 1 );
add_action( 'woocommerce_before_trash_order', 'finalpos_block_wc_order_delete', 1 );


function finalpos_unhook_stock_handlers_for_readonly( $order ) {
	$order_id = is_numeric( $order ) ? absint( $order ) : ( $order instanceof WC_Order ? $order->get_id() : 0 );

	if ( ! $order_id || ! finalpos_is_order_readonly( $order_id ) || ( function_exists( 'finalpos_is_order_woo_outlet' ) && finalpos_is_order_woo_outlet( $order_id ) ) ) {
		return; // Not a read-only order – leave WooCommerce behaviour untouched. Or if it's a Woo Outlet order in which case we DO expect stock to be adjusted.
	}

	$reduce_hooks = array(
		'woocommerce_payment_complete',
		'woocommerce_order_status_on-hold',
		'woocommerce_order_status_processing',
		'woocommerce_order_status_completed',
	);

	$increase_hooks = array(
		'woocommerce_order_status_cancelled',
		'woocommerce_order_status_pending',
	);

	$current = current_filter();

	if ( in_array( $current, $reduce_hooks, true ) ) {
		remove_action( $current, 'wc_maybe_reduce_stock_levels', 10 );
	}

	if ( in_array( $current, $increase_hooks, true ) ) {
		remove_action( $current, 'wc_maybe_increase_stock_levels', 10 );
	}

	add_filter( 'woocommerce_can_restock_refunded_items', '__return_false', 99 );
}

$stock_events = array(
	// Events that normally REDUCE stock.
	'woocommerce_payment_complete',
	'woocommerce_order_status_on-hold',
	'woocommerce_order_status_processing',
	'woocommerce_order_status_completed',

	// Events that normally INCREASE stock.
	'woocommerce_order_status_cancelled',
	'woocommerce_order_status_pending',
);

foreach ( $stock_events as $event ) {
	add_action( $event, 'finalpos_unhook_stock_handlers_for_readonly', 1, 1 );
}

/**
 * Get a FinalPOS order meta value with fallback to stringified summary
 *
 * @param WC_Order $order The order object
 * @param string   $meta_key The primary meta key to check
 * @param string   $summary_key The key in the stringified summary JSON
 * @return float The meta value or 0
 */
function finalpos_get_order_meta_with_fallback( $order, $meta_key, $summary_key ) {
	$value = $order->get_meta( $meta_key ) ?? 0;

	if ( empty( $value ) ) {
		$summary_meta = $order->get_meta( FINALPOS_META_KEY_STRINGIFIED_SUMMARY ) ?: $order->get_meta( FINALPOS_META_KEY_STRINGIFIED_SUMMARY_LEGACY );

		if ( ! empty( $summary_meta ) ) {
			$summary = json_decode( $summary_meta, true );
			$value   = isset( $summary[ $summary_key ] ) ? floatval( $summary[ $summary_key ] ) : 0;
		}
	}

	return floatval( $value );
}

add_action( 'woocommerce_rest_insert_shop_order', 'finalpos_force_total', PHP_INT_MAX, 3 );
add_action( 'woocommerce_rest_insert_shop_order_object', 'finalpos_force_total', PHP_INT_MAX, 3 );
add_action( 'woocommerce_order_after_calculate_totals', 'finalpos_force_total', PHP_INT_MAX, 2 );

/**
 * Force the total of the order to be the finalpos order total
 *
 * @param WC_Order $order The order object
 * @return void
 */
function finalpos_force_total( $order ) {
	if ( is_a( $order, 'WC_Order' ) && finalpos_is_order_readonly( $order ) ) {
		$finalpos_order_total = finalpos_get_order_meta_with_fallback( $order, FINALPOS_META_KEY_ORDER_TOTAL, 'total' );

		if ( ! empty( $finalpos_order_total ) ) {
			$order->set_total( $finalpos_order_total );
			$order->save();
		}
	}
}

add_filter( 'woocommerce_order_get_tax_totals', 'finalpos_force_taxes', 10, 2 );

/**
 * Force the taxes of the order to be the finalpos order total taxes
 *
 * @param array    $tax_totals The tax totals
 * @param WC_Order $order The order object
 * @return array The tax totals
 */
function finalpos_force_taxes( $tax_totals, $order ) {

	// Only adjust tax totals for FinalPOS read-only orders.
	if ( is_a( $order, 'WC_Order' ) && finalpos_is_order_readonly( $order ) ) {
		$total_taxes = finalpos_get_order_meta_with_fallback( $order, FINALPOS_META_KEY_ORDER_TOTAL_TAXES, 'totalTaxes' );

		// we need to keep going even if the total taxes are 0
		// we should prevent wooCommerce from apply its own taxes
		$first = true;
		foreach ( $tax_totals as $single_tax_key => $single_tax_value ) {
			if ( $first ) {
				$tax_totals[ $single_tax_key ]->amount           = $total_taxes;
				$tax_totals[ $single_tax_key ]->formatted_amount = wc_price( $total_taxes );
				$first = false;
			} else {
				$tax_totals[ $single_tax_key ]->amount           = 0;
				$tax_totals[ $single_tax_key ]->formatted_amount = wc_price( 0 );
			}
		}
		foreach ( $order->get_items() as $item ) {
			if ( is_callable( array( $item, 'set_taxes' ) ) ) {
				$item->set_taxes(
					array(
						'total'    => array(),
						'subtotal' => array(),
					)
				);
			}

			if ( is_callable( array( $item, 'set_tax_total' ) ) ) {
				$item->set_total_tax( null );
			}

			if ( is_callable( array( $item, 'set_subtotal_tax' ) ) ) {
				$item->set_subtotal_tax( null );
			}

			$item->save();
		}
		foreach ( $order->get_items( 'tax' ) as $tax_item_id => $tax_item ) {
			$order->remove_item( $tax_item_id );
		}
				$new_tax = new WC_Order_Item_Tax();
				$new_tax->set_rate_id( 0 );
				$new_tax->set_label( 'Finalpos Total Tax' );
				$new_tax->set_compound( false );
				$new_tax->set_tax_total( $total_taxes );
				$new_tax->set_shipping_tax_total( 0 );
				$order->add_item( $new_tax );

				$order->set_cart_tax( null );
				$order->set_shipping_tax( null );

	}

	return $tax_totals;
}
