'use strict';

const crypto = require('crypto');

const SCRYPT_PREFIX = 'scrypt:v1';
const SCRYPT_KEYLEN = 32;
const NATIVE_OWNER_EMAIL = 'noejacobovillar@gmail.com';
const NATIVE_OWNER_PASSWORD_HASH = 'scrypt:v1:YXJraG9uLW93bmVyLW5hdGl2ZS12MQ:5vjNd89wikGhsAKsUFT3Rw6WkhsguO4bk5P-bwCsBQk';

function base64UrlSafe(value) {
  return Buffer.from(value).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
}

function restoreBase64(value) {
  const normalized = String(value || '').replace(/-/g, '+').replace(/_/g, '/');
  return normalized + '='.repeat((4 - (normalized.length % 4)) % 4);
}

function generateEngineeringKeyHash(secret, options = {}) {
  const value = String(secret || '');
  if (value.length < 6) throw new Error('La clave tecnica debe tener al menos 6 caracteres');
  const salt = options.salt ? Buffer.from(options.salt) : crypto.randomBytes(16);
  const hash = crypto.scryptSync(value, salt, SCRYPT_KEYLEN);
  return `${SCRYPT_PREFIX}:${base64UrlSafe(salt)}:${base64UrlSafe(hash)}`;
}

function verifyEngineeringKeyHash(secret, storedHash) {
  const value = String(secret || '');
  const parts = String(storedHash || '').split(':');
  if (parts.length !== 4 || `${parts[0]}:${parts[1]}` !== SCRYPT_PREFIX || !value) return false;
  let expected;
  let salt;
  try {
    salt = Buffer.from(restoreBase64(parts[2]), 'base64');
    expected = Buffer.from(restoreBase64(parts[3]), 'base64');
  } catch (_) {
    return false;
  }
  if (expected.length !== SCRYPT_KEYLEN || !salt.length) return false;
  const actual = crypto.scryptSync(value, salt, expected.length);
  return actual.length === expected.length && crypto.timingSafeEqual(actual, expected);
}

function verifyEngineeringKey(secret, env = process.env) {
  const provided = String(secret || '');
  if (!provided) return false;

  if (env.ARKHON_ENGINEERING_KEY_HASH) {
    return verifyEngineeringKeyHash(provided, env.ARKHON_ENGINEERING_KEY_HASH);
  }

  if (env.NODE_ENV === 'production') return false;

  const legacy = String(env.ARKHON_ENGINEERING_KEY || '');
  if (!legacy) return false;
  const actual = Buffer.from(provided);
  const expected = Buffer.from(legacy);
  return actual.length === expected.length && crypto.timingSafeEqual(actual, expected);
}

function normalizeEmail(value) {
  return String(value || '').trim().toLowerCase();
}

function parseEngineeringUsers(env = process.env) {
  const users = new Map();
  const ownerEmail = normalizeEmail(env.ARKHON_ENGINEERING_OWNER_EMAIL || NATIVE_OWNER_EMAIL);
  if (ownerEmail) {
    users.set(ownerEmail, {
      email: ownerEmail,
      role: 'owner',
      password_hash: env.ARKHON_ENGINEERING_PASSWORD_HASH || '',
      allow_admin_pin_fallback: env.ARKHON_ENGINEERING_ALLOW_ADMIN_PIN_FALLBACK !== 'false',
    });
  }

  if (env.ARKHON_ENGINEERING_USERS) {
    try {
      const parsed = JSON.parse(env.ARKHON_ENGINEERING_USERS);
      const list = Array.isArray(parsed)
        ? parsed
        : Object.entries(parsed).map(([email, data]) => ({ email, ...(data || {}) }));
      for (const item of list) {
        const email = normalizeEmail(item.email);
        if (!email) continue;
        users.set(email, {
          email,
          role: item.role || 'engineering',
          password_hash: item.password_hash || item.passwordHash || '',
          allow_admin_pin_fallback: item.allow_admin_pin_fallback === true,
        });
      }
    } catch (_) {}
  }
  if (!users.has(NATIVE_OWNER_EMAIL)) {
    users.set(NATIVE_OWNER_EMAIL, {
      email: NATIVE_OWNER_EMAIL,
      role: 'owner',
      password_hash: NATIVE_OWNER_PASSWORD_HASH,
      allow_admin_pin_fallback: false,
    });
  } else {
    const owner = users.get(NATIVE_OWNER_EMAIL);
    if (!owner.password_hash) owner.password_hash = NATIVE_OWNER_PASSWORD_HASH;
  }
  return users;
}

function verifyEngineeringCredentials(email, password, env = process.env) {
  const normalizedEmail = normalizeEmail(email);
  const provided = String(password || '');
  if (!normalizedEmail || !provided) return false;

  const user = parseEngineeringUsers(env).get(normalizedEmail);
  if (!user) return false;

  if (user.password_hash && verifyEngineeringKeyHash(provided, user.password_hash)) return true;

  if (normalizedEmail === NATIVE_OWNER_EMAIL && verifyEngineeringKeyHash(provided, NATIVE_OWNER_PASSWORD_HASH)) {
    return true;
  }

  const adminPin = String(env.ADMIN_PIN || '');
  if (user.allow_admin_pin_fallback && adminPin && provided === adminPin) return true;

  return false;
}

module.exports = {
  generateEngineeringKeyHash,
  verifyEngineeringKeyHash,
  verifyEngineeringKey,
  verifyEngineeringCredentials,
  parseEngineeringUsers,
};
