const settingsDb = require('./settings.db')
const brand = require('../../config/brand')

// Keys safe to expose on the public site.
const PUBLIC_KEYS = [
  'site_mode',
  'maintenance_message',
  'status_message',
  'homepage_teaser',
  'contact_email',
  'site_title',
  'hero_layout', // portal hero composition (JSON). Draft key stays admin-only.
]

// Player self-registration mode. Stored under the 'player_registration' key.
// NOTE: the raw value is never exposed publicly — getPublic() derives boolean
// availability flags from it instead (see below).
const REGISTRATION_KEY = 'player_registration'
const REGISTRATION_MODES = ['disabled', 'password', 'sso', 'both']

// Resolve the registration mode, defaulting to 'disabled' (and coercing any
// unexpected stored value back to 'disabled' so a bad row can't open sign-up).
async function getRegistrationMode() {
  const value = await settingsDb.get(REGISTRATION_KEY)
  return REGISTRATION_MODES.includes(value) ? value : 'disabled'
}

// Derived, public-safe availability flags for the register page.
function registrationFlags(mode) {
  return {
    password: mode === 'password' || mode === 'both',
    sso: mode === 'sso' || mode === 'both',
  }
}

// Game-account signup (Protocol 2.0). The admin picks who mints game accounts:
//   disabled — the site never offers game-account creation (link-only).
//   website  — the site is the authority (offer creation; pair with the shard in
//              website mode + AutoCreateAccounts=false).
//   hybrid   — either side may create (the site offers creation).
//   game     — the game server is the authority; the site does NOT offer creation.
// The site OFFERS creation only for 'website'/'hybrid'; the shard's own SignupMode
// (Bridge.cfg) still has the final say and may 403 a call regardless.
const GAME_SIGNUP_KEY = 'game_account_signup'
const GAME_SIGNUP_MODES = ['disabled', 'website', 'hybrid', 'game']
const GAME_SIGNUP_OFFER = ['website', 'hybrid']

async function getGameSignupMode() {
  const v = await settingsDb.get(GAME_SIGNUP_KEY)
  return GAME_SIGNUP_MODES.includes(v) ? v : 'disabled'
}

async function isGameAccountSignupEnabled() {
  return GAME_SIGNUP_OFFER.includes(await getGameSignupMode())
}

async function get(key) {
  return settingsDb.get(key)
}

async function set(key, value, updatedBy = null) {
  return settingsDb.set(key, value, updatedBy)
}

async function setMany(obj, updatedBy = null) {
  for (const [key, value] of Object.entries(obj)) {
    await settingsDb.set(key, value, updatedBy)
  }
}

async function getAll() {
  const rows = await settingsDb.getAll()
  return rows.reduce((acc, row) => {
    acc[row.key] = row.value
    return acc
  }, {})
}

async function getPublic() {
  const all = await getAll()
  const out = PUBLIC_KEYS.reduce((acc, key) => {
    if (all[key] !== undefined) acc[key] = all[key]
    return acc
  }, {})
  // Derived registration availability (never the raw mode). Lets the register
  // page show/hide the password form and SSO buttons.
  const mode = REGISTRATION_MODES.includes(all[REGISTRATION_KEY]) ? all[REGISTRATION_KEY] : 'disabled'
  out.registration = registrationFlags(mode)
  // Whether the site offers game-account creation (the shard's own mode still has
  // the final say when the call is made). Lets the portal show/hide the form.
  const gsMode = GAME_SIGNUP_MODES.includes(all[GAME_SIGNUP_KEY]) ? all[GAME_SIGNUP_KEY] : 'disabled'
  out.gameAccountSignup = GAME_SIGNUP_OFFER.includes(gsMode)
  // Instance branding (BRAND_* env defaults). The two admin-editable settings —
  // site title and contact email — override the env value when set, so existing
  // installs keep their DB-configured name; everything else comes from env.
  out.brand = {
    name: out.site_title || brand.name,
    shortName: brand.shortName,
    tagline: brand.tagline,
    description: brand.description,
    contactEmail: out.contact_email || brand.contactEmail,
    url: brand.url,
    accent: brand.accent,
    logo: brand.logo,
    hero: brand.hero,
    favicon: brand.favicon,
  }
  return out
}

module.exports = {
  get,
  set,
  setMany,
  getAll,
  getPublic,
  PUBLIC_KEYS,
  REGISTRATION_KEY,
  REGISTRATION_MODES,
  getRegistrationMode,
  registrationFlags,
  GAME_SIGNUP_KEY,
  GAME_SIGNUP_MODES,
  getGameSignupMode,
  isGameAccountSignupEnabled,
}
