export type SystemSettingFieldType = 'text' | 'number' | 'boolean' | 'select' | 'textarea';

export interface SystemSettingMeta {
  key: string;
  label: string;
  group: string;
  type: SystemSettingFieldType;
  unit?: string;
  hint?: string;
  options?: Array<{ value: string; label: string }>;
  showWhen?: { key: string; equals: string };
}

export const SYSTEM_SETTING_GROUPS: Record<string, string> = {
  general: 'Проект и брендинг',
  pin: 'PIN-код и блокировка сессии',
  auth: 'Аутентификация и регистрация',
  ldap: 'LDAP / Active Directory',
  messaging: 'Email и SMS',
  limits: 'Лимиты и ограничения',
  media: 'Медиа и файлы'
};

export const SYSTEM_SETTING_CATALOG: SystemSettingMeta[] = [
  { key: 'PROJECT_NAME', label: 'Название проекта', group: 'general', type: 'text', hint: 'Отображается в меню, заголовке и боковой панели' },
  { key: 'PROJECT_TAGLINE', label: 'Слоган проекта', group: 'general', type: 'text' },
  { key: 'PROJECT_DOMAIN', label: 'Домен IdP', group: 'general', type: 'text', hint: 'Домен без пути, например sso.example.ru' },
  {
    key: 'PUBLIC_API_URL',
    label: 'URL API (OAuth issuer)',
    group: 'general',
    type: 'text',
    hint: 'Базовый URL API для OAuth/OIDC. Пример: https://sso.example.ru/idp-api или https://api.example.ru'
  },
  { key: 'PIN_LOCK_TIMEOUT_MINUTES', label: 'Таймаут блокировки PIN', group: 'pin', type: 'number', unit: 'мин' },
  { key: 'PIN_DELETE_GRACE_MINUTES', label: 'Задержка удаления PIN', group: 'pin', type: 'number', unit: 'мин', hint: 'Сколько ждать после запроса удаления PIN-кода' },
  { key: 'PIN_REQUIRE_ON_DELETE', label: 'Требовать PIN при удалении', group: 'pin', type: 'boolean' },
  { key: 'PIN_MIN_LENGTH', label: 'Мин. длина PIN', group: 'pin', type: 'number', unit: 'цифр' },
  { key: 'PIN_MAX_LENGTH', label: 'Макс. длина PIN', group: 'pin', type: 'number', unit: 'цифр' },
  { key: 'OTP_EXPIRY_MINUTES', label: 'Срок жизни OTP', group: 'auth', type: 'number', unit: 'мин' },
  { key: 'OTP_RESEND_COOLDOWN_SECONDS', label: 'Пауза перед повторной отправкой OTP', group: 'auth', type: 'number', unit: 'сек', hint: 'Минимальный интервал между запросами нового кода (обычно 60)' },
  { key: 'OTP_MAX_ATTEMPTS', label: 'Попыток ввода OTP', group: 'auth', type: 'number' },
  {
    key: 'ACCOUNT_DELETE_GRACE_DAYS',
    label: 'Отложенное удаление аккаунта',
    group: 'auth',
    type: 'number',
    unit: 'дн',
    hint: 'Срок ожидания перед окончательным удалением профиля после запроса пользователя'
  },
  { key: 'SESSION_REFRESH_DAYS', label: 'Срок refresh-токена', group: 'auth', type: 'number', unit: 'дн' },
  { key: 'PASSWORD_MIN_LENGTH', label: 'Мин. длина пароля', group: 'auth', type: 'number', unit: 'симв' },
  { key: 'REGISTRATION_ENABLED', label: 'Регистрация включена', group: 'auth', type: 'boolean' },
  { key: 'MAINTENANCE_MODE', label: 'Режим обслуживания', group: 'auth', type: 'boolean', hint: 'Блокирует вход для обычных пользователей' },
  { key: 'LDAP_ENABLED', label: 'LDAP включён', group: 'ldap', type: 'boolean', hint: 'Показывает кнопку входа через LDAP на странице авторизации' },
  { key: 'LDAP_USE_LDAPS', label: 'Использовать LDAPS', group: 'ldap', type: 'boolean', hint: 'Шифрованное подключение (порт 636)' },
  { key: 'LDAP_HOST', label: 'Хост LDAP', group: 'ldap', type: 'text', hint: 'DC-1.domain.local или IP контроллера (192.168.x.x), если Docker не резолвит AD-имена' },
  { key: 'LDAP_PORT', label: 'Порт LDAP', group: 'ldap', type: 'number', hint: '636 для LDAPS, 389 для LDAP. Не используйте 640.' },
  { key: 'LDAP_DOMAIN', label: 'Домен AD', group: 'ldap', type: 'text', hint: 'mvkug.local — для bind вида user@domain' },
  { key: 'LDAP_SKIP_TLS_VERIFY', label: 'Не проверять TLS', group: 'ldap', type: 'boolean', hint: 'Только для тестовых окружений' },
  { key: 'LDAP_BASE_DN', label: 'Base DN (поиск пользователей)', group: 'ldap', type: 'text', hint: 'OU или CN контейнера с пользователями. Напр. OU=Lugansk,DC=mvkug,DC=local. Если CN не работает — попробуйте OU' },
  { key: 'LDAP_BIND_USERNAME', label: 'Логин сервисной УЗ', group: 'ldap', type: 'text', hint: 'mvkadmin или mvkug\\mvkadmin — учётная запись для подключения к AD' },
  { key: 'LDAP_BIND_DN', label: 'Bind DN (опционально)', group: 'ldap', type: 'text', hint: 'Полный DN сервисной УЗ. Оставьте пустым, если указан логин выше' },
  { key: 'LDAP_BIND_PASSWORD', label: 'Пароль сервисной УЗ', group: 'ldap', type: 'text', hint: 'Секретное значение' },
  { key: 'LDAP_USER_FILTER', label: 'Фильтр пользователя', group: 'ldap', type: 'text', hint: 'Placeholder {username}' },
  { key: 'LDAP_USERNAME_ATTR', label: 'Атрибут логина', group: 'ldap', type: 'text' },
  { key: 'LDAP_EMAIL_ATTR', label: 'Атрибут почты', group: 'ldap', type: 'text' },
  { key: 'LDAP_DISPLAY_NAME_ATTR', label: 'Атрибут имени', group: 'ldap', type: 'text' },
  { key: 'EMAIL_ENABLED', label: 'Email включён', group: 'messaging', type: 'boolean', hint: 'Отправка OTP-кодов на почту через SMTP' },
  {
    key: 'EMAIL_PROVIDER',
    label: 'Email-провайдер',
    group: 'messaging',
    type: 'select',
    options: [
      { value: 'smtp', label: 'SMTP (Yandex, Gmail, Mail.ru и др.)' },
      { value: 'console', label: 'Только лог (отладка)' }
    ],
    showWhen: { key: 'EMAIL_ENABLED', equals: 'true' }
  },
  { key: 'EMAIL_SMTP_HOST', label: 'SMTP-хост', group: 'messaging', type: 'text', hint: 'smtp.yandex.ru, smtp.gmail.com', showWhen: { key: 'EMAIL_ENABLED', equals: 'true' } },
  { key: 'EMAIL_SMTP_PORT', label: 'SMTP-порт', group: 'messaging', type: 'number', unit: 'порт', showWhen: { key: 'EMAIL_ENABLED', equals: 'true' } },
  { key: 'EMAIL_SMTP_SECURE', label: 'SMTP SSL/TLS', group: 'messaging', type: 'boolean', hint: 'Включите для порта 465', showWhen: { key: 'EMAIL_ENABLED', equals: 'true' } },
  { key: 'EMAIL_SMTP_USER', label: 'SMTP-логин', group: 'messaging', type: 'text', showWhen: { key: 'EMAIL_ENABLED', equals: 'true' } },
  { key: 'EMAIL_SMTP_PASSWORD', label: 'SMTP-пароль', group: 'messaging', type: 'text', hint: 'App-password для Gmail/Yandex', showWhen: { key: 'EMAIL_ENABLED', equals: 'true' } },
  { key: 'EMAIL_FROM_ADDRESS', label: 'Email отправителя', group: 'messaging', type: 'text', hint: 'noreply@yourdomain.ru', showWhen: { key: 'EMAIL_ENABLED', equals: 'true' } },
  { key: 'EMAIL_FROM_NAME', label: 'Имя отправителя', group: 'messaging', type: 'text', showWhen: { key: 'EMAIL_ENABLED', equals: 'true' } },
  { key: 'SMS_ENABLED', label: 'SMS включён', group: 'messaging', type: 'boolean', hint: 'Отправка OTP-кодов по SMS' },
  {
    key: 'SMS_PROVIDER',
    label: 'SMS-провайдер',
    group: 'messaging',
    type: 'select',
    options: [
      { value: 'smsru', label: 'sms.ru' },
      { value: 'smsc', label: 'smsc.ru' },
      { value: 'huawei_modem', label: 'Huawei E5573 (локальный шлюз)' },
      { value: 'console', label: 'Только лог (отладка)' }
    ],
    showWhen: { key: 'SMS_ENABLED', equals: 'true' }
  },
  {
    key: 'SMS_GATEWAY_URL',
    label: 'URL локального SMS-шлюза',
    group: 'messaging',
    type: 'text',
    hint: 'IP или URL модема Huawei HiLink, например http://192.168.8.1',
    showWhen: { key: 'SMS_ENABLED', equals: 'true' }
  },
  {
    key: 'SMS_GATEWAY_USERNAME',
    label: 'Логин модема Huawei',
    group: 'messaging',
    type: 'text',
    hint: 'Обычно admin',
    showWhen: { key: 'SMS_ENABLED', equals: 'true' }
  },
  {
    key: 'SMS_GATEWAY_PASSWORD',
    label: 'Пароль модема Huawei',
    group: 'messaging',
    type: 'text',
    hint: 'Пароль веб-интерфейса модема (требуется для отправки SMS)',
    showWhen: { key: 'SMS_ENABLED', equals: 'true' }
  },
  {
    key: 'SMS_GATEWAY_MESSAGE_TEMPLATE',
    label: 'Шаблон текста SMS (Huawei)',
    group: 'messaging',
    type: 'textarea',
    hint: 'Теги: {{appname}} — название проекта, {{code}} — OTP-код, {{expiry}} — срок действия в минутах',
    showWhen: { key: 'SMS_ENABLED', equals: 'true' }
  },
  { key: 'SMS_API_KEY', label: 'API-ключ sms.ru', group: 'messaging', type: 'text', hint: 'api_id из личного кабинета sms.ru', showWhen: { key: 'SMS_ENABLED', equals: 'true' } },
  { key: 'SMS_LOGIN', label: 'Логин smsc.ru', group: 'messaging', type: 'text', showWhen: { key: 'SMS_ENABLED', equals: 'true' } },
  { key: 'SMS_PASSWORD', label: 'Пароль smsc.ru', group: 'messaging', type: 'text', showWhen: { key: 'SMS_ENABLED', equals: 'true' } },
  { key: 'SMS_SENDER', label: 'Имя отправителя SMS', group: 'messaging', type: 'text', hint: 'Опционально, если одобрено провайдером', showWhen: { key: 'SMS_ENABLED', equals: 'true' } },
  { key: 'MAX_FAMILY_MEMBERS', label: 'Макс. участников семьи', group: 'limits', type: 'number' },
  { key: 'MAX_ACTIVE_SESSIONS', label: 'Макс. активных сессий', group: 'limits', type: 'number' },
  { key: 'AVATAR_URL_TTL_MINUTES', label: 'TTL ссылки на аватар', group: 'media', type: 'number', unit: 'мин' }
];

