<?php

namespace Meliconnect\Meliconnect\Core\Services;

if (! defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

use Meliconnect\Meliconnect\Core\Helpers\Helper;
use Meliconnect\Meliconnect\Core\Helpers\MeliconMeli;
use Meliconnect\Meliconnect\Core\Helpers\SyncHashHelper;

class SyncContextResolver
{

    public static function build($item, $log_channel = 'sync-cron')
    {
        $woo = wc_get_product(
            $item->woo_variation_id ?: $item->woo_product_id
        );

        if (!$woo) {

            Helper::logData([
                'message' => 'Woo product not found',
                'item_id' => $item->id,
            ], $log_channel);

            return null;
        }

        $meliRaw = self::fetchMeliItem(
            $item->meli_item_id,
            $item->meli_seller_id
        );

        if (!$meliRaw) {

            Helper::logData([
                'message' => 'Meli item not found',
                'item_id' => $item->id,
            ], $log_channel);

            return null;
        }

        /* Helper::logData([
            'message' => 'Build sync context',
            'woo_id' => $woo->get_id(),
            'woo_type' => $woo->get_type(),
            'meli_item_id' => $meliRaw->id ?? null,
            'meli_has_variations' => !empty($meliRaw->variations),
            'meli_family_id' => $meliRaw->family_id ?? null,
        ], $log_channel); */

        $meliVariation = null;

        // ==================================================
        // CASE 1:
        // Woo variation child
        // ==================================================
        if ($woo->is_type('variation')) {

            /* Helper::logData([
                'message' => 'Woo variation detected'
            ], $log_channel); */

            $meliVariation = self::resolveMeliVariation(
                $meliRaw,
                $woo
            );
        }

        // ==================================================
        // CASE 2:
        // Woo variable parent
        // ==================================================
        elseif ($woo->is_type('variable')) {

            /* Helper::logData([
                'message' => 'Woo variable parent detected'
            ], $log_channel); */

            // =============================================
            // CASE 2A:
            // ML item with internal variations
            // =============================================
            if (!empty($meliRaw->variations)) {

                Helper::logData([
                    'message' => 'Resolving using ML variations'
                ], $log_channel);

                foreach ($meliRaw->variations as $variation) {

                    $wooVariation = self::resolveWooVariationFromMeliVariation(
                        $woo,
                        $variation,
                        $log_channel
                    );

                    if ($wooVariation) {

                        $woo = $wooVariation;

                        $meliVariation = $variation;

                        $item->woo_variation_id = $wooVariation->get_id();

                        self::persistVariationMapping(
                            $item->id,
                            $wooVariation->get_id(),
                            $variation->id,
                            $meliRaw->id
                        );

                        Helper::logData([
                            'message' => 'Resolved Woo variation from ML variation',
                            'woo_variation_id' => $wooVariation->get_id(),
                            'meli_variation_id' => $variation->id,
                        ], $log_channel);

                        break;
                    }
                }
            }

            // =============================================
            // CASE 2B:
            // ML family item WITHOUT variations
            // =============================================
            elseif (!empty($meliRaw->family_id)) {

                /* Helper::logData([
                    'message' => 'Family item without variations'
                ], $log_channel); */

                foreach ($woo->get_children() as $variationId) {

                    $mappedItemId = get_post_meta($variationId,'meliconnect_meli_asoc_variation_id',true);

                    /* Helper::logData([
                        'message' => 'Checking Woo variation',
                        'woo_variation_id' => $variationId,
                        'mapped_item_id' => $mappedItemId,
                        'meli_item_id' => $meliRaw->id
                    ], $log_channel); */

                    if (
                        $mappedItemId &&
                        (string)$mappedItemId === (string)$meliRaw->id
                    ) {
                        /* Helper::logData([
                            'message' => 'Resolved Woo variation from ML family item',
                            'woo_variation_id' => $variationId,
                        ]);
 */
                        $wooVariation = wc_get_product($variationId);

                        if ($wooVariation) {

                            self::persistVariationMapping(
                                $item->id,
                                $wooVariation->get_id(),
                                null,
                                $meliRaw->id
                            );
                            
                            Helper::logData([
                                'message' => 'Resolved Woo variation from ML family item',
                                'woo_variation_id' => $wooVariation->get_id(),
                            ], $log_channel);

                            $woo = $wooVariation;

                            $item->woo_variation_id = $wooVariation->get_id();

                            break;
                        }
                    }
                }
            }
        }

        // ==================================================
        // CASE 3:
        // simple/simple fallback
        // ==================================================
        else {

            Helper::logData([
                'message' => 'Simple product sync context'
            ], $log_channel);
        }

        /* Helper::logData([
            'message' => 'Resolved sync context',
            'sync_state_id' => $item->id,
            'woo_product_id' => $item->woo_product_id,
            'woo_variation_id' => $item->woo_variation_id,
            'meli_item_id' => $meliRaw->id ?? null,
            'meli_variation_id' => $meliVariation->id ?? null,
            'meli_family_id' => $meliRaw->family_id ?? null,
        ], $log_channel); */

        $meli = SyncHashHelper::normalizeMeliItem(
            $meliRaw,
            $meliVariation
        );

        return [
            'woo' => $woo,
            'meli_raw' => $meliRaw,
            'meli_variation' => $meliVariation,
            'meli' => $meli,
        ];
    }



    private static function resolveWooVariationFromMeliVariation(
        $wooParent,
        $meliVariation,
        $log_channel = 'sync-cron'
    ) {

        if (
            !$wooParent ||
            !$wooParent->is_type('variable')
        ) {
            return null;
        }

        $meliAttrs = self::getMeliVariationAttributes(
            $meliVariation
        );

        $wooFamilyId = get_post_meta(
            $wooParent->get_id(),
            'meliconnect_meli_family_id',
            true
        );

        $meliFamilyId = $meliVariation->family_id ?? null;

        if (
            $wooFamilyId &&
            $meliFamilyId &&
            (string)$wooFamilyId !== (string)$meliFamilyId
        ) {
            Helper::logData([
                'message' => 'Family mismatch',
                'woo_family_id' => $wooFamilyId,
                'meli_family_id' => $meliFamilyId
            ], $log_channel);

            return null;
        }

        foreach ($wooParent->get_children() as $variationId) {

            $wooVariation = wc_get_product($variationId);

            if (!$wooVariation) {
                continue;
            }

            // =====================================
            // FAST PATH → variation_id
            // =====================================
            $mappedVariationId = get_post_meta(
                $variationId,
                'meliconnect_meli_asoc_variation_id',
                true
            );

            if (
                $mappedVariationId &&
                (string)$mappedVariationId === (string)$meliVariation->id
            ) {

                return $wooVariation;
            }

            // =====================================
            // FALLBACK → attributes
            // =====================================
            $wooAttrs = self::getWooVariationAttributes(
                $wooVariation
            );

            if ($wooAttrs === $meliAttrs) {

                Helper::logData([
                    'message' => 'Variation matched by attributes',
                    'woo_variation_id' => $wooVariation->get_id(),
                    'meli_variation_id' => $meliVariation->id,
                    'woo_attrs' => $wooAttrs,
                    'meli_attrs' => $meliAttrs,
                ], $log_channel);

                // persist cache
                update_post_meta(
                    $variationId,
                    'meliconnect_meli_asoc_variation_id',
                    $meliVariation->id
                );

                return $wooVariation;
            }
        }

        return null;
    }

    private static function persistVariationMapping(
        $syncStateId,
        $wooVariationId,
        $meliVariationId = null,
        $meliItemId = null
    ) {

        if (
            empty($syncStateId) ||
            empty($wooVariationId)
        ) {
            return;
        }

        global $wpdb;

        $data = [
            'woo_variation_id' => $wooVariationId,
            'updated_at'       => current_time('mysql'),
        ];

        if ($meliVariationId) {
            $data['meli_variation_id'] = $meliVariationId;

            update_post_meta(
                $wooVariationId,
                'meliconnect_meli_asoc_variation_id',
                $meliVariationId
            );
        }

        if ($meliItemId) {

            update_post_meta(
                $wooVariationId,
                'meliconnect_meli_asoc_listing_id',
                $meliItemId
            );
        }

        $wpdb->update(
            $wpdb->prefix . 'meliconnect_sync_state',
            $data,
            [
                'id' => $syncStateId
            ]
        );
    }
    public static function resolveMeliVariation($meliRaw, $woo)
    {
        if (
            !$woo ||
            !$woo->is_type('variation') ||
            empty($meliRaw->variations)
        ) {
            return null;
        }

        $mappedVariationId = get_post_meta(
            $woo->get_id(),
            'meliconnect_meli_asoc_variation_id',
            true
        );

        $wooAttrs = self::getWooVariationAttributes($woo);

        foreach ($meliRaw->variations as $variation) {

            // =====================================
            // FAST PATH
            // =====================================
            if (
                $mappedVariationId &&
                (string)$variation->id === (string)$mappedVariationId
            ) {

                return $variation;
            }

            // =====================================
            // FALLBACK ATTRIBUTES
            // =====================================
            $meliAttrs = self::getMeliVariationAttributes($variation);

            if ($wooAttrs === $meliAttrs) {



                update_post_meta(
                    $woo->get_id(),
                    'meliconnect_meli_asoc_variation_id',
                    $variation->id
                );

                return $variation;
            }
        }

        return null;
    }

    private static function fetchMeliItem($meli_id, $seller_id)
    {
        if (empty($seller_id) || empty($meli_id)) {
            return null;
        }

        $seller = \Meliconnect\Meliconnect\Core\Models\UserConnection::getUser($seller_id);

        if (!$seller || empty($seller->access_token)) {
            return null;
        }

        $res = MeliconMeli::getWithHeader(
            'items/' . $meli_id,
            $seller->access_token
        );

        if (is_wp_error($res)) {
            return null;
        }

        return $res['body'] ?? null;
    }


    public static function buildSeedContext($product_id, $meli_id, $seller_id)
    {
        $fakeItem = (object) [
            'id' => 0,
            'woo_product_id' => $product_id,
            'woo_variation_id' => null,
            'meli_item_id' => $meli_id,
            'meli_seller_id' => $seller_id,
            'sync_type' => 'full',
        ];

        return self::build($fakeItem);
    }

    private static function getMeliVariationAttributes($meliVariation)
    {
        $attrs = [];

        foreach (($meliVariation->attribute_combinations ?? []) as $attr) {

            $attrs[strtoupper($attr->id)] = self::normalizeAttrValue(
                $attr->value_name
            );
        }

        ksort($attrs);

        return $attrs;
    }

    private static function getWooVariationAttributes($wooVariation)
    {
        $attrs = [];

        foreach ($wooVariation->get_attributes() as $key => $value) {

            $taxonomy = str_replace('attribute_', '', $key);

            // SI es taxonomía global
            if (taxonomy_exists($taxonomy)) {

                $term = get_term_by('slug', $value, $taxonomy);

                if ($term) {
                    $value = $term->name;
                }
            }

            $key = strtoupper(
                str_replace('attribute_pa_', '', $key)
            );

            $attrs[$key] = self::normalizeAttrValue($value);
        }

        ksort($attrs);

        return $attrs;
    }

    private static function normalizeAttrValue($value)
    {
        $value = wc_clean($value);

        $value = remove_accents($value);

        $value = strtolower($value);

        $value = str_replace('-', ' ', $value);

        $value = preg_replace('/\s+/', ' ', $value);

        return trim($value);
    }
}
