<script setup lang="ts">
import { useMutation, useQuery } from '@vue/apollo-composable';
import {
  CreateMyDeliveryAddressDocument,
  DeleteMyDeliveryAddressDocument,
  MeDocument,
  MyCounterpartyProfileDocument,
  MyDeliveryAddressesDocument,
  MyMessengerConnectionsDocument,
  SetMyDefaultDeliveryAddressDocument,
  UpsertMyCounterpartyProfileDocument,
  type MyDeliveryAddressesQuery,
} from '~/composables/graphql/generated';
import { buildMessengerBotStartUrl } from '~/composables/useMessengerBotLink';
import { isCounterpartyProfileComplete } from '~/composables/useCounterpartyProfile';

type MessengerItem = {
  type: 'TELEGRAM' | 'MAX';
  isActive: boolean;
  channelId: string;
};

type PartySuggestion = {
  value: string;
  unrestricted_value?: string;
  data?: {
    inn?: string;
    kpp?: string;
    ogrn?: string;
    address?: { value?: string };
    management?: {
      name?: string;
      post?: string;
    };
  };
};

type BankSuggestion = {
  value: string;
  unrestricted_value?: string;
  data?: {
    bic?: string;
    correspondent_account?: string;
  };
};

type AddressSuggestion = {
  value: string;
  unrestricted_value?: string;
  data?: {
    fias_id?: string;
  };
};

type DeliveryAddressItem = MyDeliveryAddressesQuery['myDeliveryAddresses'][number];

const config = useRuntimeConfig();

const counterpartyForm = reactive({
  companyName: '',
  companyFullName: '',
  inn: '',
  kpp: '',
  ogrn: '',
  legalAddress: '',
  bankName: '',
  bik: '',
  correspondentAccount: '',
  checkingAccount: '',
  signerFullName: '',
  signerPosition: '',
  signerBasis: '',
});

const profileFeedback = ref('');
const profileFeedbackTone = ref<'success' | 'error'>('success');
const addressFeedback = ref('');
const addressFeedbackTone = ref<'success' | 'error'>('success');

const meQuery = useQuery(MeDocument);
const profileQuery = useQuery(MyCounterpartyProfileDocument);
const connectionsQuery = useQuery(MyMessengerConnectionsDocument);
const deliveryAddressesQuery = useQuery(MyDeliveryAddressesDocument);

const saveCounterpartyMutation = useMutation(UpsertMyCounterpartyProfileDocument, { throws: 'never' });
const createAddressMutation = useMutation(CreateMyDeliveryAddressDocument, { throws: 'never' });
const setDefaultAddressMutation = useMutation(SetMyDefaultDeliveryAddressDocument, { throws: 'never' });
const deleteAddressMutation = useMutation(DeleteMyDeliveryAddressDocument, { throws: 'never' });

const companySearch = ref('');
const partySuggestions = ref<PartySuggestion[]>([]);
const partyLoading = ref(false);
const partyOpen = ref(false);
const partySearchTimer = ref<ReturnType<typeof setTimeout> | null>(null);

const bankSearch = ref('');
const bankSuggestions = ref<BankSuggestion[]>([]);
const bankLoading = ref(false);
const bankOpen = ref(false);
const bankSearchTimer = ref<ReturnType<typeof setTimeout> | null>(null);

const addressForm = reactive({
  label: '',
  address: '',
  unrestrictedValue: '',
  fiasId: '',
});
const addressSearch = ref('');
const addressSuggestions = ref<AddressSuggestion[]>([]);
const addressLoading = ref(false);
const addressOpen = ref(false);
const addressSearchTimer = ref<ReturnType<typeof setTimeout> | null>(null);
const addressBusyId = ref<string | null>(null);

const partyDropdownRef = ref<HTMLElement | null>(null);
const bankDropdownRef = ref<HTMLElement | null>(null);
const addressDropdownRef = ref<HTMLElement | null>(null);

