<script setup lang="ts">
import { useQuery } from '@vue/apollo-composable';
import {
  CatalogProductTypeSettingsDocument,
  ClientProductsDocument,
  type CatalogProductTypeSettingsQuery,
  type ClientProductsQuery,
} from '~/composables/graphql/generated';
import { useClientCart } from '~/composables/useClientCart';

const props = defineProps<{
  productTypeSlug: string;
}>();

type ProductNode = ClientProductsQuery['clientProducts'][number];
type CatalogProductTypeSettingNode = CatalogProductTypeSettingsQuery['catalogProductTypeSettings'][number];
type ParamFieldKey = 'widthMm' | 'lengthM' | 'thicknessMicron' | 'sleeveBrand' | 'quantityPerBox' | 'colorTag' | 'labelTag';
type ParamValue = number | string;

type ParsedProduct = ProductNode & {
  productTypeLabel: string;
  quantityPerBoxOptions: string[];
  normalizedTags: string[];
  colorTags: string[];
  labelTags: string[];
};

type ProductGroup = {
  key: string;
  typeLabel: string;
  products: ParsedProduct[];
};

type GroupState = {
  widthMm: number | null;
  lengthM: number | null;
  thicknessMicron: number | null;
  sleeveBrand: string | null;
  quantityPerBox: string | null;
  colorTag: string | null;
  labelTag: string | null;
};

const COLOR_TAGS = ['прозрачный', 'коричневый', 'белый', 'черный', 'желтый', 'зеленый', 'красный', 'синий', 'оранжевый', 'красно-белый'];
const LABEL_TAGS = ['хрупкое', 'подарок', 'акция'];
const PARAM_KEYS: ParamFieldKey[] = ['widthMm', 'lengthM', 'thicknessMicron', 'sleeveBrand', 'quantityPerBox', 'colorTag', 'labelTag'];
const DEFAULT_CATALOG_PRODUCT_TYPE_SETTING: CatalogProductTypeSettingNode = {
  productType: '',
  showQuantityPerBox: false,
  allowCustomLength: false,
  customLengthMinM: null,
  customLengthMaxM: null,
  customLengthStepM: null,
  allowCustomSleeveBrand: false,
  allowCustomLabel: false,
  widthOptionsMm: [],
  lengthOptionsM: [],
  thicknessOptionsMicron: [],
  sleeveOptions: [],
  colorOptions: [],
  labelOptions: [],
};
const parameterFields: Array<{ key: ParamFieldKey; label: string }> = [
  { key: 'widthMm', label: 'Ширина' },
  { key: 'lengthM', label: 'Длина' },
  { key: 'thicknessMicron', label: 'Толщина' },
  { key: 'sleeveBrand', label: 'Втулка' },
  { key: 'quantityPerBox', label: 'Короб' },
  { key: 'colorTag', label: 'Цвет' },
  { key: 'labelTag', label: 'Надпись' },
];

const coverPresets = [
  ['#d9f5e6', '#9ce8c1', '#6fd09d'],
  ['#eaf9ef', '#b3e8cb', '#76c89f'],
  ['#e8f5ec', '#b2e0c6', '#7dd0a9'],
];

const productsQuery = useQuery(ClientProductsDocument);
const catalogSettingsQuery = useQuery(CatalogProductTypeSettingsDocument);
const groupStates = reactive<Record<string, GroupState>>({});
const { addProduct, getQuantity, incrementQuantity, decrementQuantity } = useClientCart();

const loading = computed(() => productsQuery.loading.value || catalogSettingsQuery.loading.value);
const error = computed(() => productsQuery.error.value || catalogSettingsQuery.error.value);

const catalogSettingsByType = computed<Record<string, CatalogProductTypeSettingNode>>(() => (
  Object.fromEntries(
    (catalogSettingsQuery.result.value?.catalogProductTypeSettings ?? [])
      .map((setting) => [setting.productType, setting]),
  )
));

function normalizeText(value: string | null | undefined) {
  return String(value ?? '').replaceAll(/\s+/g, ' ').trim();
}

function splitBoxValues(value: string | null | undefined) {
  return normalizeText(value)
    .split('/')
    .map((item) => item.trim())
    .filter(Boolean);
}

