#!/usr/bin/env node
/**
 * Script zum Setzen des Admin-Passworts
 * 
 * Verwendung:
 *   node scripts/set-admin-password.js <neues-passwort>
 * 
 * Oder interaktiv:
 *   node scripts/set-admin-password.js
 */

import fs from 'fs/promises'
import path from 'path'
import { fileURLToPath } from 'url'
import bcrypt from 'bcryptjs'
import { decryptObject, encryptObject } from '../server/utils/encryption.js'
import dotenv from 'dotenv'
import readline from 'readline'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

// Lade .env Datei
dotenv.config({ path: path.join(__dirname, '..', '.env') })

const ADMIN_EMAIL = 'admin@harheimertc.de'

// Pfade bestimmen
function getDataPath(filename) {
  const cwd = process.cwd()
  if (cwd.endsWith('.output')) {
    // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
    return path.join(cwd, '../server/data', filename)
  }
  // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
  return path.join(cwd, 'server/data', filename)
}

const USERS_FILE = getDataPath('users.json')

// Get encryption key from environment
function getEncryptionKey() {
  return process.env.ENCRYPTION_KEY || 'local_development_encryption_key_change_in_production'
}

// Prüft ob Daten verschlüsselt sind
function isEncrypted(data) {
  try {
    const parsed = JSON.parse(data.trim())
    if (Array.isArray(parsed)) {
      return false
    }
    if (typeof parsed === 'object' && parsed !== null && !parsed.encryptedData) {
      return false
    }
    return false
  } catch (e) {
    return true
  }
}

// Liest Benutzer aus Datei
async function readUsers() {
  try {
    const data = await fs.readFile(USERS_FILE, 'utf-8')
    const encrypted = isEncrypted(data)
    
    if (encrypted) {
      const encryptionKey = getEncryptionKey()
      try {
        return decryptObject(data, encryptionKey)
      } catch (decryptError) {
        console.error('Fehler beim Entschlüsseln der Benutzerdaten:', decryptError.message)
        throw new Error('Konnte Benutzerdaten nicht entschlüsseln. Bitte prüfe ENCRYPTION_KEY in .env')
      }
    } else {
      return JSON.parse(data)
    }
  } catch (error) {
    if (error.code === 'ENOENT') {
      return []
    }
    throw error
  }
}

// Schreibt Benutzer in Datei (immer verschlüsselt)
async function writeUsers(users) {
  try {
    const encryptionKey = getEncryptionKey()
    const encryptedData = encryptObject(users, encryptionKey)
    await fs.writeFile(USERS_FILE, encryptedData, 'utf-8')
    return true
  } catch (error) {
    console.error('Fehler beim Schreiben der Benutzerdaten:', error)
    return false
  }
}

// Hash-Passwort generieren
async function hashPassword(password) {
  const salt = await bcrypt.genSalt(10)
  return await bcrypt.hash(password, salt)
}

// Fragt nach Passwort (wenn nicht als Argument übergeben)
function askPassword() {
  return new Promise((resolve) => {
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout
    })
    
    rl.question('Neues Passwort für admin@harheimertc.de: ', (password) => {
      rl.close()
      resolve(password)
    })
  })
}

// Fragt nach Bestätigung
function askConfirmation(question) {
  return new Promise((resolve) => {
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout
    })
    
    rl.question(`${question} (j/n): `, (answer) => {
      rl.close()
      resolve(answer.toLowerCase() === 'j' || answer.toLowerCase() === 'y' || answer.toLowerCase() === 'ja' || answer.toLowerCase() === 'yes')
    })
  })
}

// Erstellt ein Backup der users.json
async function createBackup() {
  try {
    await fs.access(USERS_FILE)
    // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
    const backupDir = path.join(__dirname, '..', 'backups', `users-${Date.now()}`)
    await fs.mkdir(backupDir, { recursive: true })
    // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
    const backupPath = path.join(backupDir, 'users.json')
    await fs.copyFile(USERS_FILE, backupPath)
    // nosemgrep: javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring
    console.log(`📦 Backup erstellt: ${backupPath}`)
    return backupPath
  } catch (error) {
    if (error.code === 'ENOENT') {
      console.log('ℹ️  users.json existiert nicht, kein Backup nötig')
      return null
    }
    throw error
  }
}

// Erstellt eine neue users.json mit Admin-User
async function createNewUsersFile(password) {
  const hashedPassword = await hashPassword(password)
  
  const adminUser = {
    id: Date.now().toString(),
    email: ADMIN_EMAIL,
    password: hashedPassword,
    name: 'Administrator',
    role: 'admin',
    active: true,
    created: new Date().toISOString(),
    lastLogin: null
  }
  
  return [adminUser]
}