const counterpartySectionRef = ref<HTMLElement | null>(null);
const notificationsSectionRef = ref<HTMLElement | null>(null);
const addressesSectionRef = ref<HTMLElement | null>(null);

watch(
  () => profileQuery.result.value?.myCounterpartyProfile,
  (profile) => {
    if (!profile) {
      return;
    }

    counterpartyForm.companyName = profile.companyName;
    counterpartyForm.companyFullName = profile.companyFullName;
    counterpartyForm.inn = profile.inn;
    counterpartyForm.kpp = profile.kpp ?? '';
    counterpartyForm.ogrn = profile.ogrn ?? '';
    counterpartyForm.legalAddress = profile.legalAddress;
    counterpartyForm.bankName = profile.bankName;
    counterpartyForm.bik = profile.bik;
    counterpartyForm.correspondentAccount = profile.correspondentAccount;
    counterpartyForm.checkingAccount = profile.checkingAccount;
    counterpartyForm.signerFullName = profile.signerFullName;
    counterpartyForm.signerPosition = profile.signerPosition;
    counterpartyForm.signerBasis = profile.signerBasis;

    companySearch.value = profile.companyName;
    bankSearch.value = profile.bankName;
  },
  { immediate: true },
);

const profileUpdatedAt = computed(() => profileQuery.result.value?.myCounterpartyProfile?.updatedAt ?? null);
const profileIsComplete = computed(() => isCounterpartyProfileComplete(counterpartyForm));

const telegramConnection = computed(() =>
  connectionsQuery.result.value?.myMessengerConnections?.find(
    (item: MessengerItem) => item.type === 'TELEGRAM' && item.isActive,
  ),
);

const maxConnection = computed(() =>
  connectionsQuery.result.value?.myMessengerConnections?.find(
    (item: MessengerItem) => item.type === 'MAX' && item.isActive,
  ),
);

const connectedMessengerCount = computed(() => {
  let count = 0;
  if (telegramConnection.value) {
    count += 1;
  }
  if (maxConnection.value) {
    count += 1;
  }
  return count;
});

const notificationsSummary = computed(() => {
  if (connectedMessengerCount.value === 0) {
    return 'Уведомления не подключены. Настройте Telegram или Max, чтобы не пропускать обновления заказа.';
  }
  if (connectedMessengerCount.value === 1) {
    return 'Подключён 1 канал уведомлений. Рекомендуем подключить второй как резерв.';
  }
  return 'Подключены оба канала уведомлений. Вы будете получать обновления по заказам в мессенджерах.';
});

const deliveryAddresses = computed<DeliveryAddressItem[]>(() => deliveryAddressesQuery.result.value?.myDeliveryAddresses ?? []);
const defaultDeliveryAddress = computed(() => deliveryAddresses.value.find((item) => item.isDefault) ?? null);

function buildBotConnectUrl(baseUrl: string) {
  const accountEmail = meQuery.result.value?.me?.email?.trim().toLowerCase();
  if (!accountEmail || !baseUrl) {
    return '';
  }

  return buildMessengerBotStartUrl(baseUrl, accountEmail);
}

const telegramConnectUrl = computed(() => buildBotConnectUrl(config.public.telegramBotUrl || ''));
const maxConnectUrl = computed(() => buildBotConnectUrl(config.public.maxBotUrl || ''));

function clearPartyTimer() {
  if (!partySearchTimer.value) {
    return;
  }
  clearTimeout(partySearchTimer.value);
  partySearchTimer.value = null;
}

function clearBankTimer() {
  if (!bankSearchTimer.value) {
    return;
  }
  clearTimeout(bankSearchTimer.value);
  bankSearchTimer.value = null;
}

function clearAddressTimer() {
  if (!addressSearchTimer.value) {
    return;
  }
  clearTimeout(addressSearchTimer.value);
  addressSearchTimer.value = null;
}

