const fs = require('node:fs')
const path = require('node:path')

const ENABLED_VALUES = new Set(['1', 'true', 'yes'])

function parseEnvFile(content) {
  const env = {}

  for (const rawLine of content.split(/\r?\n/)) {
    const line = rawLine.trim()
    if (!line || line.startsWith('#')) continue

    const normalized = line.startsWith('export ') ? line.slice(7).trim() : line
    const separatorIndex = normalized.indexOf('=')
    if (separatorIndex === -1) continue

    const key = normalized.slice(0, separatorIndex).trim()
    if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue

    let value = normalized.slice(separatorIndex + 1)

    if (
      (value.startsWith('"') && value.endsWith('"')) ||
      (value.startsWith("'") && value.endsWith("'"))
    ) {
      const quote = value[0]
      value = value.slice(1, -1)

      if (quote === '"') {
        value = value
          .replace(/\\n/g, '\n')
          .replace(/\\r/g, '\r')
          .replace(/\\t/g, '\t')
          .replace(/\\"/g, '"')
          .replace(/\\\\/g, '\\')
      }
    }

    env[key] = value
  }

  return env
}

function loadEnvFile(filePath, env = process.env, { override = false } = {}) {
  if (!fs.existsSync(filePath)) return false
  const parsed = parseEnvFile(fs.readFileSync(filePath, 'utf8'))

  for (const [key, value] of Object.entries(parsed)) {
    if (override || env[key] === undefined) {
      env[key] = value
    }
  }

  return true
}

function isRunningInContainer() {
  return fs.existsSync('/.dockerenv')
}

function normalizeDatabaseUrlForExecution(env = process.env) {
  if (!env.DATABASE_URL) return env.DATABASE_URL

  let parsed
  try {
    parsed = new URL(env.DATABASE_URL)
  } catch {
    return env.DATABASE_URL
  }

  if (parsed.hostname !== 'postgres' || isRunningInContainer()) {
    return env.DATABASE_URL
  }

  const fallbackHost = env.POSTGRES_HOST_LOCAL ?? 'localhost'
  parsed.hostname = fallbackHost
  env.DATABASE_URL = parsed.toString()
  return env.DATABASE_URL
}

function loadDefaultEnvFiles(baseDir, env = process.env) {
  const candidates = [
    path.join(baseDir, '.env'),
    path.join(baseDir, '.env.local'),
    path.join(baseDir, '.env.docker.dev'),
  ]

  for (const candidate of candidates) {
    loadEnvFile(candidate, env)
  }
}

function ensureDatabaseUrl(env = process.env) {
  const shouldBuildFromPostgres = ENABLED_VALUES.has(
    env.DATABASE_URL_FROM_POSTGRES?.trim().toLowerCase() ?? '',
  )

  if (!shouldBuildFromPostgres) {
    return env.DATABASE_URL
  }

  if (!env.POSTGRES_PASSWORD) {
    throw new Error('DATABASE_URL_FROM_POSTGRES is enabled but POSTGRES_PASSWORD is not set')
  }

  const user = env.POSTGRES_USER ?? 'postgres'
  const password = env.POSTGRES_PASSWORD
  const host = env.POSTGRES_HOST ?? 'postgres'
  const port = env.POSTGRES_PORT ?? '5432'
  const database = env.POSTGRES_DB ?? 'rentaldrivego'

  env.DATABASE_URL = `postgresql://${encodeURIComponent(user)}:${encodeURIComponent(password)}@${host}:${port}/${encodeURIComponent(database)}`

  return env.DATABASE_URL
}

module.exports = {
  ensureDatabaseUrl,
  loadDefaultEnvFiles,
  loadEnvFile,
  normalizeDatabaseUrlForExecution,
}
