<?php
/**
 * Trait: Individual Pricing Tool
 *
 * Provides bulk_set_individual_prices — set unique per-product/variation prices.
 * Used by Niwa_AI_Admin_Autonomy_Tools.
 *
 * @package Niwa_AI
 * @since   0.10.56
 */

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

trait Niwa_AI_Tools_Individual_Pricing {

	/* ================================================================
	 * Preview
	 * ============================================================= */

	private function preview_bulk_set_individual_prices( $args ) {
		if ( ! class_exists( 'WooCommerce' ) || ! function_exists( 'wc_get_product' ) ) {
			return array( 'success' => false, 'error' => 'WooCommerce nije aktivan.' );
		}

		$items = isset( $args['items'] ) && is_array( $args['items'] ) ? array_values( $args['items'] ) : array();
		if ( empty( $items ) ) {
			return array( 'success' => false, 'error' => 'Lista stavki za individualne cene je prazna.' );
		}

		if ( count( $items ) > self::MAX_BULK_CATALOG_TARGETS ) {
			return array( 'success' => false, 'error' => 'Previše stavki — maksimum je ' . self::MAX_BULK_CATALOG_TARGETS . ' po pozivu.' );
		}

		$resolved_items  = array();
		$target_preview  = array();
		$clarifications  = array();
		$skipped         = 0;

		foreach ( $items as $item ) {
			$result = $this->resolve_individual_price_item( $item );

			if ( ! empty( $result['needs_clarification'] ) ) {
				$clarifications[] = $result['clarification'];
				continue;
			}

			if ( ! empty( $result['skipped'] ) ) {
				$skipped++;
				continue;
			}

			if ( empty( $result['success'] ) ) {
				return $result;
			}

			foreach ( (array) $result['items'] as $resolved ) {
				$resolved_items[] = $resolved;
				if ( count( $target_preview ) < 25 ) {
					$target_preview[] = $this->build_individual_price_preview( $resolved );
				}
			}
		}

		if ( ! empty( $clarifications ) ) {
			return array(
				'success'            => true,
				'needs_clarification' => true,
				'clarifications'     => $clarifications,
				'message'            => 'Neki proizvodi imaju varijacije sa razlicitim cenama. Treba mi pojasnjenje za svaku varijaciju.',
			);
		}

		if ( empty( $resolved_items ) ) {
			return array( 'success' => false, 'error' => 'Nema validnih stavki za izmenu cena.' );
		}

		$warnings = array();
		if ( $skipped > 0 ) {
			$warnings[] = 'Preskočeno ' . $skipped . ' stavki bez validne cene ili identifikatora.';
		}

		$sale_only_count = 0;
		foreach ( $resolved_items as $resolved_item ) {
			if ( ! empty( $resolved_item['new_sale_price'] ) && empty( $resolved_item['new_regular_price'] ) ) {
				$sale_only_count++;
			}
		}
		$all_sale_only = count( $resolved_items ) > 0 && $sale_only_count === count( $resolved_items );
		$action_label  = $all_sale_only
			? 'Sale-only cene za ' . count( $resolved_items ) . ' stavki'
			: 'Individualne cene za ' . count( $resolved_items ) . ' stavki';
		$action_summary = $all_sale_only
			? 'Postavi sale-only cene za ' . count( $resolved_items ) . ' Woo proizvoda/varijacija.'
			: 'Postavi individualne cene za ' . count( $resolved_items ) . ' Woo proizvoda/varijacija.';

		return array(
			'success' => true,
			'action'  => array(
				'type'             => 'bulk_set_individual_prices',
				'label'            => $action_label,
				'summary'          => $action_summary,
				'rollback_plan'    => 'Vraca prethodne regular i sale cene za sve izmenjene stavke.',
				'rollback_support' => 'full',
				'targets'          => $target_preview,
				'args'             => array(
					'items' => $resolved_items,
				),
			),
			'warnings' => $warnings,
		);
	}

	/* ================================================================
	 * Validate
	 * ============================================================= */

