<script setup>
import {ref, watch, defineModel, defineProps, onMounted, computed} from 'vue';
import SkuInput from "./SkuInput.vue";

const options = defineModel();
const variantsData = defineModel('variantsData');

const props = defineProps({
  variants: {
    type: Array,
    required: true
  },
  selectedVariants: {
    type: Array,
    required: false,
    default: []
  },
  errors: {
    type: Object,
    required: false,
    default: {}
  },
  currentLocale: {
    type: String,
    required: true,
    default: 'nl'
  },
});

const variants = ref([]);
const variantPreviews = ref(props.selectedVariants);

// Compute headers once and keep them fixed (prevents reordering)
const headers = computed(() => {
  return options.value.map(option => ({
    id: option.id,
    name: option.translations[props.currentLocale].name
  }));
});

// Generate all possible combinations dynamically
const generateCombinations = (attributes, index = 0, current = {}) => {
  if (index === attributes.length) {
    return [{optionValues: {...current}, sku: ''}];
  }

  const key = attributes[index].id; // Use UUID for consistency

  return attributes[index].values.flatMap(value => {
    return generateCombinations(attributes, index + 1, {...current, [key]: value});
  });
};

// Function to match generated variants with existing ones
const findExistingVariant = (generatedVariant) => {
  return props.variants.find(existingVariant => {
    // Convert existing optionValues to a comparable format
    const existingOptions = Object.fromEntries(existingVariant.optionValues.map(v => [v.option_id, v.option_value_id]));

    // Convert generated variant options to the same format
    const generatedOptions = Object.fromEntries(Object.entries(generatedVariant.optionValues).map(([option_id, value]) => [option_id, value.id]));

    // Compare both objects
    return JSON.stringify(existingOptions) === JSON.stringify(generatedOptions);
  });
};

// Preserve SKU data and ensure values always stay in correct columns
const updateVariants = () => {
  if (!options.value) return;

  const attributes = options.value.map(option => ({
    id: option.id, // Keep UUID
    name: option.translations[props.currentLocale].name, // UI display only
    values: option.optionValues.map(value => ({
      id: value.id,
      name: value.translations[props.currentLocale].name
    }))
  }));

  // Generate new variants based on reordered options
  const generatedVariants = generateCombinations(attributes);

  // Ensure that the option-value pairs always align with fixed headers
  variants.value = generatedVariants.map(newVariant => {
    const existingVariant = findExistingVariant(newVariant);

    let alignedOptions = [];

    headers.value.forEach(header => {
      if (alignedOptions.find(option => option.option_id === header.id)) {
        return;
      }

      alignedOptions.push({
        option_id: header.id,
        option_value_id: newVariant.optionValues[header.id].id,
        name: header.name,
        value: newVariant.optionValues[header.id].name
      });

      // if (newVariant.optionValues[header.id]) {
      //     alignedOptions[header.id] = newVariant.optionValues[header.id];
      // } else {
      //     alignedOptions[header.id] = {id: '', name: ''}; // Empty placeholder to maintain structure
      // }
    });

    return existingVariant
        ? {...newVariant, sku: existingVariant.sku, optionValues: alignedOptions}
        : {...newVariant, optionValues: alignedOptions};
  });

  variantsData.value = JSON.stringify(variants.value, null, 2);
};

const newVariantSelected = (variant) => {
  variantPreviews.value = [...variantPreviews.value, variant];
};

const variantPreview = (sku) => {
  return variantPreviews.value.find(v => v.sku === sku);
}

const optionLine = (variant) => {
  return headers.value.map(header => {
    return {
      name: header.name,
      value: variant.optionValues.find(v => v.option_id === header.id).value
    }
  });
}

// **Trigger variant generation on mount**
onMounted(() => {
  updateVariants();
});

// **Reactively update variants when options change (including drag & drop reorder)**
watch(options, updateVariants, {deep: true});

// **Update textarea when SKU is edited**
watch(variants, () => {
  variantsData.value = JSON.stringify(variants.value, null, 2);
}, {deep: true});
</script>

<template>
  <div class="mt-12">
    <h2 class="mb-6">{{ __('daylight::store.product_variations') }}</h2>

    <table class="-mx-2">
      <thead>
      <tr class="font-semibold">
        <td class="text-sm px-2">{{ __('daylight::store.option') }}</td>
        <td class="text-sm px-2">{{ __('daylight::general.sku') }}</td>
        <td class="text-sm px-2" width="220">{{ __('daylight::store.variant') }}</td>
        <!--                <td class="text-sm px-2">Media</td>-->
      </tr>
      </thead>
      <tbody>
      <tr v-for="(variant, index) in variants" :key="index">
        <td class="text-sm px-2 w-[150px]">
          <div class="py-2" v-html="optionLine(variant).map(line => line.value).join(' / ')"/>
        </td>
        <td class="px-2 py-2 w-[220px]">
          <SkuInput
              class="mr-4"
              v-model="variant.sku"
              :error="errors['variants.'+index+'.sku'] ? errors['variants.'+index+'.sku'][0] : null"
              @variantSelected="newVariantSelected"
          />
        </td>
        <td class="px-2 max-w-[280px]">
          <div v-if="variantPreview(variant.sku)" class="flex w-full truncate whitespace-nowrap">
            <div class="w-12 flex-0 min-w-12">
              <div v-if="!variantPreview(variant.sku).image"
                   class="w-10 h-10 flex items-center justify-center text-gray-500 rounded border mr-1 bg-gray-100">
                <svg class="w-4 h-4" data-slot="icon" fill="none" stroke-width="1.5" stroke="currentColor"
                     viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                  <path stroke-linecap="round" stroke-linejoin="round"
                        d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z"></path>
                </svg>
              </div>
              <img v-else :src="variantPreview(variant.sku).image" :alt="variantPreview(variant.sku).name"
                   class="object-cover w-10 h-10 rounded border mr-1">
            </div>
            <div class="flex-0 truncate">
              <p class="text-sm">{{ variantPreview(variant.sku).sku }}</p>
              <p class="text-xs opacity-50 truncate">{{ variantPreview(variant.sku).name }}</p>
            </div>
          </div>
        </td>
      </tr>
      </tbody>

    </table>
  </div>
</template>
