import crypto from 'crypto';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import { join } from 'path';

const CHAT_USERS_FILE_NAME = 'chat-users.json';

function ensureLogsDir(baseDir) {
  const logsDir = join(baseDir, '../logs');
  if (!existsSync(logsDir)) {
    mkdirSync(logsDir, { recursive: true });
  }
  return logsDir;
}

function getChatUsersPath(baseDir) {
  return join(ensureLogsDir(baseDir), CHAT_USERS_FILE_NAME);
}

function sha256(value) {
  return crypto.createHash('sha256').update(value).digest('hex');
}

export function ensureChatUsersFile(baseDir) {
  const usersPath = getChatUsersPath(baseDir);
  if (existsSync(usersPath)) return;
  writeFileSync(usersPath, '[]\n', 'utf-8');
  console.warn(
    `[Auth] ${CHAT_USERS_FILE_NAME} wurde neu erstellt. Bitte mindestens einen Admin-User mit Passwort-Hash konfigurieren.`
  );
}

export function loadChatUsers(baseDir) {
  ensureChatUsersFile(baseDir);
  const usersPath = getChatUsersPath(baseDir);
  const raw = readFileSync(usersPath, 'utf-8').trim();
  if (!raw) return [];

  let users = [];
  try {
    users = JSON.parse(raw);
  } catch (error) {
    throw new Error(`Ungültige ${CHAT_USERS_FILE_NAME}: ${error.message}`);
  }

  if (!Array.isArray(users)) {
    throw new Error(`${CHAT_USERS_FILE_NAME} muss ein Array sein`);
  }

  return users
    .filter((entry) => entry && typeof entry.username === 'string')
    .map((entry) => ({
      username: entry.username.trim(),
      passwordHash: typeof entry.passwordHash === 'string' ? entry.passwordHash.trim() : '',
      rights: Array.isArray(entry.rights) ? entry.rights.map((r) => String(r).toLowerCase()) : []
    }))
    .filter((entry) => entry.username && entry.passwordHash);
}

export function verifyChatUser(baseDir, username, password) {
  if (!username || !password) return null;
  const normalizedUser = String(username).trim();
  const passwordHash = sha256(password);
  const user = loadChatUsers(baseDir).find(
    (entry) => entry.username.toLowerCase() === normalizedUser.toLowerCase() && entry.passwordHash === passwordHash
  );

  if (!user) return null;

  return {
    username: user.username,
    rights: new Set(user.rights)
  };
}