// Hauptfunktion
async function main() {
  console.log('🔐 Admin-Passwort setzen\n')
  
  // Prüfe ob --recreate Flag gesetzt ist
  const recreateFlag = process.argv.includes('--recreate') || process.argv.includes('-r')
  
  // Passwort aus Kommandozeilenargumenten oder interaktiv abfragen
  // Filtere Flags heraus und nimm das erste verbleibende Argument als Passwort
  const args = process.argv.slice(2).filter(arg => !arg.startsWith('--') && !arg.startsWith('-'))
  let newPassword = args.length > 0 ? args[0] : null
  
  if (!newPassword) {
    newPassword = await askPassword()
  }
  
  if (!newPassword || newPassword.trim().length === 0) {
    console.error('❌ FEHLER: Passwort darf nicht leer sein!')
    process.exit(1)
  }
  
  if (newPassword.length < 8) {
    console.error('❌ FEHLER: Passwort muss mindestens 8 Zeichen lang sein!')
    process.exit(1)
  }
  
  try {
    // Benutzer laden
    console.log('📖 Lade Benutzerdaten...')
    let users
    let shouldRecreate = recreateFlag
    
    try {
      users = await readUsers()
    } catch (error) {
      if (error.message.includes('entschlüsseln') || error.message.includes('Entschlüsselung')) {
        console.error('\n⚠️  WARNUNG: Konnte Benutzerdaten nicht entschlüsseln!')
        console.error('   Dies bedeutet, dass der ENCRYPTION_KEY nicht mit dem verwendeten Schlüssel übereinstimmt.\n')
        
        if (!shouldRecreate) {
          const confirmed = await askConfirmation('Möchten Sie die users.json Datei neu erstellen? (Alte Datei wird als Backup gespeichert)')
          if (!confirmed) {
            console.log('\n❌ Abgebrochen. Bitte setzen Sie ENCRYPTION_KEY in der .env Datei auf den korrekten Wert.')
            process.exit(1)
          }
          shouldRecreate = true
        }
        
        // Backup erstellen
        await createBackup()
        
        // Neue Datei erstellen
        console.log('\n🆕 Erstelle neue users.json Datei...')
        users = await createNewUsersFile(newPassword)
        
        // Direkt speichern
        console.log('💾 Speichere neue Benutzerdaten...')
        const success = await writeUsers(users)
        
        if (success) {
          console.log('\n✅ Neue users.json Datei erfolgreich erstellt!')
          // nosemgrep: javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring
          console.log(`📧 E-Mail: ${ADMIN_EMAIL}`)
          console.log(`👤 Rolle: admin`)
          console.log(`✅ Status: Aktiv`)
          console.log(`🔐 Passwort: Gesetzt`)
        } else {
          console.error('\n❌ FEHLER: Konnte Benutzerdaten nicht speichern!')
          process.exit(1)
        }
        
        return
      } else {
        throw error
      }
    }
    
    // Admin-User finden oder erstellen
    let adminUser = users.find(u => u.email.toLowerCase() === ADMIN_EMAIL.toLowerCase())
    
    if (!adminUser) {
      // nosemgrep: javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring
      console.log(`ℹ️  Admin-User (${ADMIN_EMAIL}) nicht gefunden, erstelle neuen Benutzer...`)
      adminUser = {
        id: Date.now().toString(),
        email: ADMIN_EMAIL,
        name: 'Administrator',
        role: 'admin',
        active: true,
        created: new Date().toISOString(),
        lastLogin: null
      }
      users.push(adminUser)
    } else {
      // nosemgrep: javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring
      console.log(`✅ Admin-User gefunden: ${adminUser.name || ADMIN_EMAIL}`)
    }
    
    // Passwort hashen
    console.log('🔐 Hashe Passwort...')
    const hashedPassword = await hashPassword(newPassword)
    
    // Passwort setzen
    adminUser.password = hashedPassword
    adminUser.updated = new Date().toISOString()
    
    // Benutzer speichern
    console.log('💾 Speichere Benutzerdaten...')
    const success = await writeUsers(users)
    
    if (success) {
      console.log('\n✅ Passwort erfolgreich gesetzt!')
      // nosemgrep: javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring
      console.log(`✅ Status: ${adminUser.active ? 'Aktiv' : 'Inaktiv'}`)
    } else {
      console.error('\n❌ FEHLER: Konnte Benutzerdaten nicht speichern!')
      process.exit(1)
    }
    
  } catch (error) {
    console.error('\n❌ FEHLER:', error.message)
    console.error(error.stack)
    process.exit(1)
  }
}

// Script ausführen
main().catch(error => {
  console.error('Unerwarteter Fehler:', error)
  process.exit(1)
})