export function getSettingMeta(key: string) {
  return SYSTEM_SETTING_CATALOG.find((item) => item.key === key);
}

export function isSettingVisible(setting: { key: string; value: string }, allSettings: Array<{ key: string; value: string }>) {
  const meta = getSettingMeta(setting.key);
  if (!meta?.showWhen) return true;
  const parent = allSettings.find((item) => item.key === meta.showWhen!.key);
  const parentValue = parent?.value ?? 'false';
  return parseBooleanValue(parentValue) === parseBooleanValue(meta.showWhen.equals);
}

function parseBooleanValue(value: string) {
  return ['true', '1', 'yes'].includes(value.trim().toLowerCase());
}

export const MESSAGING_SETTING_KEYS = SYSTEM_SETTING_CATALOG.filter((item) => item.group === 'messaging').map((item) => item.key);

export const EMAIL_SETTING_KEYS = SYSTEM_SETTING_CATALOG.filter((item) =>
  item.key.startsWith('EMAIL_')
).map((item) => item.key);

export const SMS_SETTING_KEYS = SYSTEM_SETTING_CATALOG.filter((item) =>
  item.key.startsWith('SMS_')
).map((item) => item.key);

export function sortSettingsByCatalog<T extends { key: string }>(settings: T[]) {
  const order = new Map(SYSTEM_SETTING_CATALOG.map((item, index) => [item.key, index]));
  return [...settings].sort((a, b) => (order.get(a.key) ?? 999) - (order.get(b.key) ?? 999));
}