function createProductCover(name: string, sku: string) {
  const seed = `${name}${sku}`.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
  const [start, middle, finish] = coverPresets[seed % coverPresets.length];
  const firstLetter = name.trim().charAt(0).toUpperCase() || 'P';

  const svg = `
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 220">
      <defs>
        <linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stop-color="${start}" />
          <stop offset="55%" stop-color="${middle}" />
          <stop offset="100%" stop-color="${finish}" />
        </linearGradient>
      </defs>
      <rect width="320" height="220" fill="url(#g)" rx="22" />
      <g opacity="0.15">
        <circle cx="266" cy="45" r="55" fill="#0f7a49" />
        <circle cx="42" cy="198" r="55" fill="#0f7a49" />
      </g>
      <text x="50%" y="56%" text-anchor="middle" fill="#11412c" font-family="Manrope, sans-serif" font-size="84" font-weight="700">${firstLetter}</text>
    </svg>
  `.trim();

  return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
}

function hydrateProduct(product: ProductNode): ParsedProduct {
  const normalizedTags = product.tags.map((tag) => normalizeText(tag)).filter(Boolean).sort((a, b) => a.localeCompare(b, 'ru'));

  return {
    ...product,
    productTypeLabel: normalizeText(product.productType) || 'Без типа',
    quantityPerBoxOptions: splitBoxValues(product.quantityPerBox),
    normalizedTags,
    colorTags: normalizedTags.filter((tag) => COLOR_TAGS.includes(tag)),
    labelTags: normalizedTags.filter((tag) => LABEL_TAGS.includes(tag)),
  };
}

function productSortValue(value: number | null | undefined) {
  return value ?? Number.MAX_SAFE_INTEGER;
}

function compareProducts(a: ParsedProduct, b: ParsedProduct) {
  const byWidth = productSortValue(a.widthMm) - productSortValue(b.widthMm);
  if (byWidth !== 0) {
    return byWidth;
  }

  const byLength = productSortValue(a.lengthM) - productSortValue(b.lengthM);
  if (byLength !== 0) {
    return byLength;
  }

  const byThickness = productSortValue(a.thicknessMicron) - productSortValue(b.thicknessMicron);
  if (byThickness !== 0) {
    return byThickness;
  }

  const bySleeve = normalizeText(a.sleeveBrand).localeCompare(normalizeText(b.sleeveBrand), 'ru');
  if (bySleeve !== 0) {
    return bySleeve;
  }

  return a.sku.localeCompare(b.sku, 'ru');
}

const parsedProducts = computed<ParsedProduct[]>(() => {
  const list = productsQuery.result.value?.clientProducts ?? [];

  return list
    .map(hydrateProduct)
    .sort(compareProducts);
});

const productGroups = computed<ProductGroup[]>(() => {
  const map = new Map<string, ParsedProduct[]>();

  for (const product of parsedProducts.value) {
    const existing = map.get(product.productTypeLabel);
    if (existing) {
      existing.push(product);
    } else {
      map.set(product.productTypeLabel, [product]);
    }
  }

  return [...map.entries()]
    .sort((a, b) => a[0].localeCompare(b[0], 'ru'))
    .map(([typeLabel, products]) => ({
      key: typeLabel
        .toLowerCase()
        .replaceAll(/[^a-z0-9а-яё]+/gi, '-')
        .replaceAll(/-+/g, '-')
        .replaceAll(/^-|-$/g, ''),
      typeLabel,
      products: [...products].sort(compareProducts),
    }));
});

function sortParamValues(values: ParamValue[]) {
  return [...values].sort((a, b) => {
    if (typeof a === 'number' && typeof b === 'number') {
      return a - b;
    }
    return String(a).localeCompare(String(b), 'ru');
  });
}

function getAllFieldOptions(group: ProductGroup, field: ParamFieldKey) {
  const values = new Set<ParamValue>();

  for (const product of group.products) {
    if (field === 'quantityPerBox') {
      for (const option of product.quantityPerBoxOptions) {
        values.add(option);
      }
      continue;
    }

    if (field === 'colorTag') {
      for (const tag of product.colorTags) {
        values.add(tag);
      }
      continue;
    }

    if (field === 'labelTag') {
      for (const tag of product.labelTags) {
        values.add(tag);
      }
      continue;
    }

    const value = product[field];
    if (value !== null && value !== undefined) {
      values.add(value);
    }
  }

  return sortParamValues([...values]);
}

function groupCatalogSetting(group: ProductGroup) {
  return catalogSettingsByType.value[group.typeLabel] ?? {
    ...DEFAULT_CATALOG_PRODUCT_TYPE_SETTING,
    productType: group.typeLabel,
  };
}

