import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaService } from '../infra/prisma.service';

export const DEFAULT_SYSTEM_SETTINGS = [
  { key: 'PROJECT_NAME', value: 'MVK ID', description: 'Название проекта в интерфейсе и заголовке страницы' },
  { key: 'PROJECT_TAGLINE', value: 'Единый аккаунт для сервисов Lendry', description: 'Краткий слоган под названием проекта' },
  { key: 'PROJECT_DOMAIN', value: 'id.lendry.ru', description: 'Основной домен IdP (без пути)' },
  {
    key: 'PUBLIC_API_URL',
    value: 'http://localhost:3000',
    description: 'Публичный базовый URL API для OAuth и OpenID Connect (issuer). Пример: https://sso.example.ru/idp-api'
  },
  { key: 'PIN_LOCK_TIMEOUT_MINUTES', value: '15', description: 'Через сколько минут неактивности сессия блокируется PIN-кодом' },
  { key: 'PIN_DELETE_GRACE_MINUTES', value: '1440', description: 'Задержка перед окончательным удалением PIN-кода после запроса (минуты)' },
  { key: 'PIN_REQUIRE_ON_DELETE', value: 'true', description: 'Требовать текущий PIN-код при запросе удаления защиты' },
  { key: 'PIN_MIN_LENGTH', value: '4', description: 'Минимальная длина PIN-кода' },
  { key: 'PIN_MAX_LENGTH', value: '6', description: 'Максимальная длина PIN-кода' },
  { key: 'MAX_FAMILY_MEMBERS', value: '6', description: 'Максимальное количество участников в семейной группе' },
  { key: 'OTP_EXPIRY_MINUTES', value: '10', description: 'Время жизни OTP-кода для входа (минуты)' },
  { key: 'OTP_RESEND_COOLDOWN_SECONDS', value: '60', description: 'Минимальный интервал между повторными запросами OTP-кода (секунды)' },
  { key: 'OTP_MAX_ATTEMPTS', value: '5', description: 'Максимальное количество попыток ввода OTP' },
  {
    key: 'ACCOUNT_DELETE_GRACE_DAYS',
    value: '30',
    description: 'Через сколько дней после запроса окончательно удалить аккаунт пользователя'
  },
  { key: 'SESSION_REFRESH_DAYS', value: '30', description: 'Срок жизни refresh-токена (дни)' },
  { key: 'REGISTRATION_ENABLED', value: 'true', description: 'Разрешить регистрацию новых пользователей' },
  { key: 'AVATAR_URL_TTL_MINUTES', value: '15', description: 'Время жизни подписанной ссылки на аватар (минуты)' },
  { key: 'PASSWORD_MIN_LENGTH', value: '8', description: 'Минимальная длина пароля' },
  { key: 'MAX_ACTIVE_SESSIONS', value: '20', description: 'Максимум одновременных активных сессий на пользователя' },
  { key: 'MAINTENANCE_MODE', value: 'false', description: 'Режим обслуживания: блокирует вход для обычных пользователей' },
  { key: 'LDAP_ENABLED', value: 'false', description: 'Разрешить вход через LDAP/LDAPS' },
  { key: 'LDAP_USE_LDAPS', value: 'false', description: 'Использовать LDAPS (порт 636) вместо LDAP (порт 389)' },
  { key: 'LDAP_HOST', value: '', description: 'Хост LDAP: один сервер или несколько через запятую. Можно ldaps://dc-1.local:636' },
  { key: 'LDAP_PORT', value: '636', description: 'Порт LDAP-сервера (389 для LDAP, 636 для LDAPS)' },
  { key: 'LDAP_DOMAIN', value: '', description: 'Домен AD для UPN bind, например mvkug.local' },
  { key: 'LDAP_SKIP_TLS_VERIFY', value: 'false', description: 'Не проверять TLS-сертификат LDAPS (только для тестов)' },
  { key: 'LDAP_BASE_DN', value: '', description: 'Base DN для поиска пользователей, например OU=Lugansk,DC=example,DC=com' },
  { key: 'LDAP_BIND_USERNAME', value: '', description: 'Логин сервисной учётной записи для bind (например mvkadmin)' },
  { key: 'LDAP_BIND_DN', value: '', description: 'Полный Bind DN (опционально). Если указан, имеет приоритет над логином' },
  { key: 'LDAP_BIND_PASSWORD', value: '', description: 'Пароль сервисной учётной записи LDAP' },
  {
    key: 'LDAP_USER_FILTER',
    value: '(|(sAMAccountName={username})(userPrincipalName={username})(mail={username})(uid={username}))',
    description: 'LDAP-фильтр поиска пользователя. Используйте {username} как placeholder'
  },
  { key: 'LDAP_USERNAME_ATTR', value: 'sAMAccountName', description: 'Атрибут LDAP с логином пользователя' },
  { key: 'LDAP_EMAIL_ATTR', value: 'mail', description: 'Атрибут LDAP с почтой пользователя' },
  { key: 'LDAP_DISPLAY_NAME_ATTR', value: 'displayName', description: 'Атрибут LDAP с отображаемым именем' },
  { key: 'EMAIL_ENABLED', value: 'false', description: 'Отправлять OTP-коды на email через настроенный SMTP' },
  { key: 'EMAIL_PROVIDER', value: 'smtp', description: 'Провайдер email: smtp или console (только лог)' },
  { key: 'EMAIL_SMTP_HOST', value: '', description: 'SMTP-сервер, например smtp.yandex.ru или smtp.gmail.com' },
  { key: 'EMAIL_SMTP_PORT', value: '587', description: 'Порт SMTP (587 — STARTTLS, 465 — SSL)' },
  { key: 'EMAIL_SMTP_SECURE', value: 'false', description: 'SSL/TLS при подключении (true для порта 465)' },
  { key: 'EMAIL_SMTP_USER', value: '', description: 'Логин SMTP (обычно совпадает с адресом отправителя)' },
  { key: 'EMAIL_SMTP_PASSWORD', value: '', description: 'Пароль или app-password SMTP' },
  { key: 'EMAIL_FROM_ADDRESS', value: '', description: 'Адрес отправителя, например noreply@example.com' },
  { key: 'EMAIL_FROM_NAME', value: '', description: 'Имя отправителя в письме (пусто = название проекта)' },
  { key: 'SMS_ENABLED', value: 'false', description: 'Отправлять OTP-коды по SMS через настроенного провайдера' },
  { key: 'SMS_PROVIDER', value: 'smsru', description: 'SMS-провайдер: smsru, smsc, huawei_modem или console (только лог)' },
  { key: 'SMS_API_KEY', value: '', description: 'API-ключ sms.ru (api_id)' },
  { key: 'SMS_LOGIN', value: '', description: 'Логин smsc.ru' },
  { key: 'SMS_PASSWORD', value: '', description: 'Пароль smsc.ru' },
  { key: 'SMS_SENDER', value: '', description: 'Имя отправителя SMS (если поддерживается провайдером)' },
  {
    key: 'SMS_GATEWAY_URL',
    value: '',
    description: 'URL локального SMS-шлюза Huawei HiLink, например http://192.168.8.1'
  },
  {
    key: 'SMS_GATEWAY_USERNAME',
    value: 'admin',
    description: 'Логин веб-интерфейса модема Huawei HiLink (обычно admin)'
  },
  {
    key: 'SMS_GATEWAY_PASSWORD',
    value: '',
    description: 'Пароль веб-интерфейса модема Huawei HiLink'
  },
  {
    key: 'SMS_GATEWAY_MESSAGE_TEMPLATE',
    value: '{{appname}}: код {{code}}. Действует {{expiry}} мин.',
    description: 'Шаблон текста SMS для Huawei HiLink с тегами {{appname}}, {{code}}, {{expiry}}'
  },
  { key: 'BOT_MAX_BOTS_PER_USER', value: '5', description: 'Максимальное количество ботов на одного пользователя' },
  { key: 'BOT_API_RATE_LIMIT_PER_SECOND', value: '30', description: 'Лимит запросов Bot API на один токен в секунду' },
  { key: 'BOT_WEBHOOK_TIMEOUT_MS', value: '10000', description: 'Таймаут HTTP-запроса webhook бота (мс)' },
  { key: 'BOT_WEBHOOK_MAX_RETRIES', value: '3', description: 'Число повторов webhook с exponential backoff' }
] as const;

