<?php

namespace AIPT\Api\BulkGenerator\Desc\Core;

use AIPT\Utils\VariableConverter;

class ProductDataProvider {

	private const CACHE_GROUP = 'aipt_product';
	private const CACHE_TTL = 300;

	public static function get( int $product_id, bool $use_cache = true ): ?array {
		if ( $use_cache ) {
			$cache_key = self::CACHE_GROUP . '_' . $product_id;
			$cached    = get_transient( $cache_key );
			if ( false !== $cached ) {
				return $cached;
			}
		}

		$product = wc_get_product( $product_id );
		if ( ! $product ) {
			return null;
		}

		$data = self::extractProductData( $product );

		if ( $use_cache ) {
			set_transient( $cache_key, $data, self::CACHE_TTL );
		}

		return $data;
	}

	public static function bulkGet( array $product_ids, bool $use_cache = true ): array {
		if ( empty( $product_ids ) ) {
			return array();
		}

		$result      = array();
		$to_load     = array();
		$product_ids = array_unique( array_map( 'absint', $product_ids ) );

		if ( $use_cache ) {
			foreach ( $product_ids as $id ) {
				$cache_key = self::CACHE_GROUP . '_' . $id;
				$cached    = get_transient( $cache_key );
				if ( false !== $cached ) {
					$result[ $id ] = $cached;
				} else {
					$to_load[] = $id;
				}
			}
		} else {
			$to_load = $product_ids;
		}

		if ( ! empty( $to_load ) ) {
			$products = wc_get_products(
				array(
					'include' => $to_load,
					'limit'   => -1,
					'return'  => 'objects',
					'status'  => array( 'publish', 'draft', 'pending', 'private' ),

				)
			);

			$loaded_ids = array();
			foreach ( $products as $product ) {
				$data                         = self::extractProductData( $product );
				$result[ $product->get_id() ] = $data;
				$loaded_ids[]                 = $product->get_id();

				if ( $use_cache ) {
					$cache_key = self::CACHE_GROUP . '_' . $product->get_id();
					set_transient( $cache_key, $data, self::CACHE_TTL );
				}
			}

			$missing_ids = array_diff( $to_load, $loaded_ids );
			if ( ! empty( $missing_ids ) ) {
				foreach ( $missing_ids as $missing_id ) {
					$product = wc_get_product( $missing_id );
					if ( $product ) {
						$data                    = self::extractProductData( $product );
						$result[ $missing_id ]   = $data;

						if ( $use_cache ) {
							$cache_key = self::CACHE_GROUP . '_' . $missing_id;
							set_transient( $cache_key, $data, self::CACHE_TTL );
						}
					}
				}
			}
		}

		return $result;
	}

	private static function extractProductData( \WC_Product $product ): array {
		$categories = self::extractCategories( $product );
		$tags       = self::extractTags( $product );

		$raw_price         = $product->get_price();
		$raw_regular_price = $product->get_regular_price();
		$raw_sale_price    = $product->is_on_sale() ? $product->get_sale_price() : '';

		$data = array(
			'id'                   => $product->get_id(),
			'name'                 => $product->get_name(),
			'sku'                  => $product->get_sku() ?: '',
			'price'                => ( $raw_price !== '' && $raw_price !== null ) ? (string) $raw_price : '',
			'regular_price'        => ( $raw_regular_price !== '' && $raw_regular_price !== null ) ? (string) $raw_regular_price : '',
			'sale_price'           => ( $raw_sale_price !== '' && $raw_sale_price !== null ) ? (string) $raw_sale_price : '',
			'price_display'        => ( $raw_price !== '' && $raw_price !== null ) ? wp_strip_all_tags( wc_price( $raw_price ) ) : '',
			'regular_price_display' => ( $raw_regular_price !== '' && $raw_regular_price !== null ) ? wp_strip_all_tags( wc_price( $raw_regular_price ) ) : '',
			'sale_price_display'   => ( $raw_sale_price !== '' && $raw_sale_price !== null ) ? wp_strip_all_tags( wc_price( $raw_sale_price ) ) : '',
			'categories'           => $categories,
			'categories_string'    => implode( ', ', $categories ),
			'tags'                 => $tags,
			'tags_string'          => implode( ', ', $tags ),
			'attributes'           => self::extractAttributes( $product ),
			'formatted_attributes' => '',
			'short_description'    => $product->get_short_description(),
			'description'          => $product->get_description(),
			'custom_variables'     => array(),
			'image'                => self::extractImage( $product ),
			'stock_status'         => $product->get_stock_status(),
		);

		$attr_texts = array();
		foreach ( $data['attributes'] as $name => $value ) {
			$attr_texts[] = $name . ': ' . $value;
		}
		$data['formatted_attributes'] = implode( '; ', $attr_texts );

		$data['custom_variables'] = self::extractCustomVariables( $product, $data );

		$dimensions = self::extractDimensions( $product );
		if ( ! empty( $dimensions ) ) {
			foreach ( $dimensions as $key => $value ) {
				$data['attributes'][ ucfirst( $key ) ] = $value;
				$attr_texts[]                          = ucfirst( $key ) . ': ' . $value;
			}
			$data['formatted_attributes'] = implode( '; ', $attr_texts );
		}

		return $data;
	}