function visibleFields(group: ProductGroup) {
  return parameterFields.filter((field) => {
    if (field.key === 'quantityPerBox') {
      return false;
    }

    return getAllFieldOptions(group, field.key).length > 1;
  });
}

const selectedGroup = computed(() => productGroups.value.find((group) => group.key === props.productTypeSlug) ?? null);
const currentGroupIndex = computed(() => productGroups.value.findIndex((group) => group.key === props.productTypeSlug));
const previousGroup = computed(() => {
  if (currentGroupIndex.value <= 0) {
    return null;
  }

  return productGroups.value[currentGroupIndex.value - 1] ?? null;
});
const nextGroup = computed(() => {
  if (currentGroupIndex.value < 0 || currentGroupIndex.value >= productGroups.value.length - 1) {
    return null;
  }

  return productGroups.value[currentGroupIndex.value + 1] ?? null;
});

function requiredKeys(group: ProductGroup) {
  return visibleFields(group).map((field) => field.key);
}

function createGroupState(group: ProductGroup): GroupState {
  const firstProduct = group.products[0];

  return {
    widthMm: firstProduct?.widthMm ?? null,
    lengthM: firstProduct?.lengthM ?? null,
    thicknessMicron: firstProduct?.thicknessMicron ?? null,
    sleeveBrand: firstProduct?.sleeveBrand ?? null,
    quantityPerBox: firstProduct?.quantityPerBoxOptions[0] ?? null,
    colorTag: firstProduct?.colorTags[0] ?? null,
    labelTag: firstProduct?.labelTags[0] ?? null,
  };
}

watch(
  productGroups,
  (groups) => {
    const keys = new Set(groups.map((group) => group.key));

    for (const key of Object.keys(groupStates)) {
      if (!keys.has(key)) {
        Reflect.deleteProperty(groupStates, key);
      }
    }

    for (const group of groups) {
      groupStates[group.key] ??= createGroupState(group);
    }
  },
  { immediate: true },
);

function getGroupState(group: ProductGroup) {
  groupStates[group.key] ??= createGroupState(group);
  return groupStates[group.key];
}

function matchesProductState(product: ParsedProduct, state: GroupState, keys: ParamFieldKey[]) {
  return keys.every((key) => {
    if (state[key] === null) {
      return true;
    }

    if (key === 'quantityPerBox') {
      return product.quantityPerBoxOptions.includes(String(state[key]));
    }

    if (key === 'colorTag') {
      return product.colorTags.includes(String(state[key]));
    }

    if (key === 'labelTag') {
      return product.labelTags.includes(String(state[key]));
    }

    return product[key] === state[key];
  });
}

function selectedProduct(group: ProductGroup) {
  const keys = requiredKeys(group);
  const state = getGroupState(group);

  if (keys.length === 0) {
    return group.products[0] ?? null;
  }

  if (keys.some((key) => state[key] === null)) {
    return null;
  }

  const matches = group.products.filter((product) => matchesProductState(product, state, keys));
  return matches[0] ?? null;
}

function formatOptionLabel(field: ParamFieldKey, value: ParamValue) {
  if (field === 'widthMm') {
    return `${value} мм`;
  }
  if (field === 'lengthM') {
    return `${value} м`;
  }
  if (field === 'thicknessMicron') {
    return `${value} мкм`;
  }
  return String(value);
}

function productHasOption(product: ParsedProduct, field: ParamFieldKey, option: ParamValue) {
  if (field === 'quantityPerBox') {
    return product.quantityPerBoxOptions.includes(String(option));
  }

  if (field === 'colorTag') {
    return product.colorTags.includes(String(option));
  }

  if (field === 'labelTag') {
    return product.labelTags.includes(String(option));
  }

  return product[field] === option;
}

function isOptionAvailable(group: ProductGroup, field: ParamFieldKey, option: ParamValue) {
  const state = getGroupState(group);
  const scopedState = {
    ...state,
    [field]: option,
  } satisfies GroupState;

  return group.products.some((product) => matchesProductState(product, scopedState, requiredKeys(group)));
}

function pickBestProductForOption(group: ProductGroup, field: ParamFieldKey, option: ParamValue) {
  const state = getGroupState(group);
  const candidates = group.products.filter((product) => productHasOption(product, field, option));

  if (candidates.length === 0) {
    return null;
  }

  return [...candidates].sort((a, b) => {
    let aScore = 0;
    let bScore = 0;

    for (const key of PARAM_KEYS) {
      if (key === field) {
        continue;
      }

      const selectedValue = state[key];
      if (selectedValue === null) {
        continue;
      }

      if (productHasOption(a, key, selectedValue)) {
        aScore += 1;
      }
      if (productHasOption(b, key, selectedValue)) {
        bScore += 1;
      }
    }

    if (aScore !== bScore) {
      return bScore - aScore;
    }

    return compareProducts(a, b);
  })[0];
}