	private function validate_bulk_individual_price_action_args( $args ) {
		$items = isset( $args['items'] ) && is_array( $args['items'] ) ? $args['items'] : array();
		if ( empty( $items ) ) {
			return array( 'success' => false, 'error' => 'Lista stavki je prazna.' );
		}

		if ( count( $items ) > self::MAX_BULK_CATALOG_TARGETS ) {
			return array( 'success' => false, 'error' => 'Previše stavki za jedan run.' );
		}

		foreach ( $items as $item ) {
			$has_id = ( ! empty( $item['product_id'] ) && intval( $item['product_id'] ) > 0 )
			       || ( ! empty( $item['variation_id'] ) && intval( $item['variation_id'] ) > 0 );
			if ( ! $has_id ) {
				return array( 'success' => false, 'error' => 'Stavka nema validan product_id ili variation_id.' );
			}

			if ( empty( $item['new_regular_price'] ) && empty( $item['new_sale_price'] ) && empty( $item['clear_sale_price'] ) ) {
				return array( 'success' => false, 'error' => 'Stavka nema nijednu cenovnu promenu.' );
			}
		}

		return array( 'success' => true );
	}

	/* ================================================================
	 * Execute
	 * ============================================================= */

	private function execute_bulk_set_individual_prices_action( $action ) {
		if ( ! function_exists( 'wc_get_product' ) ) {
			return array( 'success' => false, 'error' => 'WooCommerce nije dostupan.' );
		}

		$items    = isset( $action['args']['items'] ) && is_array( $action['args']['items'] ) ? array_values( $action['args']['items'] ) : array();
		$executed = array();
		$rollback = array();
		$parents  = array();
		$unchanged = array();

		if ( empty( $items ) ) {
			return array( 'success' => false, 'error' => 'Nema stavki za izvršavanje.' );
		}

		foreach ( $items as $item ) {
			$variation_id = intval( isset( $item['variation_id'] ) ? $item['variation_id'] : 0 );
			$product_id   = intval( isset( $item['product_id'] ) ? $item['product_id'] : 0 );

			if ( $variation_id > 0 ) {
				$result = $this->apply_individual_price_to_variation( $variation_id, $item, $rollback );
			} else {
				$result = $this->apply_individual_price_to_simple( $product_id, $item, $rollback );
			}

			if ( empty( $result['success'] ) ) {
				$this->rollback_entries( $rollback );
				return $result;
			}

			if ( ! empty( $result['unchanged'] ) ) {
				$unchanged[] = isset( $result['record'] ) && is_array( $result['record'] ) ? $result['record'] : array();
				continue;
			}

			$rollback   = $result['rollback'];
			$executed[] = $result['record'];
			if ( ! empty( $result['parent_id'] ) ) {
				$parents[ intval( $result['parent_id'] ) ] = true;
			}
		}

		if ( empty( $executed ) ) {
			return array(
				'success'         => false,
				'error'           => 'Sve individualne cene su vec u trazenom stanju; nema promene za snimanje.',
				'unchanged_items' => $unchanged,
			);
		}

		foreach ( array_keys( $parents ) as $parent_id ) {
			$this->sync_variable_parent( intval( $parent_id ) );
		}

		$sale_only_count = 0;
		foreach ( $items as $item ) {
			if ( ! empty( $item['new_sale_price'] ) && empty( $item['new_regular_price'] ) ) {
				$sale_only_count++;
			}
		}
		$all_sale_only = count( $items ) > 0 && $sale_only_count === count( $items );

		return array(
			'success'          => true,
			'summary'          => $all_sale_only
				? 'Postavila sam sale-only cene za ' . count( $executed ) . ' Woo stavki.'
				: 'Postavila sam individualne cene za ' . count( $executed ) . ' Woo stavki.',
			'executed_actions' => $executed,
			'rollback_entries' => $rollback,
			'unchanged_items'  => $unchanged,
		);
	}

	/* ================================================================
	 * Item Resolution (preview phase)
	 * ============================================================= */

