<?php
namespace ShopyPress\Services;
if ( ! defined( 'ABSPATH' ) ) exit;

use ShopyPress\Models\ShopyPressProduct;

class ProductRepository {

    private CollectionTaxonomyService $collection_service;

    public function __construct() {
        $this->collection_service = new CollectionTaxonomyService();
    }

    /**
     * Find WordPress post ID by Shopify product ID
     *
     * @param string $shopify_product_id The Shopify product ID (e.g., gid://shopify/Product/123)
     * @return int|null WordPress post ID or null if not found
     */
    public function findByShopifyId(string $shopify_product_id): ?int {
        $query = new \WP_Query([
            'post_type' => ShopyPressProduct::PRODUCT_SLUG,
            'meta_query' => [
                [
                    'key' => '_shopify_product_id',
                    'value' => $shopify_product_id,
                    'compare' => '='
                ]
            ],
            'posts_per_page' => 1,
            'fields' => 'ids'
        ]);

        if (!empty($query->posts)) {
            return $query->posts[0];
        }

        return null;
    }

    /**
     * Create or update product from Shopify data
     *
     * @param array $shopify_product Full Shopify product data
     * @return int WordPress post ID
     */
    public function createOrUpdate(array $shopify_product): int {
        $existing_id = $this->findByShopifyId($shopify_product['id']);

        $post_data = [
            'post_type' => ShopyPressProduct::PRODUCT_SLUG,
            'post_title' => $shopify_product['title'] ?? '',
            'post_name' => $shopify_product['handle'] ?? '',
            'post_content' => $shopify_product['description'] ?? '',
            'post_status' => ($shopify_product['status'] === 'ACTIVE') ? 'publish' : 'draft',
        ];

        if ($existing_id) {
            $post_data['ID'] = $existing_id;
            $post_id = wp_update_post($post_data);
        } else {
            $post_id = wp_insert_post($post_data);
        }

        if (is_wp_error($post_id) || !$post_id) {
            throw new \Exception('Failed to create/update product: ' . esc_html($shopify_product['title']));
        }

        // Save all meta data
        $this->saveProductMeta($post_id, $shopify_product);

        return $post_id;
    }

    /**
     * Save all product meta fields
     *
     * @param int $post_id WordPress post ID
     * @param array $shopify_product Shopify product data
     */
    private function saveProductMeta(int $post_id, array $shopify_product): void {
        update_post_meta($post_id, '_shopify_product_id', $shopify_product['id']);
        update_post_meta($post_id, '_shopify_handle', $shopify_product['handle'] ?? '');
        update_post_meta($post_id, '_shopify_description', $shopify_product['description'] ?? '');
        update_post_meta($post_id, '_shopify_description_html', $shopify_product['descriptionHtml'] ?? '');
        update_post_meta($post_id, '_shopify_product_type', $shopify_product['productType'] ?? '');
        update_post_meta($post_id, '_shopify_vendor', $shopify_product['vendor'] ?? '');

        // Tags - save as array and individual meta entries for searchability
        $tags = $shopify_product['tags'] ?? [];
        update_post_meta($post_id, '_shopify_tags', $tags);

        // Save each tag as individual meta for better searchability
        delete_post_meta($post_id, '_shopify_tag');
        foreach ($tags as $tag) {
            add_post_meta($post_id, '_shopify_tag', sanitize_text_field($tag));
        }

        update_post_meta($post_id, '_shopify_updated_at', $shopify_product['updatedAt'] ?? '');

        // Price range
        $price_min = $shopify_product['priceRangeV2']['minVariantPrice']['amount'] ?? '';
        $price_max = $shopify_product['priceRangeV2']['maxVariantPrice']['amount'] ?? '';
        update_post_meta($post_id, '_shopify_price_min', $price_min);
        update_post_meta($post_id, '_shopify_price_max', $price_max);

        // Variants (serialized array)
        $variants = $this->extractVariants($shopify_product['variants']['edges'] ?? []);
        update_post_meta($post_id, '_shopify_variants', $variants);

        // Extract and save variant options for easier querying
        $this->saveVariantOptions($post_id, $variants);

        // Images (array of CDN URLs)
        $images = $this->extractImages($shopify_product['images']['edges'] ?? []);
        update_post_meta($post_id, '_shopify_images', $images);

        // Featured Media
        $featured_media = $this->extractFeaturedMedia($shopify_product['featuredMedia'] ?? null);
        update_post_meta($post_id, '_shopify_featured_media', $featured_media);

        // All Media
        $media = $this->extractMedia($shopify_product['media']['edges'] ?? []);
        update_post_meta($post_id, '_shopify_media', $media);

        // Product Status
        update_post_meta($post_id, '_shopify_status', $shopify_product['status'] ?? '');

        // Total Inventory
        update_post_meta($post_id, '_shopify_total_inventory', $shopify_product['totalInventory'] ?? 0);

        // Collections - sync taxonomy terms and assign to product
        $collections = $this->extractCollections($shopify_product['collections']['edges'] ?? []);
        if (!empty($collections)) {
            $term_ids = $this->collection_service->getTermIdsForCollections($collections);
            $this->collection_service->assignCollectionsToProduct($post_id, $term_ids);
        } else {
            $this->collection_service->clearProductCollections($post_id);
        }
    }