async function fetchPartySuggestions() {
  const query = companySearch.value.trim();
  if (query.length < 2) {
    partySuggestions.value = [];
    partyOpen.value = false;
    return;
  }

  partyLoading.value = true;
  await $fetch<{ suggestions: PartySuggestion[] }>('/api/dadata/party', {
    method: 'POST',
    body: { query },
  })
    .then((response) => {
      partySuggestions.value = response.suggestions || [];
      partyOpen.value = partySuggestions.value.length > 0;
    })
    .finally(() => {
      partyLoading.value = false;
    });
}

async function fetchBankSuggestions() {
  const query = bankSearch.value.trim();
  if (query.length < 2) {
    bankSuggestions.value = [];
    bankOpen.value = false;
    return;
  }

  bankLoading.value = true;
  await $fetch<{ suggestions: BankSuggestion[] }>('/api/dadata/bank', {
    method: 'POST',
    body: { query },
  })
    .then((response) => {
      bankSuggestions.value = response.suggestions || [];
      bankOpen.value = bankSuggestions.value.length > 0;
    })
    .finally(() => {
      bankLoading.value = false;
    });
}

async function fetchAddressSuggestions() {
  const query = addressSearch.value.trim();
  if (query.length < 2) {
    addressSuggestions.value = [];
    addressOpen.value = false;
    return;
  }

  addressLoading.value = true;
  await $fetch<{ suggestions: AddressSuggestion[] }>('/api/dadata/address', {
    method: 'POST',
    body: { query },
  })
    .then((response) => {
      addressSuggestions.value = response.suggestions || [];
      addressOpen.value = addressSuggestions.value.length > 0;
    })
    .finally(() => {
      addressLoading.value = false;
    });
}

function schedulePartySuggest() {
  clearPartyTimer();
  partySearchTimer.value = setTimeout(() => {
    void fetchPartySuggestions();
  }, 250);
}

function scheduleBankSuggest() {
  clearBankTimer();
  bankSearchTimer.value = setTimeout(() => {
    void fetchBankSuggestions();
  }, 250);
}

function scheduleAddressSuggest() {
  clearAddressTimer();
  addressSearchTimer.value = setTimeout(() => {
    void fetchAddressSuggestions();
  }, 250);
}

function applyPartySuggestion(item: PartySuggestion) {
  partyOpen.value = false;
  companySearch.value = item.value;

  counterpartyForm.companyName = item.value;
  counterpartyForm.companyFullName = item.unrestricted_value || item.value;
  counterpartyForm.inn = item.data?.inn || '';
  counterpartyForm.kpp = item.data?.kpp || '';
  counterpartyForm.ogrn = item.data?.ogrn || '';
  counterpartyForm.legalAddress = item.data?.address?.value || '';

  if (!counterpartyForm.signerFullName && item.data?.management?.name) {
    counterpartyForm.signerFullName = item.data.management.name;
  }
  if (!counterpartyForm.signerPosition && item.data?.management?.post) {
    counterpartyForm.signerPosition = item.data.management.post;
  }
}

function applyBankSuggestion(item: BankSuggestion) {
  bankOpen.value = false;
  bankSearch.value = item.value;

  counterpartyForm.bankName = item.value;
  counterpartyForm.bik = item.data?.bic || '';
  counterpartyForm.correspondentAccount = item.data?.correspondent_account || '';
}

function applyAddressSuggestion(item: AddressSuggestion) {
  addressOpen.value = false;
  addressSearch.value = item.value;
  addressForm.address = item.value;
  addressForm.unrestrictedValue = item.unrestricted_value || item.value;
  addressForm.fiasId = item.data?.fias_id || '';
}

function scrollToSection(section: 'counterparty' | 'notifications' | 'addresses') {
  const element =
    section === 'counterparty'
      ? counterpartySectionRef.value
      : section === 'notifications'
        ? notificationsSectionRef.value
        : addressesSectionRef.value;

  element?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}

function closeDropdownsFromOutside(event: MouseEvent) {
  const target = event.target as Node | null;
  if (partyDropdownRef.value && target && !partyDropdownRef.value.contains(target)) {
    partyOpen.value = false;
  }
  if (bankDropdownRef.value && target && !bankDropdownRef.value.contains(target)) {
    bankOpen.value = false;
  }
  if (addressDropdownRef.value && target && !addressDropdownRef.value.contains(target)) {
    addressOpen.value = false;
  }
}

