<?php

namespace Fotogenic_AI\Compat\WooCommerce;

use Fotogenic_AI\Studio_Cache_Invalidator_Interface;

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

/**
 * Registers WooCommerce product hooks that invalidate Studio caches.
 * Calls an injected invalidator instead of Rest_Studio statics.
 */
final class WooCommerce_Studio_Cache_Invalidation {

	private static bool $registered = false;

	/** @var Studio_Cache_Invalidator_Interface */
	private $invalidator;

	public function __construct( Studio_Cache_Invalidator_Interface $invalidator ) {
		$this->invalidator = $invalidator;
	}

	public function register(): void {
		if ( self::$registered ) {
			return;
		}
		add_action( 'save_post_product', [ $this, 'on_save_product' ], 10, 2 );
		add_action( 'save_post_product_variation', [ $this, 'on_save_variation' ], 10, 2 );
		add_action( 'woocommerce_new_product', [ $this, 'on_woocommerce_product_saved' ] );
		add_action( 'woocommerce_update_product', [ $this, 'on_woocommerce_product_saved' ] );
		add_action( 'woocommerce_new_product_variation', [ $this, 'on_woocommerce_variation_saved' ] );
		add_action( 'woocommerce_update_product_variation', [ $this, 'on_woocommerce_variation_saved' ] );
		add_action( 'deleted_post', [ $this, 'on_deleted_post' ], 10, 2 );
		add_action( 'trashed_post', [ $this, 'on_trashed_post' ] );
		add_action( 'untrashed_post', [ $this, 'on_untrashed_post' ] );
		add_action( 'transition_post_status', [ $this, 'on_transition_post_status' ], 10, 3 );
		self::$registered = true;
	}

	public function on_save_product( int $post_id, \WP_Post $post ): void {
		if ( 'product' !== ( $post->post_type ?? '' ) ) {
			return;
		}
		$this->invalidator->invalidate_product( $post_id );
	}

	public function on_save_variation( int $post_id, \WP_Post $post ): void {
		if ( 'product_variation' !== ( $post->post_type ?? '' ) ) {
			return;
		}
		$this->invalidate_variation_and_parent( $post_id, (int) $post->post_parent );
	}

	/**
	 * Invalidate after WooCommerce has persisted product image meta.
	 *
	 * save_post_product can run before the product data store writes gallery changes.
	 */
	public function on_woocommerce_product_saved( int $product_id ): void {
		$this->invalidator->invalidate_product( $product_id );
	}

	public function on_woocommerce_variation_saved( int $variation_id ): void {
		$this->invalidate_variation_and_parent( $variation_id, (int) wp_get_post_parent_id( $variation_id ) );
	}

	public function on_deleted_post( int $post_id, ?\WP_Post $post = null ): void {
		$this->invalidator->invalidate_product( $post_id );
		if ( $post instanceof \WP_Post && 'product_variation' === ( $post->post_type ?? '' ) ) {
			$this->invalidator->invalidate_product( (int) $post->post_parent );
		}
	}

	public function on_trashed_post( int $post_id ): void {
		$post = get_post( $post_id );
		if ( $post && in_array( (string) ( $post->post_type ?? '' ), [ 'product', 'product_variation' ], true ) ) {
			$this->invalidator->invalidate_latest_list();
			if ( 'product_variation' === ( $post->post_type ?? '' ) ) {
				$this->invalidate_variation_and_parent( $post_id, (int) $post->post_parent );
			}
		}
	}

	public function on_untrashed_post( int $post_id ): void {
		$post = get_post( $post_id );
		if ( $post && in_array( (string) ( $post->post_type ?? '' ), [ 'product', 'product_variation' ], true ) ) {
			$this->invalidator->invalidate_latest_list();
			if ( 'product_variation' === ( $post->post_type ?? '' ) ) {
				$this->invalidate_variation_and_parent( $post_id, (int) $post->post_parent );
			}
		}
	}

	public function on_transition_post_status( string $new_status, string $old_status, \WP_Post $post ): void {
		if ( ! in_array( (string) ( $post->post_type ?? '' ), [ 'product', 'product_variation' ], true ) ) {
			return;
		}
		if ( 'publish' === $new_status || 'publish' === $old_status ) {
			$this->invalidator->invalidate_latest_list();
			if ( 'product_variation' === ( $post->post_type ?? '' ) ) {
				$this->invalidate_variation_and_parent( (int) $post->ID, (int) $post->post_parent );
			}
		}
	}

	private function invalidate_variation_and_parent( int $variation_id, int $parent_id ): void {
		if ( $variation_id > 0 ) {
			$this->invalidator->invalidate_product( $variation_id );
		}
		if ( $parent_id > 0 ) {
			$this->invalidator->invalidate_product( $parent_id );
		}
	}
}
