<?php

namespace FuseCommerce\Services;

use FuseCommerce\Repositories\ProductRepository;

/**
 * Service for extracting product attributes used by published products
 */
class AttributeIndexerService {
    private ProductRepository $product_repository;

    public function __construct( ProductRepository $product_repository ) {
        $this->product_repository = $product_repository;
    }

    /**
     * Build attributes data for all attributes used by published products
     * Only includes attribute taxonomies (pa_*) that are actually used
     *
     * @return array Array of attribute data with terms
     */
    public function buildAttributesData(): array {
        // Get only taxonomies used by published products
        $used_taxonomies = $this->product_repository->getUsedAttributeTaxonomies();

        if ( empty( $used_taxonomies ) ) {
            return [];
        }

        $attributes = [];

        foreach ( $used_taxonomies as $taxonomy ) {
            $attribute_data = $this->buildAttributeData( $taxonomy );

            if ( ! empty( $attribute_data ) ) {
                $attributes[] = $attribute_data;
            }
        }

        return $attributes;
    }

    /**
     * Build data for a single attribute taxonomy
     *
     * @param string $taxonomy Taxonomy name (e.g., 'pa_color')
     * @return array|null Attribute data or null if no terms found
     */
    private function buildAttributeData( string $taxonomy ): ?array {
        // Get attribute label
        $label = $this->getAttributeLabel( $taxonomy );

        // Get terms for this taxonomy
        $terms = get_terms( [
            'taxonomy'   => $taxonomy,
            'hide_empty' => true, // Only terms with products
            'orderby'    => 'name',
            'order'      => 'ASC',
        ] );

        if ( is_wp_error( $terms ) || empty( $terms ) ) {
            return null;
        }

        // Convert terms to array format
        $terms_array = array_map(
            function ( $term ) {
                return [
                    'id'   => $term->term_id,
                    'name' => $term->name,
                    'slug' => $term->slug,
                ];
            },
            $terms
        );

        return [
            'name'  => $taxonomy,
            'label' => $label,
            'terms' => $terms_array,
        ];
    }

    /**
     * Get human-readable label for an attribute taxonomy
     *
     * @param string $taxonomy Taxonomy name (e.g., 'pa_color')
     * @return string Attribute label
     */
    private function getAttributeLabel( string $taxonomy ): string {
        // Remove 'pa_' prefix to get attribute name
        $attribute_name = wc_sanitize_taxonomy_name( str_replace( 'pa_', '', $taxonomy ) );

        // Get attribute from database
        $attribute = wc_get_attribute( wc_attribute_taxonomy_id_by_name( $attribute_name ) );

        if ( $attribute && ! empty( $attribute->name ) ) {
            return $attribute->name;
        }

        // Fallback: convert slug to title case
        return ucwords( str_replace( [ '-', '_' ], ' ', $attribute_name ) );
    }

    /**
     * Get all custom (non-taxonomy) attributes used in products
     * These are attributes not registered as taxonomies
     *
     * @return array Array of custom attribute names
     */
    public function getCustomAttributes(): array {
        global $wpdb;

        // Query postmeta for _product_attributes

        $results = $wpdb->get_col( $wpdb->prepare(
            "
            SELECT DISTINCT pm.meta_value
            FROM {$wpdb->postmeta} pm
            INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID
            WHERE p.post_type = %s
            AND p.post_status = %s
            AND p.post_parent = 0
            AND pm.meta_key = %s
        ",
            'product',
            'publish',
            '_product_attributes'
        ) );

        $custom_attributes = [];

        foreach ( $results as $serialized_data ) {
            $attributes = maybe_unserialize( $serialized_data );

            if ( ! is_array( $attributes ) ) {
                continue;
            }

            foreach ( $attributes as $key => $attribute ) {
                // Check if it's not a taxonomy attribute
                if ( ! isset( $attribute['is_taxonomy'] ) || $attribute['is_taxonomy'] != 1 ) {
                    if ( isset( $attribute['name'] ) && ! in_array( $attribute['name'], $custom_attributes ) ) {
                        $custom_attributes[] = $attribute['name'];
                    }
                }
            }
        }

        return $custom_attributes;
    }

    /**
     * Build complete attributes data including both taxonomy and custom attributes
     * Note: Custom attributes don't have predefined terms, so they're listed separately
     *
     * @return array Array with 'taxonomies' and 'custom' keys
     */
    public function buildCompleteAttributesData(): array {
        return [
            'taxonomies' => $this->buildAttributesData(),
            'custom'     => $this->getCustomAttributes(),
        ];
    }
}