	private static function extractCategories( \WC_Product $product ): array {
		$terms = wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) );
		if ( is_wp_error( $terms ) || empty( $terms ) ) {
			return array();
		}
		return array_map(
			function ( $cat ) {
				return html_entity_decode( $cat, ENT_QUOTES, 'UTF-8' );
			},
			$terms
		);
	}

	private static function extractTags( \WC_Product $product ): array {
		$terms = wp_get_post_terms( $product->get_id(), 'product_tag', array( 'fields' => 'names' ) );
		if ( is_wp_error( $terms ) || empty( $terms ) ) {
			return array();
		}
		return $terms;
	}

	private static function extractAttributes( \WC_Product $product ): array {
		$result     = array();
		$attributes = $product->get_attributes();

		if ( empty( $attributes ) ) {
			return $result;
		}

		foreach ( $attributes as $attribute ) {
			if ( ! $attribute->get_visible() ) {
				continue;
			}

			$name   = wc_attribute_label( $attribute->get_name() );
			$values = array();

			if ( $attribute->is_taxonomy() ) {
				$terms = wp_get_post_terms( $product->get_id(), $attribute->get_name(), array( 'fields' => 'names' ) );
				if ( ! is_wp_error( $terms ) ) {
					$values = $terms;
				}
			} else {
				$values = $attribute->get_options();
			}

			if ( ! empty( $values ) ) {
				$result[ $name ] = implode( ', ', $values );
			}
		}

		return $result;
	}

	private static function extractDimensions( \WC_Product $product ): array {
		$dimensions = array();

		$weight = $product->get_weight();
		$length = $product->get_length();
		$width  = $product->get_width();
		$height = $product->get_height();

		if ( ! empty( $weight ) ) {
			$dimensions['weight'] = $weight . ' ' . get_option( 'woocommerce_weight_unit' );
		}
		if ( ! empty( $length ) ) {
			$dimensions['length'] = $length . ' ' . get_option( 'woocommerce_dimension_unit' );
		}
		if ( ! empty( $width ) ) {
			$dimensions['width'] = $width . ' ' . get_option( 'woocommerce_dimension_unit' );
		}
		if ( ! empty( $height ) ) {
			$dimensions['height'] = $height . ' ' . get_option( 'woocommerce_dimension_unit' );
		}

		return $dimensions;
	}

	private static function extractImage( \WC_Product $product ): string {
		$image_id = $product->get_image_id();
		if ( ! $image_id ) {
			return '';
		}

		$image_url = wp_get_attachment_image_url( $image_id, 'thumbnail' );
		return $image_url ?: '';
	}

	private static function extractCustomVariables( \WC_Product $product, array $data ): array {
		$custom_vars    = array();
		$variable_defs  = get_option( 'aipt_custom_variables', array() );

		if ( empty( $variable_defs ) ) {
			return $custom_vars;
		}

		foreach ( $variable_defs as $variable ) {
			if ( empty( $variable['field'] ) || empty( $variable['name'] ) ) {
				continue;
			}

			$value = self::getCustomFieldValue( $product, $variable['field'] );
			if ( null !== $value ) {
				$custom_vars[ $variable['name'] ] = $value;
			}
		}

		return $custom_vars;
	}

	private static function getCustomFieldValue( \WC_Product $product, string $field_key ): ?string {
		$wc_methods = array(
			'weight'            => 'get_weight',
			'length'            => 'get_length',
			'width'             => 'get_width',
			'height'            => 'get_height',
			'description'       => 'get_description',
			'short_description' => 'get_short_description',
			'name'              => 'get_name',
			'sku'               => 'get_sku',
			'price'             => 'get_price',
			'regular_price'     => 'get_regular_price',
			'sale_price'        => 'get_sale_price',
			'stock_status'      => 'get_stock_status',
			'stock_quantity'    => 'get_stock_quantity',
		);

		if ( isset( $wc_methods[ $field_key ] ) && method_exists( $product, $wc_methods[ $field_key ] ) ) {
			$value = $product->{$wc_methods[ $field_key ]}();
			if ( ! empty( $value ) ) {
				if ( in_array( $field_key, array( 'description', 'short_description' ), true ) ) {
					$value = wp_strip_all_tags( $value );
				}
				return VariableConverter::toString( $value );
			}
		}

		if ( function_exists( 'get_field' ) ) {
			$acf_value = get_field( $field_key, $product->get_id() );
			if ( null !== $acf_value && false !== $acf_value ) {
				return VariableConverter::formatCustomField( $acf_value );
			}
		}

		$attribute = $product->get_attribute( $field_key );
		if ( ! empty( $attribute ) ) {
			return VariableConverter::toString( $attribute );
		}

		$meta_value = get_post_meta( $product->get_id(), $field_key, true );
		if ( ! empty( $meta_value ) ) {
			return VariableConverter::toString( $meta_value );
		}

		return null;
	}

	public static function getPrioritizedContext( array $data, int $max_chars = 1500 ): string {
		$lines = array();
		$total = 0;

		$priority_fields = array(
			array( 'label' => 'Product', 'key' => 'name' ),
			array( 'label' => 'SKU', 'key' => 'sku' ),
			array( 'label' => 'Price', 'key' => 'price' ),
			array( 'label' => 'Categories', 'key' => 'categories_string' ),
			array( 'label' => 'Attributes', 'key' => 'formatted_attributes' ),
			array( 'label' => 'Tags', 'key' => 'tags_string' ),
			array( 'label' => 'Short Description', 'key' => 'short_description' ),
		);

		foreach ( $priority_fields as $field ) {
			$value = $data[ $field['key'] ] ?? '';
			if ( empty( $value ) ) {
				continue;
			}

			$line = $field['label'] . ': ' . $value;

			if ( $total + strlen( $line ) > $max_chars ) {
				$remaining = $max_chars - $total - strlen( $field['label'] ) - 5;
				if ( $remaining > 50 ) {
					$value = substr( $value, 0, $remaining ) . '...';
					$line  = $field['label'] . ': ' . $value;
				} else {
					break;
				}
			}

			$lines[] = $line;
			$total  += strlen( $line ) + 1;

			if ( $total >= $max_chars ) {
				break;
			}
		}

		return implode( "\n", $lines );
	}

	public static function clearCache( int $product_id ): void {
		delete_transient( self::CACHE_GROUP . '_' . $product_id );
	}

	public static function clearAllCache(): void {
		global $wpdb;

		$wpdb->query(
			$wpdb->prepare(
				"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
				'_transient_' . self::CACHE_GROUP . '_%'
			)
		);
		$wpdb->query(
			$wpdb->prepare(
				"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
				'_transient_timeout_' . self::CACHE_GROUP . '_%'
			)
		);

	}
}