	private function resolve_individual_price_item( $item ) {
		$product_id    = intval( isset( $item['product_id'] ) ? $item['product_id'] : 0 );
		$variation_id  = intval( isset( $item['variation_id'] ) ? $item['variation_id'] : 0 );
		$sku           = isset( $item['sku'] ) ? trim( (string) $item['sku'] ) : '';
		$product_query = isset( $item['product_query'] ) ? trim( (string) $item['product_query'] ) : '';
		$new_regular   = isset( $item['regular_price'] ) ? trim( (string) $item['regular_price'] ) : '';
		$new_sale      = isset( $item['sale_price'] ) ? trim( (string) $item['sale_price'] ) : '';

		// Resolve by SKU if no ID provided.
		if ( $product_id <= 0 && $variation_id <= 0 && '' !== $sku ) {
			$resolved_id = wc_get_product_id_by_sku( $sku );
			if ( $resolved_id > 0 ) {
				$resolved_product = wc_get_product( $resolved_id );
				if ( $resolved_product && $resolved_product->is_type( 'variation' ) ) {
					$variation_id = $resolved_id;
				} else {
					$product_id = $resolved_id;
				}
			}
		}

		// Write operations require an exact product target; fuzzy lookup is read-only.
		if ( $product_id <= 0 && $variation_id <= 0 && '' !== $product_query ) {
			$resolved = $this->resolve_product_target_for_write( 0, $product_query, array( 'publish', 'private' ), 'individual pricing' );
			if ( ! empty( $resolved['success'] ) && ! empty( $resolved['target']['post_id'] ) ) {
				$target           = $resolved['target'];
				$resolved_product = wc_get_product( intval( $target['post_id'] ) );
				if ( $resolved_product && $resolved_product->is_type( 'variation' ) ) {
					$variation_id = intval( $target['post_id'] );
				} else {
					$product_id = intval( $target['post_id'] );
				}
			}
		}

		if ( $product_id <= 0 && $variation_id <= 0 ) {
			return array( 'success' => false, 'skipped' => true );
		}

		if ( '' === $new_regular && '' === $new_sale ) {
			return array( 'success' => false, 'skipped' => true );
		}

		// Direct variation target.
		if ( $variation_id > 0 ) {
			return $this->resolve_as_variation_item( $variation_id, $new_regular, $new_sale );
		}

		$product = wc_get_product( $product_id );
		if ( ! $product ) {
			return array( 'success' => false, 'skipped' => true );
		}

		// Simple product.
		if ( $product->is_type( 'simple' ) ) {
			return $this->resolve_as_simple_item( $product, $new_regular, $new_sale );
		}

		// Variable product — check variation prices.
		if ( $product->is_type( 'variable' ) ) {
			return $this->resolve_as_variable_item( $product, $new_regular, $new_sale );
		}

		return array( 'success' => false, 'skipped' => true );
	}

	private function resolve_as_simple_item( $product, $new_regular, $new_sale ) {
		return array(
			'success' => true,
			'items'   => array(
                array(
                    'product_id'        => intval( $product->get_id() ),
                    'variation_id'      => 0,
                    'target_label'      => (string) $product->get_name(),
                    'new_regular_price' => $new_regular,
                    'new_sale_price'    => $new_sale,
                    'clear_sale_price'  => 0,
                    'price_mode'        => '' !== $new_sale && '' === $new_regular ? 'sale_only' : ( '' !== $new_sale ? 'regular_and_sale' : 'regular_only' ),
                ),
            ),
        );
    }

	private function resolve_as_variation_item( $variation_id, $new_regular, $new_sale ) {
		$variation = wc_get_product( $variation_id );
		if ( ! $variation || ! $variation->is_type( 'variation' ) ) {
			return array( 'success' => false, 'skipped' => true );
		}

		$parent = wc_get_product( $variation->get_parent_id() );
		$label  = $parent ? (string) $parent->get_name() : '#' . $variation_id;
		$attrs  = $variation->get_attributes();
		if ( ! empty( $attrs ) ) {
			$label .= ' — ' . implode( ', ', array_filter( array_values( $attrs ) ) );
		}

		return array(
			'success' => true,
			'items'   => array(
                array(
                    'product_id'        => intval( $variation->get_parent_id() ),
                    'variation_id'      => $variation_id,
                    'target_label'      => $label,
                    'new_regular_price' => $new_regular,
                    'new_sale_price'    => $new_sale,
                    'clear_sale_price'  => 0,
                    'price_mode'        => '' !== $new_sale && '' === $new_regular ? 'sale_only' : ( '' !== $new_sale ? 'regular_and_sale' : 'regular_only' ),
                ),
            ),
        );
    }