    /**
     * Save variant options as separate meta entries for searchability
     *
     * @param int $post_id WordPress post ID
     * @param array $variants Formatted variants array
     */
    private function saveVariantOptions(int $post_id, array $variants): void {
        // Collect all unique option names and values
        $option_data = [];

        foreach ($variants as $variant) {
            $selected_options = $variant['selected_options'] ?? [];

            foreach ($selected_options as $option) {
                $option_name = $option['name'] ?? '';
                $option_value = $option['value'] ?? '';

                if (empty($option_name)) {
                    continue;
                }

                if (!isset($option_data[$option_name])) {
                    $option_data[$option_name] = [];
                }

                if (!in_array($option_value, $option_data[$option_name])) {
                    $option_data[$option_name][] = $option_value;
                }
            }
        }

        // Save option names
        update_post_meta($post_id, '_shopify_option_names', array_keys($option_data));

        // Save each option type with its values
        foreach ($option_data as $option_name => $values) {
            $meta_key = '_shopify_option_' . sanitize_key(strtolower($option_name));
            update_post_meta($post_id, $meta_key, $values);
        }

        // Save complete option data structure
        update_post_meta($post_id, '_shopify_options', $option_data);
    }

    /**
     * Extract and format variant data
     *
     * @param array $edges Shopify variants edges
     * @return array Formatted variants
     */
    private function extractVariants(array $edges): array {
        return array_map(function($edge) {
            $node = $edge['node'];
            return [
                'id' => $node['id'] ?? '',
                'title' => $node['title'] ?? '',
                'sku' => $node['sku'] ?? '',
                'price' => $node['price'] ?? '',
                'compare_at_price' => $node['compareAtPrice'] ?? '',
                'inventory_quantity' => $node['inventoryQuantity'] ?? 0,
                'available_for_sale' => $node['availableForSale'] ?? false,
                'selected_options' => $node['selectedOptions'] ?? [],
                'image' => $node['image'] ?? null,
                'media' => $this->extractMedia($node['media']['edges'] ?? [])
            ];
        }, $edges);
    }

    /**
     * Extract and format collection data
     *
     * @param array $edges Shopify collections edges
     * @return array Formatted collections
     */
    private function extractCollections(array $edges): array {
        return array_map(function($edge) {
            $collection = [
                'id' => $edge['node']['id'] ?? '',
                'title' => $edge['node']['title'] ?? '',
                'handle' => $edge['node']['handle'] ?? ''
            ];

            // Add optional fields if they exist
            if (isset($edge['node']['description'])) {
                $collection['description'] = $edge['node']['description'];
            }

            if (isset($edge['node']['descriptionHtml'])) {
                $collection['descriptionHtml'] = $edge['node']['descriptionHtml'];
            }

            if (isset($edge['node']['image'])) {
                $collection['image'] = $edge['node']['image'];
            }

            if (isset($edge['node']['updatedAt'])) {
                $collection['updatedAt'] = $edge['node']['updatedAt'];
            }

            return $collection;
        }, $edges);
    }