async function saveCounterpartyProfile() {
  profileFeedback.value = '';
  const result = await saveCounterpartyMutation.mutate({
    input: {
      companyName: counterpartyForm.companyName,
      companyFullName: counterpartyForm.companyFullName,
      inn: counterpartyForm.inn,
      kpp: counterpartyForm.kpp.trim() ? counterpartyForm.kpp.trim() : null,
      ogrn: counterpartyForm.ogrn.trim() ? counterpartyForm.ogrn.trim() : null,
      legalAddress: counterpartyForm.legalAddress,
      bankName: counterpartyForm.bankName,
      bik: counterpartyForm.bik,
      correspondentAccount: counterpartyForm.correspondentAccount,
      checkingAccount: counterpartyForm.checkingAccount,
      signerFullName: counterpartyForm.signerFullName,
      signerPosition: counterpartyForm.signerPosition,
      signerBasis: counterpartyForm.signerBasis,
    },
  });

  const payload = result?.data?.upsertMyCounterpartyProfile;
  if (!payload) {
    profileFeedbackTone.value = 'error';
    profileFeedback.value = saveCounterpartyMutation.error.value?.message || 'Не удалось сохранить карточку контрагента.';
    return;
  }

  profileFeedbackTone.value = 'success';
  profileFeedback.value = 'Карточка контрагента сохранена.';
  await profileQuery.refetch();
}

async function addDeliveryAddress() {
  addressFeedback.value = '';

  const normalizedAddress = addressForm.address.trim() || addressSearch.value.trim();
  if (normalizedAddress.length < 5) {
    addressFeedbackTone.value = 'error';
    addressFeedback.value = 'Введите адрес через подсказки DaData.';
    return;
  }

  const result = await createAddressMutation.mutate({
    input: {
      label: addressForm.label.trim() ? addressForm.label.trim() : null,
      address: normalizedAddress,
      unrestrictedValue: addressForm.unrestrictedValue.trim() ? addressForm.unrestrictedValue.trim() : null,
      fiasId: addressForm.fiasId.trim() ? addressForm.fiasId.trim() : null,
    },
  });

  const payload = result?.data?.createMyDeliveryAddress;
  if (!payload) {
    addressFeedbackTone.value = 'error';
    addressFeedback.value = createAddressMutation.error.value?.message || 'Не удалось добавить адрес.';
    return;
  }

  addressForm.label = '';
  addressForm.address = '';
  addressForm.unrestrictedValue = '';
  addressForm.fiasId = '';
  addressSearch.value = '';
  addressSuggestions.value = [];
  addressOpen.value = false;

  addressFeedbackTone.value = 'success';
  addressFeedback.value = 'Адрес сохранён.';
  await deliveryAddressesQuery.refetch();
}

async function setDefaultAddress(addressId: string) {
  addressFeedback.value = '';
  addressBusyId.value = addressId;

  const result = await setDefaultAddressMutation.mutate({ addressId });
  const payload = result?.data?.setMyDefaultDeliveryAddress;
  addressBusyId.value = null;

  if (!payload) {
    addressFeedbackTone.value = 'error';
    addressFeedback.value = setDefaultAddressMutation.error.value?.message || 'Не удалось сделать адрес основным.';
    return;
  }

  addressFeedbackTone.value = 'success';
  addressFeedback.value = 'Основной адрес обновлён.';
  await deliveryAddressesQuery.refetch();
}

async function deleteAddress(addressId: string) {
  addressFeedback.value = '';
  addressBusyId.value = addressId;

  const result = await deleteAddressMutation.mutate({ addressId });
  const payload = result?.data?.deleteMyDeliveryAddress;
  addressBusyId.value = null;

  if (!payload) {
    addressFeedbackTone.value = 'error';
    addressFeedback.value = deleteAddressMutation.error.value?.message || 'Не удалось удалить адрес.';
    return;
  }

  addressFeedbackTone.value = 'success';
  addressFeedback.value = 'Адрес удалён.';
  await deliveryAddressesQuery.refetch();
}

