import { renderHeader } from '../components/header.js';
import { profile } from '../mock-data.js';
import { authService, state } from '../state.js';
import {
  PROFILE_GENDER_FEMALE,
  PROFILE_GENDER_MALE,
  PROFILE_GENDER_UNKNOWN,
  loadProfileSnapshot,
  saveProfileGender,
  saveProfileParamBlock,
  saveProfileToggle,
} from '../services/user-profile-params.js';
import { buildIdentityLines, loadUserProfileCard } from '../services/user-connections.js';
import { openAvatarWizard } from '../components/avatar-wizard.js';
import { renderUserAvatar } from '../components/avatar-image.js';

export const pageMeta = { id: 'profile-edit-view', title: 'Редактирование профиля' };

function toggleText(enabled) {
  return enabled ? 'Yes' : 'No';
}

function showLocalErrorAlert(prefix, error) {
  const message = error?.message || 'Неизвестная ошибка';
  const stack = error?.stack ? `\n\nStack:\n${error.stack}` : '';
  window.alert(`${prefix}: ${message}${stack}`);
}

function genderLabel(value) {
  if (value === PROFILE_GENDER_MALE) return 'Мужской';
  if (value === PROFILE_GENDER_FEMALE) return 'Женский';
  return 'Не указан';
}

const GENDER_OPTIONS = Object.freeze([
  { value: PROFILE_GENDER_MALE, label: 'Мужской' },
  { value: PROFILE_GENDER_FEMALE, label: 'Женский' },
  { value: PROFILE_GENDER_UNKNOWN, label: 'Не указан' },
]);

const RELATIVE_RELATION_OPTIONS = Object.freeze([
  { value: 'parent', label: 'Родитель (мать/отец по полу)' },
  { value: 'child', label: 'Ребёнок (сын/дочь по полу)' },
  { value: 'spouse', label: 'Жена / Муж (по полу)' },
  { value: 'sibling', label: 'Брат или сестра (по полу)' },
  { value: 'close_friend', label: 'Близкий друг' },
]);

function normalizeGender(value) {
  const v = String(value || '').trim().toLowerCase();
  if (v === PROFILE_GENDER_MALE) return PROFILE_GENDER_MALE;
  if (v === PROFILE_GENDER_FEMALE) return PROFILE_GENDER_FEMALE;
  return PROFILE_GENDER_UNKNOWN;
}

function relationAccusativeLabel(type, targetGender) {
  const gender = normalizeGender(targetGender);
  if (type === 'parent') {
    if (gender === PROFILE_GENDER_MALE) return 'отца';
    if (gender === PROFILE_GENDER_FEMALE) return 'мать';
    return 'родителя';
  }
  if (type === 'child') {
    if (gender === PROFILE_GENDER_MALE) return 'сына';
    if (gender === PROFILE_GENDER_FEMALE) return 'дочь';
    return 'ребёнка';
  }
  if (type === 'sibling') {
    if (gender === PROFILE_GENDER_MALE) return 'брата';
    if (gender === PROFILE_GENDER_FEMALE) return 'сестру';
    return 'брата/сестру';
  }
  if (type === 'spouse') {
    if (gender === PROFILE_GENDER_MALE) return 'мужа';
    if (gender === PROFILE_GENDER_FEMALE) return 'жену';
    return 'жену/мужа';
  }
  return 'близкого друга';
}

function escapeHtml(text) {
  return String(text || '')
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;')
    .replaceAll('"', '&quot;')
    .replaceAll("'", '&#39;');
}