	private function resolve_as_variable_item( $product, $new_regular, $new_sale ) {
		$children = $product->get_children();
		if ( empty( $children ) ) {
			return array( 'success' => false, 'skipped' => true );
		}

		// Check if all variations have the same price.
		$prices = array();
		$variation_details = array();
		foreach ( $children as $child_id ) {
			$child = wc_get_product( $child_id );
			if ( ! $child || ! $child->is_type( 'variation' ) ) {
				continue;
			}

			$price = (string) $child->get_regular_price();
			$prices[ $price ] = true;
			$variation_details[] = array(
				'variation_id'  => intval( $child_id ),
				'attributes'    => $child->get_attributes(),
				'regular_price' => $price,
				'sale_price'    => (string) $child->get_sale_price(),
			);
		}

		if ( empty( $variation_details ) ) {
			return array( 'success' => false, 'skipped' => true );
		}

		// All same price — auto-expand to all variations.
		if ( count( $prices ) <= 1 ) {
			$items = array();
			foreach ( $variation_details as $detail ) {
				$items[] = array(
					'product_id'        => intval( $product->get_id() ),
					'variation_id'      => $detail['variation_id'],
					'target_label'      => $product->get_name() . ' — ' . implode( ', ', array_filter( array_values( $detail['attributes'] ) ) ),
					'new_regular_price' => $new_regular,
					'new_sale_price'    => $new_sale,
					'clear_sale_price'  => 0,
					'price_mode'        => '' !== $new_sale && '' === $new_regular ? 'sale_only' : ( '' !== $new_sale ? 'regular_and_sale' : 'regular_only' ),
				);
			}
			return array( 'success' => true, 'items' => $items );
		}

		// Different prices — need clarification.
		$display_variations = array();
		foreach ( array_slice( $variation_details, 0, 50 ) as $detail ) {
			$display_variations[] = array(
				'variation_id'  => $detail['variation_id'],
				'attributes'    => implode( ', ', array_filter( array_values( $detail['attributes'] ) ) ),
				'regular_price' => $detail['regular_price'],
				'sale_price'    => $detail['sale_price'],
				'regular_price_display' => $this->format_price_display_value( $detail['regular_price'] ),
				'sale_price_display'    => $this->format_price_display_value( $detail['sale_price'] ),
			);
		}

		return array(
			'success'            => false,
			'needs_clarification' => true,
			'clarification'      => array(
				'product_id'     => intval( $product->get_id() ),
				'product_name'   => (string) $product->get_name(),
				'variation_count' => count( $variation_details ),
				'message'        => 'Proizvod "' . $product->get_name() . '" ima ' . count( $variation_details ) . ' varijacija sa RAZLIČITIM cenama. Treba mi cena za svaku varijaciju pojedinačno.',
				'variations'     => $display_variations,
			),
		);
	}

	/* ================================================================
	 * Price Application (execute phase)
	 * ============================================================= */

	private function apply_individual_price_to_variation( $variation_id, $item, $rollback ) {
		$variation = wc_get_product( $variation_id );
		if ( ! $variation || ! $variation->is_type( 'variation' ) ) {
			return array( 'success' => false, 'error' => 'Varijacija #' . $variation_id . ' ne postoji.' );
		}

		$new_regular = isset( $item['new_regular_price'] ) ? trim( (string) $item['new_regular_price'] ) : '';
		$new_sale    = isset( $item['new_sale_price'] ) ? trim( (string) $item['new_sale_price'] ) : '';
		$clear_sale  = ! empty( $item['clear_sale_price'] );

		if ( '' !== $new_regular ) {
			$variation->set_regular_price( $new_regular );
		}
		if ( $clear_sale ) {
			$variation->set_sale_price( '' );
		} elseif ( '' !== $new_sale ) {
			$variation->set_sale_price( $new_sale );
		}

		if ( method_exists( $variation, 'get_changes' ) && empty( $variation->get_changes() ) ) {
			return array(
				'success'   => true,
				'unchanged' => true,
				'rollback'  => $rollback,
				'parent_id' => intval( $variation->get_parent_id() ),
				'record'    => array(
					'type'         => 'bulk_set_individual_prices',
					'variation_id' => $variation_id,
					'unchanged'    => true,
				),
			);
		}

		$rollback[] = $this->build_variation_restore_entry( $variation );

		$saved = $variation->save();
		if ( ! $saved ) {
			return array( 'success' => false, 'error' => 'Varijacija #' . $variation_id . ' nije sačuvana.' );
		}

		return array(
			'success'   => true,
			'rollback'  => $rollback,
			'parent_id' => intval( $variation->get_parent_id() ),
			'record'    => array(
				'type'         => 'bulk_set_individual_prices',
				'variation_id' => $variation_id,
				'changes'      => array(
					'regular_price'        => $new_regular,
					'regular_price_display' => $this->format_price_display_value( $new_regular ),
					'sale_price'           => $new_sale,
					'sale_price_display'   => $this->format_price_display_value( $new_sale ),
					'price_mode'           => '' !== $new_sale && '' === $new_regular ? 'sale_only' : ( '' !== $new_sale ? 'regular_and_sale' : 'regular_only' ),
				),
			),
		);
	}

