<?php

/**
 * Swatch data service.
 *
 * @package B3WVS\VariationSwatches\Frontend
 */
namespace B3WVS\VariationSwatches\Frontend;

defined( 'ABSPATH' ) || exit;
/**
 * Class SwatchDataService
 */
class SwatchDataService {
    /**
     * Runtime cache for attribute data to avoid duplicate queries.
     *
     * @var array
     */
    private $attribute_cache = array();

    /**
     * Get attribute data including term meta.
     * Uses runtime caching to avoid duplicate database queries on the same page.
     *
     * @param \WC_Product $product   Product object.
     * @param string      $attribute Attribute name.
     * @param array       $options   Attribute options.
     * @param array|null  $settings  Optional pre-fetched settings.
     * @return array
     */
    public function get_attribute_data(
        $product,
        $attribute,
        $options,
        $settings = null
    ) {
        $product_id = ( is_object( $product ) && method_exists( $product, 'get_id' ) ? $product->get_id() : 0 );
        $settings = ( is_array( $settings ) ? $settings : \b3wvs_get_effective_settings() );
        if ( !is_array( $settings ) ) {
            $settings = array();
        }
        // phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode -- wp_json_encode is used.
        $cache_key = $product_id . '_' . $attribute . '_' . md5( wp_json_encode( $options ) );
        if ( isset( $this->attribute_cache[$cache_key] ) ) {
            return $this->attribute_cache[$cache_key];
        }
        $data = array();
        $overrides = array();
        if ( $product_id ) {
            $maybe_overrides = get_post_meta( $product_id, '_b3_wvs_overrides', true );
            if ( is_array( $maybe_overrides ) ) {
                $overrides = $maybe_overrides;
            }
        }
        if ( !taxonomy_exists( $attribute ) ) {
            foreach ( $options as $option ) {
                $override = ( isset( $overrides[$attribute][$option] ) && is_array( $overrides[$attribute][$option] ) ? $overrides[$attribute][$option] : array() );
                $override_label = ( isset( $override['label'] ) ? trim( (string) $override['label'] ) : '' );
                $label = ( '' !== $override_label ? $override_label : $option );
                $raw = array(
                    'type'  => ( isset( $override['type'] ) ? (string) $override['type'] : '' ),
                    'color' => ( isset( $override['color'] ) ? (string) $override['color'] : '' ),
                );
                $data[$option] = SwatchPayloadNormalizer::normalize( $raw, $label );
            }
        }
        if ( taxonomy_exists( $attribute ) ) {
            $terms_by_slug = array();
            $term_ids = array();
            $slugs = array();
            foreach ( $options as $option ) {
                $slug = sanitize_title( (string) $option );
                if ( '' !== $slug ) {
                    $slugs[] = $slug;
                }
            }
            if ( !empty( $slugs ) ) {
                $terms = get_terms( array(
                    'taxonomy'   => $attribute,
                    'hide_empty' => false,
                    'slug'       => $slugs,
                ) );
                if ( is_array( $terms ) ) {
                    foreach ( $terms as $term ) {
                        if ( !$term || is_wp_error( $term ) ) {
                            continue;
                        }
                        $terms_by_slug[$term->slug] = $term;
                        $term_ids[] = $term->term_id;
                    }
                }
            }
            if ( !empty( $term_ids ) ) {
                update_termmeta_cache( $term_ids );
            }
            foreach ( $options as $option ) {
                if ( !isset( $terms_by_slug[$option] ) ) {
                    continue;
                }
                $term = $terms_by_slug[$option];
                $term_type = (string) get_term_meta( $term->term_id, 'b3_wvs_type', true );
                $term_color = (string) get_term_meta( $term->term_id, 'b3_wvs_color', true );
                $term_label = (string) get_term_meta( $term->term_id, 'b3_wvs_label', true );
                $label = ( 'button' === $term_type && '' !== trim( $term_label ) ? $term_label : $term->name );
                $raw = array(
                    'type'  => $term_type,
                    'color' => $term_color,
                );
                $data[$option] = SwatchPayloadNormalizer::normalize( $raw, $label );
            }
        }
        $this->attribute_cache[$cache_key] = $data;
        return $data;
    }

}