function applyProductToState(state: GroupState, product: ParsedProduct, preferredBoxOption: ParamValue | null = null) {
  state.widthMm = product.widthMm ?? null;
  state.lengthM = product.lengthM ?? null;
  state.thicknessMicron = product.thicknessMicron ?? null;
  state.sleeveBrand = product.sleeveBrand ?? null;
  state.colorTag = product.colorTags[0] ?? null;
  state.labelTag = product.labelTags[0] ?? null;

  if (preferredBoxOption !== null && product.quantityPerBoxOptions.includes(String(preferredBoxOption))) {
    state.quantityPerBox = String(preferredBoxOption);
    return;
  }

  state.quantityPerBox = product.quantityPerBoxOptions[0] ?? null;
}

function updateField(group: ProductGroup, field: ParamFieldKey, value: ParamValue) {
  const state = getGroupState(group);
  const fallback = pickBestProductForOption(group, field, value);
  if (!fallback) {
    return;
  }

  applyProductToState(state, fallback, field === 'quantityPerBox' ? value : state.quantityPerBox);

  if (field === 'quantityPerBox') {
    state.quantityPerBox = String(value);
    return;
  }

  state[field] = value as GroupState[typeof field];
}

function articleLabel(group: ProductGroup) {
  return selectedProduct(group)?.sku ?? '—';
}

function formatLengthRange(setting: CatalogProductTypeSettingNode) {
  if (!setting.customLengthMinM || !setting.customLengthMaxM || !setting.customLengthStepM) {
    return null;
  }

  return `${setting.customLengthMinM}-${setting.customLengthMaxM} м, шаг ${setting.customLengthStepM} м`;
}

function fieldHelperText(group: ProductGroup, field: ParamFieldKey) {
  const setting = groupCatalogSetting(group);

  if (field === 'widthMm') {
    return 'Ширина рулона. От неё зависит, насколько широкую полосу материала вы получите.';
  }

  if (field === 'lengthM') {
    const customRange = formatLengthRange(setting);
    if (setting.allowCustomLength && customRange) {
      return `Выберите стандартную длину или закажите свою. Доступный диапазон: ${customRange}.`;
    }

    return 'Длина рулона в метрах. Здесь выбирается стандартный доступный размер.';
  }

  if (field === 'thicknessMicron') {
    return 'Толщина материала. Чем выше значение, тем плотнее и заметнее сама лента.';
  }

  if (field === 'sleeveBrand') {
    if (setting.allowCustomSleeveBrand) {
      return 'Тип втулки внутри рулона. При необходимости можем сделать втулку с вашим логотипом.';
    }

    return 'Тип втулки внутри рулона. Выберите подходящий стандартный вариант.';
  }

  if (field === 'colorTag') {
    return 'Цвет или визуальное исполнение ленты. Он влияет на внешний вид готового продукта.';
  }

  if (field === 'labelTag') {
    if (setting.allowCustomLabel) {
      return 'Готовая надпись или маркировка. Если нужно, можем нанести и вашу собственную надпись.';
    }

    return 'Готовая надпись или маркировка на ленте для стандартных сценариев использования.';
  }

  return 'Выберите подходящий параметр для этой позиции.';
}

function customizationDetails(group: ProductGroup) {
  const setting = groupCatalogSetting(group);
  const details: string[] = [];
  const customRange = formatLengthRange(setting);

  if (setting.allowCustomLength && customRange) {
    details.push(`Длина под заказ: ${customRange}.`);
  }

  if (setting.allowCustomSleeveBrand) {
    details.push('Втулка под заказ: можно сделать с вашим логотипом.');
  }

  if (setting.allowCustomLabel) {
    details.push('Надпись под заказ: можно нанести вашу маркировку или текст.');
  }

  return details;
}

function incrementProduct(product: ProductNode) {
  if (getQuantity(product.id) === 0) {
    addProduct({
      id: product.id,
      name: product.name,
      sku: product.sku,
      isCustomizable: product.isCustomizable,
    });
    return;
  }

  incrementQuantity(product.id);
}

function decrementProduct(productId: string) {
  decrementQuantity(productId);
}