    /**
     * Extract and format image data
     *
     * @param array $edges Shopify images edges
     * @return array Formatted images
     */
    private function extractImages(array $edges): array {
        return array_map(function($edge) {
            return [
                'url' => $edge['node']['url'] ?? '',
                'alt_text' => $edge['node']['altText'] ?? ''
            ];
        }, $edges);
    }

    /**
     * Extract and format featured media
     *
     * @param array|null $featured_media Shopify featured media
     * @return array|null Formatted featured media
     */
    private function extractFeaturedMedia(?array $featured_media): ?array {
        if (empty($featured_media)) {
            return null;
        }

        return [
            'media_content_type' => $featured_media['mediaContentType'] ?? '',
            'preview' => [
                'url' => $featured_media['preview']['image']['url'] ?? '',
                'alt_text' => $featured_media['preview']['image']['altText'] ?? ''
            ]
        ];
    }

    /**
     * Extract and format media data
     *
     * @param array $edges Shopify media edges
     * @return array Formatted media items
     */
    private function extractMedia(array $edges): array {
        return array_map(function($edge) {
            $node = $edge['node'];
            $media_type = $node['mediaContentType'] ?? '';

            $media_item = [
                'media_content_type' => $media_type
            ];

            // Handle different media types
            switch ($media_type) {
                case 'IMAGE':
                    if (isset($node['image'])) {
                        $media_item['image'] = [
                            'url' => $node['image']['url'] ?? '',
                            'alt_text' => $node['image']['altText'] ?? '',
                            'width' => $node['image']['width'] ?? null,
                            'height' => $node['image']['height'] ?? null
                        ];
                    }
                    break;

                case 'VIDEO':
                    if (isset($node['sources'])) {
                        $media_item['sources'] = $node['sources'];
                    }
                    if (isset($node['preview']['image']['url'])) {
                        $media_item['preview_url'] = $node['preview']['image']['url'];
                    }
                    break;

                case 'EXTERNAL_VIDEO':
                    $media_item['embed_url'] = $node['embedUrl'] ?? '';
                    $media_item['host'] = $node['host'] ?? '';
                    if (isset($node['preview']['image']['url'])) {
                        $media_item['preview_url'] = $node['preview']['image']['url'];
                    }
                    break;

                case 'MODEL_3D':
                    if (isset($node['sources'])) {
                        $media_item['sources'] = $node['sources'];
                    }
                    if (isset($node['preview']['image']['url'])) {
                        $media_item['preview_url'] = $node['preview']['image']['url'];
                    }
                    break;
            }

            return $media_item;
        }, $edges);
    }

    /**
     * Get all shopypress-product post IDs
     *
     * @return array Array of WordPress post IDs
     */
    public function getAllProductIds(): array {
        $query = new \WP_Query([
            'post_type' => ShopyPressProduct::PRODUCT_SLUG,
            'posts_per_page' => -1,
            'fields' => 'ids',
            'post_status' => 'any'
        ]);

        return $query->posts;
    }

    /**
     * Get all Shopify product IDs from WordPress posts
     *
     * @return array Array of Shopify product IDs
     */
    public function getAllShopifyProductIds(): array {
        global $wpdb;

        $results = $wpdb->get_col($wpdb->prepare(
            "SELECT meta_value FROM {$wpdb->postmeta} pm
            INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID
            WHERE p.post_type = %s
            AND pm.meta_key = '_shopify_product_id'",
            ShopyPressProduct::PRODUCT_SLUG
        ));

        return $results;
    }

    /**
     * Force delete a product by post ID
     *
     * @param int $post_id WordPress post ID
     * @return bool True if deleted, false otherwise
     */
    public function forceDelete(int $post_id): bool {
        $result = wp_delete_post($post_id, true);
        return $result !== false && $result !== null;
    }
}
