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

definePageMeta({
  middleware: ['manager-only'],
  path: '/admin/settings/catalog',
});

type CatalogSettingItem = CatalogProductTypeSettingsQuery['catalogProductTypeSettings'][number];
type CatalogSettingForm = {
  productType: string;
  showQuantityPerBox: boolean;
  allowCustomLength: boolean;
  customLengthMinM: string;
  customLengthMaxM: string;
  customLengthStepM: string;
  allowCustomSleeveBrand: boolean;
  allowCustomLabel: boolean;
};

const settingsQuery = useQuery(CatalogProductTypeSettingsDocument);
const saveSettingMutation = useMutation(UpsertCatalogProductTypeSettingDocument, { throws: 'never' });

const forms = reactive<Record<string, CatalogSettingForm>>({});
const savingState = reactive<Record<string, boolean>>({});
const successMessage = reactive<Record<string, string>>({});
const errorMessage = reactive<Record<string, string>>({});

const settings = computed<CatalogSettingItem[]>(() => settingsQuery.result.value?.catalogProductTypeSettings ?? []);

function toInputValue(value: number | null | undefined) {
  return value == null ? '' : String(value);
}

function createForm(item: CatalogSettingItem): CatalogSettingForm {
  return {
    productType: item.productType,
    showQuantityPerBox: item.showQuantityPerBox,
    allowCustomLength: item.allowCustomLength,
    customLengthMinM: toInputValue(item.customLengthMinM),
    customLengthMaxM: toInputValue(item.customLengthMaxM),
    customLengthStepM: toInputValue(item.customLengthStepM),
    allowCustomSleeveBrand: item.allowCustomSleeveBrand,
    allowCustomLabel: item.allowCustomLabel,
  };
}

function parseOptionalInteger(value: string) {
  const normalized = value.trim();
  if (!normalized) {
    return null;
  }

  return Number(normalized);
}

function formFor(item: CatalogSettingItem) {
  forms[item.productType] ??= createForm(item);
  savingState[item.productType] ??= false;
  successMessage[item.productType] ??= '';
  errorMessage[item.productType] ??= '';
  return forms[item.productType];
}

watch(
  settings,
  (items) => {
    const activeTypes = new Set(items.map((item) => item.productType));

    for (const productType of Object.keys(forms)) {
      if (!activeTypes.has(productType)) {
        Reflect.deleteProperty(forms, productType);
        Reflect.deleteProperty(savingState, productType);
        Reflect.deleteProperty(successMessage, productType);
        Reflect.deleteProperty(errorMessage, productType);
      }
    }

    for (const item of items) {
      forms[item.productType] = createForm(item);
      savingState[item.productType] ??= false;
      successMessage[item.productType] ??= '';
      errorMessage[item.productType] ??= '';
    }
  },
  { immediate: true },
);

async function saveProductTypeSetting(productType: string) {
  const form = forms[productType];
  if (!form) {
    return;
  }

  successMessage[productType] = '';
  errorMessage[productType] = '';
  savingState[productType] = true;

  const result = await saveSettingMutation.mutate({
    input: {
      productType: form.productType,
      showQuantityPerBox: form.showQuantityPerBox,
      allowCustomLength: form.allowCustomLength,
      customLengthMinM: form.allowCustomLength ? parseOptionalInteger(form.customLengthMinM) : null,
      customLengthMaxM: form.allowCustomLength ? parseOptionalInteger(form.customLengthMaxM) : null,
      customLengthStepM: form.allowCustomLength ? parseOptionalInteger(form.customLengthStepM) : null,
      allowCustomSleeveBrand: form.allowCustomSleeveBrand,
      allowCustomLabel: form.allowCustomLabel,
    },
  });

  savingState[productType] = false;

  if (!result?.data?.upsertCatalogProductTypeSetting) {
    errorMessage[productType] = saveSettingMutation.error.value?.message || 'Не удалось сохранить настройки.';
    return;
  }

  forms[productType] = createForm(result.data.upsertCatalogProductTypeSetting);
  successMessage[productType] = 'Настройки сохранены.';
}
</script>