onMounted(() => {
  document.addEventListener('click', closeDropdownsFromOutside);
});

onBeforeUnmount(() => {
  document.removeEventListener('click', closeDropdownsFromOutside);
  clearPartyTimer();
  clearBankTimer();
  clearAddressTimer();
});
</script>

<template>
  <section class="space-y-6">
    <h1 class="text-3xl font-extrabold text-[#0f2f20]">Профиль</h1>

    <div class="grid gap-4 md:grid-cols-3">
      <article
        class="rounded-3xl border p-4"
        :class="profileIsComplete ? 'border-[#76c893] bg-[#ecfdf3]' : 'border-[#f5d49a] bg-[#fff9eb]'"
      >
        <p class="text-sm opacity-70">Карточка контрагента</p>
        <p class="mt-2 text-lg font-bold text-[#123824]">
          {{ profileIsComplete ? 'Заполнена' : 'Требует внимания' }}
        </p>
        <p class="mt-2 text-sm text-[#355947]">
          {{
            profileIsComplete
              ? 'Можно оформлять заказы и отправлять заявки менеджеру.'
              : 'Заполните реквизиты, чтобы открыть оформление заявок.'
          }}
        </p>
        <button class="btn btn-sm mt-4 w-full" @click="scrollToSection('counterparty')">Открыть карточку</button>
      </article>

      <article class="rounded-3xl border border-[#d6ebde] bg-[#f7fffb] p-4">
        <p class="text-sm opacity-70">Уведомления</p>
        <p class="mt-2 text-lg font-bold text-[#123824]">{{ connectedMessengerCount }}/2 каналов подключено</p>
        <p class="mt-2 text-sm text-[#355947]">{{ notificationsSummary }}</p>
        <button class="btn btn-sm mt-4 w-full" @click="scrollToSection('notifications')">Открыть уведомления</button>
      </article>

      <article class="rounded-3xl border border-[#d6ebde] bg-[#f7fffb] p-4">
        <p class="text-sm opacity-70">Адреса доставки</p>
        <p class="mt-2 text-lg font-bold text-[#123824]">{{ deliveryAddresses.length }}</p>
        <p class="mt-2 text-sm text-[#355947]">
          {{
            defaultDeliveryAddress
              ? `Основной: ${defaultDeliveryAddress.label || defaultDeliveryAddress.address}`
              : 'Добавьте хотя бы один адрес для оформления заявок.'
          }}
        </p>
        <button class="btn btn-sm mt-4 w-full" @click="scrollToSection('addresses')">Открыть адреса</button>
      </article>
    </div>

    <div class="grid gap-4 lg:grid-cols-[1.7fr_1fr]">
      <div ref="counterpartySectionRef" class="surface-card rounded-3xl p-5">
        <div class="space-y-1">
          <h2 class="text-xl font-bold text-[#123824]">Карточка контрагента</h2>
          <p class="text-sm text-[#355947]">
            Пожалуйста, заполните реквизиты, чтобы получить максимум возможностей личного кабинета.
          </p>
        </div>

        <div class="mt-4 space-y-4">
          <section>
            <h3 class="mb-3 text-base font-bold">1. Контрагент (DaData)</h3>

            <div ref="partyDropdownRef" class="relative">
              <fieldset class="fieldset">
                <legend class="fieldset-legend">Поиск компании</legend>
                <input
                  v-model="companySearch"
                  type="text"
                  class="input input-bordered w-full"
                  placeholder="Введите название или ИНН"
                  @input="schedulePartySuggest"
                  @focus="partyOpen = partySuggestions.length > 0"
                >
              </fieldset>

              <span v-if="partyLoading" class="loading loading-spinner loading-sm absolute right-3 top-1/2 -translate-y-1/2" />

              <div
                v-if="partyOpen && partySuggestions.length > 0"
                class="absolute z-30 mt-2 max-h-72 w-full overflow-auto rounded-box border border-base-300 bg-base-100 p-2 shadow-xl"
              >
                <button
                  v-for="item in partySuggestions"
                  :key="`${item.value}-${item.data?.inn || ''}`"
                  type="button"
                  class="btn btn-ghost mb-1 h-auto min-h-0 w-full justify-start whitespace-normal px-3 py-2 text-left"
                  @click="applyPartySuggestion(item)"
                >
                  <span>
                    <span class="block text-sm font-semibold">{{ item.value }}</span>
                    <span class="block text-xs opacity-70">ИНН: {{ item.data?.inn || '—' }} <span v-if="item.data?.kpp">• КПП: {{ item.data.kpp }}</span></span>
                  </span>
                </button>
              </div>
            </div>

            <fieldset class="fieldset">
              <legend class="fieldset-legend">Краткое наименование</legend>
              <input v-model="counterpartyForm.companyName" type="text" class="input input-bordered w-full" >
            </fieldset>

            <fieldset class="fieldset">
              <legend class="fieldset-legend">Полное наименование</legend>
              <input v-model="counterpartyForm.companyFullName" type="text" class="input input-bordered w-full" >
            </fieldset>

            <div class="grid gap-3 sm:grid-cols-3">
              <fieldset class="fieldset">
                <legend class="fieldset-legend">ИНН</legend>
                <input v-model="counterpartyForm.inn" type="text" class="input input-bordered w-full" >
              </fieldset>

              <fieldset class="fieldset">
                <legend class="fieldset-legend">КПП</legend>
                <input v-model="counterpartyForm.kpp" type="text" class="input input-bordered w-full" >
              </fieldset>

              <fieldset class="fieldset">
                <legend class="fieldset-legend">ОГРН</legend>
                <input v-model="counterpartyForm.ogrn" type="text" class="input input-bordered w-full" >
              </fieldset>
            </div>

            <fieldset class="fieldset">
              <legend class="fieldset-legend">Юридический адрес</legend>
              <textarea v-model="counterpartyForm.legalAddress" class="textarea textarea-bordered min-h-24 w-full" />
            </fieldset>
          </section>

          <div class="divider my-0" />

          <section>
            <h3 class="mb-3 text-base font-bold">2. Банк (DaData)</h3>

            <div ref="bankDropdownRef" class="relative">
              <fieldset class="fieldset">
                <legend class="fieldset-legend">Поиск банка</legend>
                <input
                  v-model="bankSearch"
                  type="text"
                  class="input input-bordered w-full"
                  placeholder="Введите название банка"
                  @input="scheduleBankSuggest"
                  @focus="bankOpen = bankSuggestions.length > 0"
                >
              </fieldset>

              <span v-if="bankLoading" class="loading loading-spinner loading-sm absolute right-3 top-1/2 -translate-y-1/2" />

              <div
                v-if="bankOpen && bankSuggestions.length > 0"
                class="absolute z-30 mt-2 max-h-72 w-full overflow-auto rounded-box border border-base-300 bg-base-100 p-2 shadow-xl"
              >
                <button
                  v-for="item in bankSuggestions"
                  :key="`${item.value}-${item.data?.bic || ''}`"
                  type="button"
                  class="btn btn-ghost mb-1 h-auto min-h-0 w-full justify-start whitespace-normal px-3 py-2 text-left"
                  @click="applyBankSuggestion(item)"
                >
                  <span>
                    <span class="block text-sm font-semibold">{{ item.value }}</span>
                    <span class="block text-xs opacity-70">БИК: {{ item.data?.bic || '—' }}</span>
                  </span>
                </button>
              </div>
            </div>

            <fieldset class="fieldset">
              <legend class="fieldset-legend">Банк</legend>
              <input v-model="counterpartyForm.bankName" type="text" class="input input-bordered w-full" >
            </fieldset>

            <div class="grid gap-3 sm:grid-cols-2">
              <fieldset class="fieldset">
                <legend class="fieldset-legend">БИК</legend>
                <input v-model="counterpartyForm.bik" type="text" class="input input-bordered w-full" >
              </fieldset>

              <fieldset class="fieldset">
                <legend class="fieldset-legend">Корр. счет</legend>
                <input v-model="counterpartyForm.correspondentAccount" type="text" class="input input-bordered w-full" >
              </fieldset>
            </div>

            <fieldset class="fieldset">
              <legend class="fieldset-legend">Расчетный счет</legend>
              <input v-model="counterpartyForm.checkingAccount" type="text" class="input input-bordered w-full" >
            </fieldset>
          </section>

          <div class="divider my-0" />

          <section>
            <h3 class="mb-3 text-base font-bold">3. Подписант и основание</h3>

            <fieldset class="fieldset">
              <legend class="fieldset-legend">ФИО подписанта</legend>
              <input v-model="counterpartyForm.signerFullName" type="text" class="input input-bordered w-full" placeholder="Иванов Иван Иванович" >
            </fieldset>

            <fieldset class="fieldset">
              <legend class="fieldset-legend">Должность</legend>
              <input v-model="counterpartyForm.signerPosition" type="text" class="input input-bordered w-full" placeholder="Генеральный директор" >
            </fieldset>

            <fieldset class="fieldset">
              <legend class="fieldset-legend">Основание полномочий</legend>
              <textarea
                v-model="counterpartyForm.signerBasis"
                class="textarea textarea-bordered min-h-24 w-full"
                placeholder="Действует на основании Устава"
              />
            </fieldset>

            <button class="btn btn-primary mt-4 w-full" :disabled="saveCounterpartyMutation.loading.value || !profileIsComplete" @click="saveCounterpartyProfile">
              {{ saveCounterpartyMutation.loading.value ? 'Сохраняем…' : 'Сохранить' }}
            </button>

            <p v-if="profileUpdatedAt" class="mt-2 text-xs opacity-70">Обновлено: {{ new Date(profileUpdatedAt).toLocaleString() }}</p>
          </section>
        </div>

        <div v-if="profileFeedback" class="alert mt-4" :class="profileFeedbackTone === 'success' ? 'alert-success' : 'alert-error'">
          {{ profileFeedback }}
        </div>
      </div>

      <div class="space-y-4">
        <aside ref="notificationsSectionRef" class="surface-card rounded-3xl p-5">
          <h2 class="text-xl font-bold text-[#123824]">Уведомления</h2>
          <p class="mt-2 text-sm text-[#355947]">{{ notificationsSummary }}</p>

          <div class="mt-4 space-y-3">
            <div class="rounded-2xl border border-[#d6ebde] bg-white/75 p-4">
              <p class="font-semibold">Telegram</p>
              <p class="text-sm opacity-80">
                {{ telegramConnection ? `Подключен: ${telegramConnection.channelId}` : 'Не подключен' }}
              </p>
              <a
                :href="telegramConnectUrl || undefined"
                target="_blank"
                rel="noopener noreferrer"
                class="btn btn-secondary mt-3 w-full"
                :class="{ 'btn-disabled pointer-events-none': !telegramConnectUrl }"
              >
                {{ telegramConnection ? 'Переподключить Telegram' : 'Подключить Telegram' }}
              </a>
            </div>

            <div class="rounded-2xl border border-[#d6ebde] bg-white/75 p-4">
              <p class="font-semibold">Max</p>
              <p class="text-sm opacity-80">
                {{ maxConnection ? `Подключен: ${maxConnection.channelId}` : 'Не подключен' }}
              </p>
              <a
                :href="maxConnectUrl || undefined"
                target="_blank"
                rel="noopener noreferrer"
                class="btn btn-accent mt-3 w-full"
                :class="{ 'btn-disabled pointer-events-none': !maxConnectUrl }"
              >
                {{ maxConnection ? 'Переподключить Max' : 'Подключить Max' }}
              </a>
            </div>
          </div>
        </aside>

        <aside ref="addressesSectionRef" class="surface-card rounded-3xl p-5">
          <h2 class="text-xl font-bold text-[#123824]">Адреса доставки</h2>
          <p class="mt-2 text-sm text-[#355947]">
            Добавьте адрес через DaData и выберите основной. Этот адрес будет подставляться при оформлении заявки из корзины.
          </p>

          <fieldset class="fieldset mt-4">
            <legend class="fieldset-legend">Название адреса (необязательно)</legend>
            <input v-model="addressForm.label" type="text" class="input input-bordered w-full" placeholder="Склад МСК" >
          </fieldset>

          <div ref="addressDropdownRef" class="relative mt-2">
            <fieldset class="fieldset">
              <legend class="fieldset-legend">Поиск адреса (DaData)</legend>
              <input
                v-model="addressSearch"
                type="text"
                class="input input-bordered w-full"
                placeholder="Начните вводить адрес"
                @input="scheduleAddressSuggest"
                @focus="addressOpen = addressSuggestions.length > 0"
              >
            </fieldset>

            <span v-if="addressLoading" class="loading loading-spinner loading-sm absolute right-3 top-1/2 -translate-y-1/2" />

            <div
              v-if="addressOpen && addressSuggestions.length > 0"
              class="absolute z-30 mt-2 max-h-72 w-full overflow-auto rounded-box border border-base-300 bg-base-100 p-2 shadow-xl"
            >
              <button
                v-for="item in addressSuggestions"
                :key="`${item.value}-${item.data?.fias_id || ''}`"
                type="button"
                class="btn btn-ghost mb-1 h-auto min-h-0 w-full justify-start whitespace-normal px-3 py-2 text-left"
                @click="applyAddressSuggestion(item)"
              >
                <span class="block text-sm font-semibold">{{ item.value }}</span>
              </button>
            </div>
          </div>

          <button class="btn btn-primary mt-4 w-full" :disabled="createAddressMutation.loading.value" @click="addDeliveryAddress">
            {{ createAddressMutation.loading.value ? 'Добавляем…' : 'Добавить адрес' }}
          </button>

          <div v-if="addressFeedback" class="alert mt-3" :class="addressFeedbackTone === 'success' ? 'alert-success' : 'alert-error'">
            {{ addressFeedback }}
          </div>

          <div class="mt-4 space-y-2">
            <div v-if="deliveryAddressesQuery.loading.value" class="alert surface-card border-0">Загрузка адресов...</div>
            <div v-else-if="deliveryAddresses.length === 0" class="alert surface-card border-0">
              Пока нет адресов доставки. Добавьте первый адрес через DaData.
            </div>

            <article
              v-for="address in deliveryAddresses"
              :key="address.id"
              class="rounded-2xl border border-[#d6ebde] bg-white/75 p-3"
            >
              <div class="flex items-start justify-between gap-2">
                <div>
                  <p class="font-semibold text-[#123824]">{{ address.label || 'Адрес доставки' }}</p>
                  <p class="text-sm text-[#355947]">{{ address.unrestrictedValue || address.address }}</p>
                </div>
                <span v-if="address.isDefault" class="badge badge-success">Основной</span>
              </div>

              <div class="mt-3 flex flex-wrap gap-2">
                <button
                  v-if="!address.isDefault"
                  class="btn btn-sm"
                  :disabled="addressBusyId === address.id"
                  @click="setDefaultAddress(address.id)"
                >
                  {{ addressBusyId === address.id ? 'Сохраняем…' : 'Сделать основным' }}
                </button>
                <button
                  class="btn btn-sm btn-ghost text-error"
                  :disabled="addressBusyId === address.id"
                  @click="deleteAddress(address.id)"
                >
                  {{ addressBusyId === address.id ? 'Удаляем…' : 'Удалить' }}
                </button>
              </div>
            </article>
          </div>
        </aside>
      </div>
    </div>
  </section>
</template>