const SECRET_SETTING_KEYS = new Set([
  'LDAP_BIND_PASSWORD',
  'EMAIL_SMTP_PASSWORD',
  'SMS_API_KEY',
  'SMS_PASSWORD',
  'SMS_GATEWAY_PASSWORD'
]);

export const PUBLIC_SETTING_KEYS = [
  'PROJECT_NAME',
  'PROJECT_TAGLINE',
  'PROJECT_DOMAIN',
  'PUBLIC_API_URL',
  'REGISTRATION_ENABLED',
  'MAINTENANCE_MODE',
  'LDAP_ENABLED',
  'LDAP_USE_LDAPS'
] as const;

@Injectable()
export class SystemSettingsSeedService implements OnModuleInit {
  constructor(private readonly prisma: PrismaService) {}

  async onModuleInit() {
    for (const setting of DEFAULT_SYSTEM_SETTINGS) {
      await this.prisma.systemSetting.upsert({
        where: { key: setting.key },
        create: { ...setting, isSecret: SECRET_SETTING_KEYS.has(setting.key) },
        update: { description: setting.description, isSecret: SECRET_SETTING_KEYS.has(setting.key) }
      });
    }

    const envPublicApiUrl = process.env.PUBLIC_API_URL?.trim();
    if (envPublicApiUrl) {
      await this.prisma.systemSetting.upsert({
        where: { key: 'PUBLIC_API_URL' },
        create: {
          key: 'PUBLIC_API_URL',
          value: envPublicApiUrl,
          description: 'Публичный базовый URL API для OAuth и OpenID Connect (issuer). Пример: https://sso.example.ru/idp-api'
        },
        update: { value: envPublicApiUrl }
      });
    }
  }
}