<template>
  <section class="space-y-6">
    <div class="space-y-2">
      <h1 class="text-3xl font-extrabold text-[#0f2f20]">Каталог</h1>
      <p class="text-sm leading-6 text-[#557562]">
        Правила конструктора по каждому типу товара: длина, своя втулка, своя надпись и видимость короба.
      </p>
    </div>

    <div v-if="settingsQuery.loading.value" class="manager-empty-state">
      Загружаем настройки каталога...
    </div>

    <div v-else-if="settings.length === 0" class="manager-empty-state">
      Типы товаров пока не появились в каталоге.
    </div>

    <div v-else class="grid gap-4 xl:grid-cols-2">
      <article
        v-for="item in settings"
        :key="item.productType"
        class="rounded-[28px] bg-white p-5 shadow-[0_18px_38px_rgba(18,56,36,0.08)]"
      >
        <div class="flex flex-col gap-4">
          <div class="space-y-1">
            <h2 class="text-xl font-bold text-[#123824]">{{ item.productType }}</h2>
            <p class="text-sm text-[#557562]">
              Определяет, какие параметры клиент сможет менять на витрине для этого типа товара.
            </p>
          </div>

          <div class="grid gap-3 md:grid-cols-2">
            <label class="surface-card flex items-start gap-3 rounded-[22px] p-4">
              <input v-model="formFor(item).allowCustomLength" type="checkbox" class="toggle toggle-success mt-1">
              <span>
                <span class="block font-semibold text-[#123824]">Своя длина</span>
                <span class="mt-1 block text-sm text-[#557562]">Разрешить длину вне стандартного списка.</span>
              </span>
            </label>

            <label class="surface-card flex items-start gap-3 rounded-[22px] p-4">
              <input v-model="formFor(item).allowCustomSleeveBrand" type="checkbox" class="toggle toggle-success mt-1">
              <span>
                <span class="block font-semibold text-[#123824]">Своя втулка</span>
                <span class="mt-1 block text-sm text-[#557562]">Клиент сможет запросить втулку со своим вариантом.</span>
              </span>
            </label>

            <label class="surface-card flex items-start gap-3 rounded-[22px] p-4">
              <input v-model="formFor(item).allowCustomLabel" type="checkbox" class="toggle toggle-success mt-1">
              <span>
                <span class="block font-semibold text-[#123824]">Своя надпись</span>
                <span class="mt-1 block text-sm text-[#557562]">Разрешить индивидуальную надпись или маркировку.</span>
              </span>
            </label>

            <label class="surface-card flex items-start gap-3 rounded-[22px] p-4">
              <input v-model="formFor(item).showQuantityPerBox" type="checkbox" class="toggle toggle-success mt-1">
              <span>
                <span class="block font-semibold text-[#123824]">Показывать короб</span>
                <span class="mt-1 block text-sm text-[#557562]">Если выключено, параметр короба скрывается из клиентского каталога.</span>
              </span>
            </label>
          </div>

          <div class="rounded-[24px] bg-[#f7fbf8] p-4">
            <div class="flex items-center justify-between gap-3">
              <div>
                <h3 class="text-sm font-bold uppercase tracking-[0.12em] text-[#355947]">Диапазон длины</h3>
                <p class="mt-1 text-sm text-[#557562]">Минимум, максимум и шаг для пользовательской длины.</p>
              </div>
              <span
                class="rounded-full px-3 py-1 text-xs font-bold uppercase tracking-[0.12em]"
                :class="formFor(item).allowCustomLength ? 'bg-[#e8f5ec] text-[#1c6b45]' : 'bg-[#eef2ef] text-[#6b7f71]'"
              >
                {{ formFor(item).allowCustomLength ? 'Включено' : 'Выключено' }}
              </span>
            </div>

            <div class="mt-4 grid gap-3 md:grid-cols-3">
              <label class="space-y-2">
                <span class="text-sm font-semibold text-[#123824]">Мин. длина, м</span>
                <input
                  v-model="formFor(item).customLengthMinM"
                  type="number"
                  min="1"
                  step="1"
                  class="input manager-field w-full"
                  :disabled="!formFor(item).allowCustomLength"
                >
              </label>

              <label class="space-y-2">
                <span class="text-sm font-semibold text-[#123824]">Макс. длина, м</span>
                <input
                  v-model="formFor(item).customLengthMaxM"
                  type="number"
                  min="1"
                  step="1"
                  class="input manager-field w-full"
                  :disabled="!formFor(item).allowCustomLength"
                >
              </label>

              <label class="space-y-2">
                <span class="text-sm font-semibold text-[#123824]">Шаг, м</span>
                <input
                  v-model="formFor(item).customLengthStepM"
                  type="number"
                  min="1"
                  step="1"
                  class="input manager-field w-full"
                  :disabled="!formFor(item).allowCustomLength"
                >
              </label>
            </div>
          </div>

          <div class="flex flex-wrap items-center justify-between gap-3">
            <div class="space-y-1 text-sm">
              <p v-if="successMessage[item.productType]" class="font-semibold text-[#1c6b45]">{{ successMessage[item.productType] }}</p>
              <p v-if="errorMessage[item.productType]" class="font-semibold text-[#c4472d]">{{ errorMessage[item.productType] }}</p>
            </div>

            <button
              class="btn h-11 rounded-full border-0 bg-[#139957] px-5 text-sm font-semibold text-white hover:bg-[#0d854a]"
              :disabled="savingState[item.productType]"
              @click="saveProductTypeSetting(item.productType)"
            >
              {{ savingState[item.productType] ? 'Сохраняем…' : 'Сохранить' }}
            </button>
          </div>
        </div>
      </article>
    </div>
  </section>
</template>