export function render({ navigate }) {
  const login = state.session.login || profile.login;

  const screen = document.createElement('section');
  screen.className = 'stack profile-screen';

  screen.append(
    renderHeader({
      title: 'Редактирование профиля',
      leftAction: { label: '←', onClick: () => navigate('profile-view') },
    }),
  );

  const card = document.createElement('div');
  card.className = 'card stack';

  const topRow = document.createElement('div');
  topRow.className = 'row';
  topRow.innerHTML = `
    <div class="row" style="gap:12px; align-items:center;">
      <div class="profile-avatar-block" data-change-avatar="true" style="cursor:pointer;">
        <div data-profile-avatar-slot="true"></div>
      </div>
      <div class="profile-identity-lines" data-profile-identity="true">
        <div class="profile-identity-line profile-identity-login">${String(login || '').trim() || 'unknown'}</div>
      </div>
    </div>
    <button class="primary-btn" type="button" data-reload="true">Обновить</button>
  `;

  const badgesRow = document.createElement('div');
  badgesRow.className = 'row';
  badgesRow.innerHTML = `
    <button class="badge profile-toggle-btn is-no" type="button" data-toggle="official">Официальный: No</button>
    <button class="badge profile-toggle-btn is-no" type="button" data-toggle="shine">Сияющий: No</button>
  `;

  const status = document.createElement('div');
  status.className = 'status-line';
  status.textContent = 'Загрузка параметров...';

  const listWrap = document.createElement('div');
  listWrap.className = 'stack profile-param-list';

  const relativesCard = document.createElement('div');
  relativesCard.className = 'card stack';
  relativesCard.innerHTML = `
    <div class="profile-param-value"><b>Близкие родственники</b></div>
    <div class="meta-muted">
      Добавьте связь: родитель, ребёнок, жена/муж, брат/сестра или близкий друг.
      Формулировка (мать/отец, брат/сестра) определяется по полу выбранного пользователя.
    </div>
    <button class="secondary-btn" type="button" data-add-relative="true">Добавить близких родственников</button>
  `;

  const reloadBtn = topRow.querySelector('[data-reload="true"]');
  const officialBtn = badgesRow.querySelector('[data-toggle="official"]');
  const shineBtn = badgesRow.querySelector('[data-toggle="shine"]');
  const addRelativeBtn = relativesCard.querySelector('[data-add-relative="true"]');
  const avatarActionEl = topRow.querySelector('[data-change-avatar="true"]');

  let currentFields = [];
  let currentToggles = [];
  let currentGender = PROFILE_GENDER_UNKNOWN;
  let currentAvatar = { value: '', source: '', txId: '', sha256Hex: '', timeMs: 0 };
  const identityEl = topRow.querySelector('[data-profile-identity="true"]');
  const avatarSlotEl = topRow.querySelector('[data-profile-avatar-slot="true"]');

  function openGenderPickerModal(initialGender) {
    const root = document.getElementById('modal-root');
    if (!root) return Promise.resolve(null);
    root.innerHTML = '';

    const selected = GENDER_OPTIONS.some((item) => item.value === initialGender)
      ? initialGender
      : PROFILE_GENDER_UNKNOWN;

    root.innerHTML = `
      <div class="modal" id="profile-gender-modal">
        <div class="modal-card stack">
          <h3 class="modal-title">Выбор пола</h3>
          <p class="meta-muted">Выберите значение профиля из списка:</p>
          <select class="input profile-gender-select" id="profile-gender-select">
            ${GENDER_OPTIONS.map((item) => (
              `<option value="${item.value}" ${item.value === selected ? 'selected' : ''}>${item.label}</option>`
            )).join('')}
          </select>
          <div class="form-actions-grid">
            <button class="secondary-btn" id="profile-gender-cancel" type="button">Отмена</button>
            <button class="primary-btn" id="profile-gender-save" type="button">Сохранить</button>
          </div>
        </div>
      </div>
    `;

    return new Promise((resolve) => {
      const modal = root.querySelector('#profile-gender-modal');
      const selectEl = root.querySelector('#profile-gender-select');
      const saveEl = root.querySelector('#profile-gender-save');
      const cancelEl = root.querySelector('#profile-gender-cancel');
      if (!(modal instanceof HTMLElement) || !(selectEl instanceof HTMLSelectElement)) {
        root.innerHTML = '';
        resolve(null);
        return;
      }

      const close = (value = null) => {
        root.innerHTML = '';
        resolve(value);
      };

      modal.addEventListener('click', (event) => {
        if (event.target === modal) close(null);
      });
      cancelEl?.addEventListener('click', () => close(null));
      saveEl?.addEventListener('click', () => close(selectEl.value || PROFILE_GENDER_UNKNOWN));
      window.setTimeout(() => selectEl.focus(), 0);
    });
  }

  function syncIdentity() {
    if (!identityEl) return;
    const firstName = currentFields.find((field) => field.key === 'first_name')?.value || '';
    const lastName = currentFields.find((field) => field.key === 'last_name')?.value || '';
    const lines = buildIdentityLines({ login, firstName, lastName });
    identityEl.innerHTML = lines.map((line, idx) => (
      `<div class="profile-identity-line${idx === lines.length - 1 ? ' profile-identity-login' : ''}">${escapeHtml(line)}</div>`
    )).join('');
  }

  function updateAvatarUi() {
    if (!(avatarSlotEl instanceof HTMLElement)) return;
    const firstName = String(currentFields.find((field) => field.key === 'first_name')?.value || '').trim();
    const lastName = String(currentFields.find((field) => field.key === 'last_name')?.value || '').trim();
    avatarSlotEl.innerHTML = '';
    avatarSlotEl.append(renderUserAvatar({
      login,
      firstName,
      lastName,
      avatar: currentAvatar?.txId
        ? { ar: currentAvatar.txId, sha256Hex: String(currentAvatar?.sha256Hex || '').trim().toLowerCase() }
        : null,
      size: 'large',
      className: 'profile-avatar',
    }));
  }

  function updateToggleButton(button, prefix, enabled) {
    button.textContent = `${prefix}: ${toggleText(enabled)}`;
    button.classList.remove('is-no', 'is-yes-official', 'is-yes-shine');

    if (!enabled) {
      button.classList.add('is-no');
      return;
    }

    if (prefix === 'Официальный') {
      button.classList.add('is-yes-official');
    } else {
      button.classList.add('is-yes-shine');
    }
  }

  function updateTogglesUi() {
    const official = currentToggles.find((item) => item.key === 'official') || { enabled: false };
    const shine = currentToggles.find((item) => item.key === 'shine') || { enabled: false };
    updateToggleButton(officialBtn, 'Официальный', official.enabled);
    updateToggleButton(shineBtn, 'Сияющий', shine.enabled);
  }

  function updateGenderUi() {
    const genderValueEl = listWrap.querySelector('[data-gender-value]');
    if (!genderValueEl) return;
    genderValueEl.textContent = genderLabel(currentGender);
  }

  function openFieldEditModal({ label, value, placeholder = '' }) {
    const root = document.getElementById('modal-root');
    if (!root) return Promise.resolve(null);
    root.innerHTML = `
      <div class="modal" id="profile-field-edit-modal">
        <div class="modal-card stack">
          <h3 class="modal-title">Изменить: ${escapeHtml(label)}</h3>
          <input
            id="profile-field-edit-input"
            class="input"
            type="text"
            maxlength="300"
            placeholder="${escapeHtml(placeholder || `Введите ${label.toLowerCase()}`)}"
            value="${escapeHtml(String(value || ''))}"
          />
          <div class="form-actions-grid">
            <button class="secondary-btn" id="profile-field-edit-cancel" type="button">Отмена</button>
            <button class="primary-btn" id="profile-field-edit-save" type="button">Сохранить</button>
          </div>
        </div>
      </div>
    `;

    return new Promise((resolve) => {
      const modal = root.querySelector('#profile-field-edit-modal');
      const inputEl = root.querySelector('#profile-field-edit-input');
      const saveEl = root.querySelector('#profile-field-edit-save');
      const cancelEl = root.querySelector('#profile-field-edit-cancel');
      if (!(modal instanceof HTMLElement) || !(inputEl instanceof HTMLInputElement)) {
        root.innerHTML = '';
        resolve(null);
        return;
      }

      const close = (nextValue = null) => {
        root.innerHTML = '';
        resolve(nextValue);
      };

      modal.addEventListener('click', (event) => {
        if (event.target === modal) close(null);
      });
      cancelEl?.addEventListener('click', () => close(null));
      saveEl?.addEventListener('click', () => close(inputEl.value));
      inputEl.addEventListener('keydown', (event) => {
        if (event.key === 'Enter') {
          event.preventDefault();
          close(inputEl.value);
        }
      });
      window.setTimeout(() => {
        inputEl.focus();
        inputEl.selectionStart = inputEl.value.length;
        inputEl.selectionEnd = inputEl.value.length;
      }, 0);
    });
  }

  function openAddRelativeModal({ contacts = [] } = {}) {
    const root = document.getElementById('modal-root');
    if (!root) return Promise.resolve(null);
    const preparedContacts = Array.isArray(contacts)
      ? contacts
        .map((item) => String(item || '').trim())
        .filter(Boolean)
      : [];
    const uniqueContacts = Array.from(new Set(preparedContacts.map((item) => item.toLowerCase())))
      .map((key) => preparedContacts.find((item) => item.toLowerCase() === key))
      .filter(Boolean);

    root.innerHTML = `
      <div class="modal" id="profile-add-relative-modal">
        <div class="modal-card stack">
          <h3 class="modal-title">Добавить связь</h3>
          <label class="meta-muted" for="profile-relative-kind">Какой тип связи вы хотите добавить?</label>
          <select class="input profile-relation-select" id="profile-relative-kind">
            ${RELATIVE_RELATION_OPTIONS.map((item) => (
              `<option value="${item.value}">${item.label}</option>`
            )).join('')}
          </select>
          <label class="meta-muted" for="profile-relative-login">Логин пользователя</label>
          <input
            class="input"
            id="profile-relative-login"
            type="text"
            maxlength="30"
            placeholder="Введите логин пользователя"
          />
          <div class="meta-muted profile-relative-search-meta" id="profile-relative-search-meta">
            Начните вводить логин. Поиск запустится через 2 секунды паузы или по Enter.
          </div>
          <div class="profile-relative-search-suggest" id="profile-relative-search-suggest" hidden></div>
          <div class="meta-muted inline-error" id="profile-relative-error"></div>
          <div class="form-actions-grid">
            <button class="secondary-btn" id="profile-relative-cancel" type="button">Отмена</button>
            <button class="primary-btn" id="profile-relative-submit" type="button">Продолжить</button>
          </div>
        </div>
      </div>
    `;

    return new Promise((resolve) => {
      const modal = root.querySelector('#profile-add-relative-modal');
      const kindEl = root.querySelector('#profile-relative-kind');
      const loginEl = root.querySelector('#profile-relative-login');
      const submitEl = root.querySelector('#profile-relative-submit');
      const cancelEl = root.querySelector('#profile-relative-cancel');
      const errorEl = root.querySelector('#profile-relative-error');
      const searchMetaEl = root.querySelector('#profile-relative-search-meta');
      const suggestEl = root.querySelector('#profile-relative-search-suggest');

      if (!(modal instanceof HTMLElement) || !(kindEl instanceof HTMLSelectElement) || !(loginEl instanceof HTMLInputElement)) {
        root.innerHTML = '';
        resolve(null);
        return;
      }

      let closed = false;
      let searchTimerId = 0;
      let searchSeq = 0;

      const clearSearchTimer = () => {
        if (!searchTimerId) return;
        window.clearTimeout(searchTimerId);
        searchTimerId = 0;
      };

      const uniqueCaseInsensitive = (list) => {
        const out = [];
        const seen = new Set();
        (Array.isArray(list) ? list : []).forEach((item) => {
          const value = String(item || '').trim();
          if (!value) return;
          const key = value.toLowerCase();
          if (seen.has(key)) return;
          seen.add(key);
          out.push(value);
        });
        return out;
      };

      const renderSuggestions = (list) => {
        if (!(suggestEl instanceof HTMLElement)) return;
        const values = uniqueCaseInsensitive(list).slice(0, 5);
        if (!values.length) {
          suggestEl.hidden = true;
          suggestEl.innerHTML = '';
          return;
        }
        suggestEl.hidden = false;
        suggestEl.innerHTML = values.map((value) => (
          `<button type="button" class="profile-relative-suggest-item" data-login="${escapeHtml(value)}">${escapeHtml(value)}</button>`
        )).join('');
      };

      const searchContactsFallback = (prefix) => {
        const query = String(prefix || '').trim().toLowerCase();
        if (!query) return [];
        return uniqueContacts
          .filter((entry) => entry.toLowerCase().startsWith(query))
          .slice(0, 5);
      };

      const runSearch = async ({ withErrorMessage = false } = {}) => {
        const prefix = String(loginEl.value || '').trim();
        if (!prefix) {
          renderSuggestions([]);
          if (searchMetaEl) {
            searchMetaEl.textContent = 'Начните вводить логин. Поиск запустится через 2 секунды паузы или по Enter.';
          }
          return;
        }

        if (searchMetaEl) searchMetaEl.textContent = `Поиск пользователей по префиксу «${prefix}»...`;
        const reqId = ++searchSeq;
        let found = [];
        let searchFailed = false;

        try {
          const payload = await authService.searchUsers(prefix);
          found = Array.isArray(payload) ? payload : [];
        } catch {
          searchFailed = true;
          found = [];
        }

        if (closed || reqId !== searchSeq) return;

        const query = prefix.toLowerCase();
        const candidateList = uniqueCaseInsensitive([
          ...found,
          ...searchContactsFallback(prefix),
        ])
          .filter((entry) => entry.toLowerCase().startsWith(query))
          .slice(0, 5);

        renderSuggestions(candidateList);

        if (candidateList.length > 0) {
          if (searchMetaEl) searchMetaEl.textContent = `Найдено ${candidateList.length} пользователей. Выберите пользователя из списка.`;
          return;
        }

        if (searchFailed) {
          if (searchMetaEl) searchMetaEl.textContent = 'Не удалось получить список пользователей. Уточните логин вручную.';
          if (withErrorMessage && errorEl) errorEl.textContent = 'Ошибка поиска пользователей.';
          return;
        }
        if (searchMetaEl) searchMetaEl.textContent = 'Пользователи с таким префиксом не найдены.';
      };

      const close = (payload = null) => {
        closed = true;
        clearSearchTimer();
        root.innerHTML = '';
        resolve(payload);
      };

      const submit = () => {
        const relationType = String(kindEl.value || '').trim();
        const toLogin = String(loginEl.value || '').trim();
        if (!relationType) {
          if (errorEl) errorEl.textContent = 'Выберите тип связи.';
          return;
        }
        if (!toLogin) {
          if (errorEl) errorEl.textContent = 'Введите логин пользователя.';
          return;
        }
        close({ relationType, toLogin });
      };

      modal.addEventListener('click', (event) => {
        if (event.target === modal) close(null);
      });
      cancelEl?.addEventListener('click', () => close(null));
      submitEl?.addEventListener('click', submit);
      suggestEl?.addEventListener('click', (event) => {
        const target = event.target;
        if (!(target instanceof HTMLElement)) return;
        const button = target.closest('[data-login]');
        if (!(button instanceof HTMLElement)) return;
        const pickedLogin = String(button.dataset.login || '').trim();
        if (!pickedLogin) return;
        loginEl.value = pickedLogin;
        if (errorEl) errorEl.textContent = '';
        if (searchMetaEl) searchMetaEl.textContent = `Выбран пользователь «${pickedLogin}». Нажмите «Продолжить».`;
        renderSuggestions([]);
      });
      loginEl.addEventListener('input', () => {
        if (errorEl) errorEl.textContent = '';
        clearSearchTimer();
        const value = String(loginEl.value || '').trim();
        if (!value) {
          renderSuggestions([]);
          if (searchMetaEl) {
            searchMetaEl.textContent = 'Начните вводить логин. Поиск запустится через 2 секунды паузы или по Enter.';
          }
          return;
        }
        if (searchMetaEl) searchMetaEl.textContent = 'Ожидание паузы 2 секунды для поиска...';
        searchTimerId = window.setTimeout(() => {
          runSearch({ withErrorMessage: false });
        }, 2000);
      });
      loginEl.addEventListener('keydown', (event) => {
        if (event.key === 'Enter') {
          event.preventDefault();
          clearSearchTimer();
          runSearch({ withErrorMessage: true });
        }
      });
      window.setTimeout(() => loginEl.focus(), 0);
    });
  }

  function renderFields(fields) {
    listWrap.innerHTML = '';
    fields.forEach((field) => {
      const row = document.createElement('div');
      row.className = 'card profile-param-item row';
      row.dataset.editField = field.key;
      row.style.cursor = 'pointer';
      const value = String(field.value || '').trim() || 'не заполнено';
      const isNameField = field.key === 'first_name' || field.key === 'last_name';
      const valueClass = isNameField ? 'profile-param-value profile-param-value-small' : 'profile-param-value';
      row.innerHTML = `<div class="${valueClass}"><b>${field.label}</b>: ${escapeHtml(value)}</div>`;
      listWrap.append(row);

      if (field.key === 'last_name') {
        const genderRow = document.createElement('div');
        genderRow.className = 'card profile-param-item row';
        genderRow.dataset.editGender = 'true';
        genderRow.style.cursor = 'pointer';
        genderRow.innerHTML = `<div class="profile-param-value"><b>Пол</b>: <span data-gender-value>${escapeHtml(genderLabel(currentGender))}</span></div>`;
        listWrap.append(genderRow);
      }
    });
  }

  async function refreshProfileSnapshot() {
    status.className = 'status-line';
    status.textContent = 'Загрузка параметров...';
    reloadBtn.disabled = true;
    officialBtn.disabled = true;
    shineBtn.disabled = true;
    if (addRelativeBtn instanceof HTMLButtonElement) addRelativeBtn.disabled = true;

    try {
      const snapshot = await loadProfileSnapshot(login);
      currentFields = snapshot.fields;
      currentToggles = snapshot.toggles;
      currentGender = snapshot.gender || PROFILE_GENDER_UNKNOWN;
      currentAvatar = snapshot.avatar || { value: '', source: '', txId: '', sha256Hex: '', timeMs: 0 };

      syncIdentity();
      renderFields(currentFields);
      updateTogglesUi();
      updateGenderUi();
      updateAvatarUi();

      status.className = 'status-line';
      status.textContent = '';
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = `Не удалось загрузить параметры: ${error.message || 'ошибка сети'}`;
      showLocalErrorAlert('Ошибка загрузки параметров профиля', error);
    } finally {
      reloadBtn.disabled = false;
      officialBtn.disabled = false;
      shineBtn.disabled = false;
      if (addRelativeBtn instanceof HTMLButtonElement) addRelativeBtn.disabled = false;
    }
  }

  async function onChangeAvatarClick() {
    const confirmed = window.confirm('Сменить аватар?');
    if (!confirmed) return;
    status.className = 'status-line';
    status.textContent = 'Открываем мастер аватара...';

    try {
      await openAvatarWizard({
        login,
        storagePwd: state.session.storagePwdInMemory,
        gateway: state.entrySettings.arweaveServer,
        navigate,
        onStatus: (message) => {
          status.className = 'status-line';
          status.textContent = String(message || '');
        },
        onAvatarSaved: async () => {
          status.className = 'status-line';
          status.textContent = 'Сохраняем аватар в профиль...';
          await refreshProfileSnapshot();
          status.className = 'status-line is-available';
          status.textContent = 'Аватар обновлён.';
        },
      });
      if (!status.textContent) {
        status.className = 'status-line';
      }
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = error?.message || 'Не удалось открыть мастер аватара.';
    }
  }

  async function onToggleClick(toggleKey) {
    const toggle = currentToggles.find((item) => item.key === toggleKey) || { enabled: false };
    const nextEnabled = !toggle.enabled;
    const title = toggleKey === 'official' ? 'официальный' : 'сияющий';

    const confirmed = window.confirm(
      `Хотите изменить «${title}» на ${toggleText(nextEnabled)}?\n` +
      'Будет создана запись в блокчейне.',
    );
    if (!confirmed) return;

    status.className = 'status-line';
    status.textContent = 'Сохранение в блокчейн...';

    try {
      await saveProfileToggle(login, toggleKey, nextEnabled);
      await refreshProfileSnapshot();
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = `Не удалось изменить ${toggleKey}: ${error.message || 'ошибка сети'}`;
      showLocalErrorAlert(`Ошибка изменения ${toggleKey}`, error);
    }
  }

  async function onEditFieldClick(fieldKey) {
    const field = currentFields.find((item) => item.key === fieldKey);
    if (!field) return;

    const entered = await openFieldEditModal({
      label: field.label,
      value: field.value || '',
      placeholder: field.placeholder || '',
    });
    if (entered === null) return;

    status.className = 'status-line';
    status.textContent = 'Сохранение в блокчейн...';

    try {
      await saveProfileParamBlock(login, field.key, entered);
      await refreshProfileSnapshot();
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = `Не удалось изменить ${field.key}: ${error.message || 'ошибка сети'}`;
      showLocalErrorAlert(`Ошибка изменения ${field.key}`, error);
    }
  }

  async function onGenderClick() {
    const nextGender = await openGenderPickerModal(currentGender);
    if (!nextGender) return;

    status.className = 'status-line';
    status.textContent = 'Сохранение в блокчейн...';

    try {
      await saveProfileGender(login, nextGender);
      await refreshProfileSnapshot();
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = `Не удалось изменить пол: ${error.message || 'ошибка сети'}`;
      showLocalErrorAlert('Ошибка изменения пола', error);
    }
  }

  async function onAddRelativeClick() {
    const sessionLogin = String(login || '').trim();
    if (!sessionLogin) {
      window.alert('Для добавления связи нужен активный логин.');
      return;
    }

    status.className = 'status-line';
    status.textContent = 'Подготовка окна добавления связи...';

    let contacts = [];
    try {
      const payload = await authService.listContacts();
      contacts = Array.isArray(payload?.contacts) ? payload.contacts : [];
    } catch {
      contacts = [];
    }

    const picked = await openAddRelativeModal({ contacts });
    if (!picked) {
      status.className = 'status-line is-available';
      status.textContent = 'Добавление связи отменено.';
      return;
    }

    const relationType = String(picked.relationType || '').trim().toLowerCase();
    const inputLogin = String(picked.toLogin || '').trim();
    if (!relationType || !inputLogin) return;
    if (inputLogin.toLowerCase() === sessionLogin.toLowerCase()) {
      status.className = 'status-line is-unavailable';
      status.textContent = 'Нельзя добавить связь с самим собой.';
      return;
    }

    status.className = 'status-line';
    status.textContent = 'Проверка пользователя...';

    let targetCard;
    try {
      targetCard = await loadUserProfileCard(inputLogin);
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = `Пользователь не найден: ${error.message || 'unknown'}`;
      showLocalErrorAlert('Ошибка выбора пользователя', error);
      return;
    }

    const targetLogin = String(targetCard?.login || inputLogin).trim();
    const targetGender = normalizeGender(targetCard?.gender || PROFILE_GENDER_UNKNOWN);
    const relationLabel = relationAccusativeLabel(relationType, targetGender);
    const confirmed = window.confirm(
      `Добавить пользователя ${targetLogin} как ${relationLabel}?`,
    );
    if (!confirmed) return;

    status.className = 'status-line';
    status.textContent = 'Сохранение связи...';

    try {
      if (relationType === 'close_friend') {
        await authService.addCloseFriend(targetLogin);
      } else {
        if (!state.session.storagePwdInMemory) {
          throw new Error('Нет storagePwd в памяти сессии. Выполните вход заново.');
        }
        await authService.setUserRelation({
          login: sessionLogin,
          toLogin: targetLogin,
          kind: relationType,
          enabled: true,
          storagePwd: state.session.storagePwdInMemory,
        });
      }
      status.className = 'status-line is-available';
      status.textContent = `Связь добавлена: ${targetLogin} как ${relationLabel}.`;
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = `Не удалось добавить связь: ${error.message || 'ошибка сети'}`;
      showLocalErrorAlert('Ошибка добавления связи', error);
    }
  }

  listWrap.addEventListener('click', (event) => {
    const target = event.target;
    if (!(target instanceof HTMLElement)) return;
    const genderRow = target.closest('[data-edit-gender="true"]');
    if (genderRow) {
      onGenderClick();
      return;
    }
    const fieldRow = target.closest('[data-edit-field]');
    const fieldKey = String(fieldRow?.getAttribute('data-edit-field') || '');
    if (!fieldKey) return;
    onEditFieldClick(fieldKey);
  });

  reloadBtn.addEventListener('click', refreshProfileSnapshot);
  officialBtn.addEventListener('click', () => onToggleClick('official'));
  shineBtn.addEventListener('click', () => onToggleClick('shine'));
  addRelativeBtn?.addEventListener('click', onAddRelativeClick);
  avatarActionEl?.addEventListener('click', () => { void onChangeAvatarClick(); });

  card.append(topRow, badgesRow, status, listWrap, relativesCard);
  screen.append(card);

  updateAvatarUi();
  refreshProfileSnapshot();

  return screen;
}