	private function apply_individual_price_to_simple( $product_id, $item, $rollback ) {
		$product = wc_get_product( $product_id );
		if ( ! $product || ! $product->is_type( 'simple' ) ) {
			return array( 'success' => false, 'error' => 'Proizvod #' . $product_id . ' ne postoji ili nije simple.' );
		}

		$new_regular = isset( $item['new_regular_price'] ) ? trim( (string) $item['new_regular_price'] ) : '';
		$new_sale    = isset( $item['new_sale_price'] ) ? trim( (string) $item['new_sale_price'] ) : '';
		$clear_sale  = ! empty( $item['clear_sale_price'] );

		if ( '' !== $new_regular ) {
			$product->set_regular_price( $new_regular );
		}
		if ( $clear_sale ) {
			$product->set_sale_price( '' );
		} elseif ( '' !== $new_sale ) {
			$product->set_sale_price( $new_sale );
		}

		if ( method_exists( $product, 'get_changes' ) && empty( $product->get_changes() ) ) {
			return array(
				'success'   => true,
				'unchanged' => true,
				'rollback'  => $rollback,
				'parent_id' => 0,
				'record'    => array(
					'type'       => 'bulk_set_individual_prices',
					'product_id' => $product_id,
					'unchanged'  => true,
				),
			);
		}

		$rollback[] = $this->build_simple_product_restore_entry( $product_id, $product );

		$saved = $product->save();
		if ( ! $saved ) {
			return array( 'success' => false, 'error' => 'Proizvod #' . $product_id . ' nije sačuvan.' );
		}

		$this->sync_product_ops_write( $product_id );

		return array(
			'success'   => true,
			'rollback'  => $rollback,
			'parent_id' => 0,
			'record'    => array(
				'type'       => 'bulk_set_individual_prices',
				'product_id' => $product_id,
				'changes'    => array(
					'regular_price'        => $new_regular,
					'regular_price_display' => $this->format_price_display_value( $new_regular ),
					'sale_price'           => $new_sale,
					'sale_price_display'   => $this->format_price_display_value( $new_sale ),
					'price_mode'           => '' !== $new_sale && '' === $new_regular ? 'sale_only' : ( '' !== $new_sale ? 'regular_and_sale' : 'regular_only' ),
				),
			),
		);
	}

	/* ================================================================
	 * Preview Helper
	 * ============================================================= */

	private function build_individual_price_preview( $item ) {
		return array(
			'product_id'        => intval( isset( $item['product_id'] ) ? $item['product_id'] : 0 ),
			'variation_id'      => intval( isset( $item['variation_id'] ) ? $item['variation_id'] : 0 ),
			'target_label'      => isset( $item['target_label'] ) ? (string) $item['target_label'] : '',
			'new_regular_price' => isset( $item['new_regular_price'] ) ? (string) $item['new_regular_price'] : '',
			'new_sale_price'    => isset( $item['new_sale_price'] ) ? (string) $item['new_sale_price'] : '',
			'new_regular_price_display' => $this->format_price_display_value( isset( $item['new_regular_price'] ) ? (string) $item['new_regular_price'] : '' ),
			'new_sale_price_display'    => $this->format_price_display_value( isset( $item['new_sale_price'] ) ? (string) $item['new_sale_price'] : '' ),
			'price_mode'        => isset( $item['price_mode'] ) ? (string) $item['price_mode'] : ( ! empty( $item['new_sale_price'] ) && empty( $item['new_regular_price'] ) ? 'sale_only' : ( ! empty( $item['new_sale_price'] ) ? 'regular_and_sale' : 'regular_only' ) ),
		);
	}
}