function selectedQty(group: ProductGroup) {
  const product = selectedProduct(group);
  return product ? getQuantity(product.id) : 0;
}

function incrementSelected(group: ProductGroup) {
  const product = selectedProduct(group);
  if (product) {
    incrementProduct(product);
  }
}

function decrementSelected(group: ProductGroup) {
  const product = selectedProduct(group);
  if (product) {
    decrementProduct(product.id);
  }
}

function productDetailPath(group: ProductGroup) {
  return `/products/${group.key}`;
}
</script>

<template>
  <section class="space-y-5">
    <div v-if="loading" class="alert surface-card border-0">Загрузка каталога...</div>
    <div v-else-if="error" class="alert alert-error">{{ error.message }}</div>
    <div v-else-if="selectedGroup" class="space-y-4">
      <NuxtLink
        v-if="previousGroup"
        :to="productDetailPath(previousGroup)"
        class="fixed left-6 top-1/2 z-10 hidden h-12 w-12 -translate-y-1/2 items-center justify-center rounded-full border border-[#dce9e1] bg-white text-xl text-[#163624] shadow-[0_12px_28px_rgba(18,56,36,0.08)] 2xl:flex"
        aria-label="Предыдущий товар"
      >
        ←
      </NuxtLink>

      <NuxtLink
        v-if="nextGroup"
        :to="productDetailPath(nextGroup)"
        class="fixed right-6 top-1/2 z-10 hidden h-12 w-12 -translate-y-1/2 items-center justify-center rounded-full border border-[#dce9e1] bg-white text-xl text-[#163624] shadow-[0_12px_28px_rgba(18,56,36,0.08)] 2xl:flex"
        aria-label="Следующий товар"
      >
        →
      </NuxtLink>

      <div class="flex items-center justify-between gap-3">
        <NuxtLink to="/products" class="btn btn-ghost rounded-full px-3 text-[#163624]">
          ← Назад
        </NuxtLink>

        <div class="flex items-center gap-2">
          <NuxtLink
            v-if="previousGroup"
            :to="productDetailPath(previousGroup)"
            class="btn btn-ghost btn-circle"
            aria-label="Предыдущий товар"
          >
            ←
          </NuxtLink>
          <NuxtLink
            v-if="nextGroup"
            :to="productDetailPath(nextGroup)"
            class="btn btn-ghost btn-circle"
            aria-label="Следующий товар"
          >
            →
          </NuxtLink>
        </div>
      </div>

      <div class="space-y-4">
        <div class="rounded-[28px] border border-[#e6efe9] bg-white p-5 md:p-7">
          <h1 class="text-3xl font-bold text-[#163624]">{{ selectedGroup.typeLabel }}</h1>

          <div v-if="customizationDetails(selectedGroup).length" class="mt-4 flex flex-wrap gap-2">
            <span
              v-for="note in customizationDetails(selectedGroup)"
              :key="`${selectedGroup.key}-${note}`"
              class="rounded-full border border-[#dce9e1] bg-white px-3 py-1 text-xs font-semibold text-[#355947]"
            >
              {{ note }}
            </span>
          </div>
        </div>

        <div class="space-y-3">
          <article
            v-for="field in visibleFields(selectedGroup)"
            :key="`${selectedGroup.key}-${field.key}`"
            class="rounded-[24px] border border-[#e6efe9] bg-white p-5"
          >
            <div class="space-y-4">
              <div class="space-y-2">
                <h2 class="text-lg font-semibold text-[#163624]">{{ field.label }}</h2>
                <p class="text-sm leading-6 text-[#5d7468]">{{ fieldHelperText(selectedGroup, field.key) }}</p>
              </div>

              <div class="flex flex-wrap gap-2">
                <label
                  v-for="option in getAllFieldOptions(selectedGroup, field.key)"
                  :key="`${selectedGroup.key}-${field.key}-${option}`"
                  class="btn btn-sm rounded-full text-sm normal-case shadow-none transition"
                  :class="[
                    getGroupState(selectedGroup)[field.key] === option
                      ? 'bg-neutral text-neutral-content'
                      : isOptionAvailable(selectedGroup, field.key, option)
                        ? 'bg-base-100 text-base-content hover:bg-base-200'
                        : 'bg-[#eef1f4] text-[#7b8591] hover:bg-[#e3e7eb]',
                    'cursor-pointer',
                  ]"
                >
                  <input
                    type="radio"
                    class="sr-only"
                    :name="`${selectedGroup.key}-${field.key}`"
                    :checked="getGroupState(selectedGroup)[field.key] === option"
                    @change="updateField(selectedGroup, field.key, option)"
                  >
                  <span>{{ formatOptionLabel(field.key, option) }}</span>
                </label>
              </div>
            </div>
          </article>

          <article class="rounded-[24px] border border-[#e6efe9] bg-white p-5">
            <div class="space-y-4">
              <div class="space-y-1">
                <h2 class="text-lg font-semibold text-[#163624]">В корзину</h2>
                <p class="text-sm leading-6 text-[#5d7468]">
                  Артикул: <span class="font-semibold text-[#163624]">{{ articleLabel(selectedGroup) }}</span>
                </p>
              </div>

              <button
                v-if="selectedQty(selectedGroup) === 0"
                class="btn h-11 rounded-full border-0 bg-[#139957] px-6 text-sm font-semibold text-white hover:bg-[#0d854a]"
                :disabled="!selectedProduct(selectedGroup)"
                @click="incrementSelected(selectedGroup)"
              >
                В корзину
              </button>

              <div v-else class="inline-flex rounded-[22px] border border-base-300 bg-base-100 px-2 py-1">
                <div class="flex items-center justify-between gap-2">
                  <button
                    class="btn btn-square btn-sm"
                    :disabled="selectedQty(selectedGroup) === 0"
                    @click="decrementSelected(selectedGroup)"
                  >
                    -
                  </button>
                  <div class="min-w-10 text-center text-lg font-semibold text-[#163624]">{{ selectedQty(selectedGroup) }}</div>
                  <button class="btn btn-square btn-sm" :disabled="!selectedProduct(selectedGroup)" @click="incrementSelected(selectedGroup)">
                    +
                  </button>
                </div>
              </div>
            </div>
          </article>

          <article class="rounded-[24px] border border-[#e6efe9] bg-white p-5">
            <div class="space-y-4">
              <div class="space-y-1">
                <h2 class="text-lg font-semibold text-[#163624]">Товар в наличии</h2>
                <p class="text-sm leading-6 text-[#5d7468]">
                  Все доступные варианты по этому типу товара.
                </p>
              </div>

              <div class="overflow-x-auto rounded-[20px] border border-[#edf4ef] bg-white">
                <table class="table border-separate border-spacing-0 bg-white [&_tbody_tr:hover]:bg-white [&_tbody_tr]:bg-white [&_td]:bg-white [&_th]:bg-white [&_thead_tr]:bg-white">
                  <thead>
                    <tr>
                      <th class="border-b border-base-300">Артикул</th>
                      <th class="border-b border-base-300">Ширина</th>
                      <th class="border-b border-base-300">Длина</th>
                      <th class="border-b border-base-300">Толщина</th>
                      <th class="border-b border-base-300">Втулка</th>
                      <th class="border-b border-base-300 text-right">Действие</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="product in selectedGroup.products" :key="`${selectedGroup.key}-${product.id}`">
                      <td class="border-b border-base-200">{{ product.sku }}</td>
                      <td class="border-b border-base-200">{{ product.widthMm ?? '—' }}</td>
                      <td class="border-b border-base-200">{{ product.lengthM ?? '—' }}</td>
                      <td class="border-b border-base-200">{{ product.thicknessMicron ?? '—' }}</td>
                      <td class="border-b border-base-200">{{ product.sleeveBrand ?? '—' }}</td>
                      <td class="border-b border-base-200 text-right">
                        <button
                          v-if="getQuantity(product.id) === 0"
                          class="btn h-9 rounded-full border-0 bg-[#139957] px-4 text-xs font-semibold text-white hover:bg-[#0d854a]"
                          @click="incrementProduct(product)"
                        >
                          В корзину
                        </button>
                        <div v-else class="ml-auto flex w-28 items-center justify-between rounded-xl border border-base-300 px-1 py-1">
                          <button
                            class="btn btn-xs btn-square"
                            :disabled="getQuantity(product.id) === 0"
                            @click="decrementProduct(product.id)"
                          >
                            -
                          </button>
                          <span class="min-w-8 text-center text-sm font-semibold">{{ getQuantity(product.id) }}</span>
                          <button class="btn btn-xs btn-square" @click="incrementProduct(product)">+</button>
                        </div>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
          </article>
        </div>
      </div>
    </div>
    <div v-else class="alert surface-card border-0">Такой тип товара не найден.</div>
  </section>
</template>
