const crypto = require('crypto');

function signEdDsaJwt(payload, privateKey) {
  const headerB64 = Buffer.from(JSON.stringify({ alg: 'EdDSA', typ: 'JWT' })).toString('base64url');
  const payloadB64 = Buffer.from(JSON.stringify(payload)).toString('base64url');
  const data = Buffer.from(`${headerB64}.${payloadB64}`, 'utf8');
  const signatureB64 = crypto.sign(null, data, privateKey).toString('base64url');

  return `${headerB64}.${payloadB64}.${signatureB64}`;
}

function verifyEdDsaJwt(token, publicKey) {
  const segments = token.split('.');

  if (segments.length !== 3) {
    throw new Error('Invalid JWT format');
  }

  const [headerB64, payloadB64, signatureB64] = segments;
  const header = JSON.parse(Buffer.from(headerB64, 'base64url').toString('utf8'));

  if (header.alg !== 'EdDSA') {
    throw new Error('Invalid JWT algorithm');
  }

  const data = Buffer.from(`${headerB64}.${payloadB64}`, 'utf8');
  const signature = Buffer.from(signatureB64, 'base64url');

  if (!crypto.verify(null, data, publicKey, signature)) {
    throw new Error('Invalid JWT signature');
  }

  return {
    isValid: true,
    payload: JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf8'))
  };
}

const {
  privateKey: fallbackPrivateKey,
  publicKey: fallbackPublicKey
} = crypto.generateKeyPairSync('ed25519', {
  privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
  publicKeyEncoding: { type: 'spki', format: 'pem' }
});

class LicenseTokenGenerator {
  static getKeyPair() {
    const privateKeyPem = process.env.SUPERADMIN_PRIVATE_KEY;
    const publicKeyPem = process.env.SUPERADMIN_PUBLIC_KEY;

    if (privateKeyPem && publicKeyPem) {
      return {
        privateKey: privateKeyPem.replace(/\\n/g, '\n'),
        publicKey: publicKeyPem.replace(/\\n/g, '\n')
      };
    }

    return {
      privateKey: fallbackPrivateKey,
      publicKey: fallbackPublicKey
    };
  }

  static generateToken(payload) {
    const { privateKey } = this.getKeyPair();
    const nowSeconds = Math.floor(Date.now() / 1000);
    const nbf = payload.nbf ?? Math.floor(new Date(payload.start_date).getTime() / 1000);
    const exp = payload.exp ?? Math.floor(new Date(payload.end_date).getTime() / 1000);

    const licensePayload = {
      iss: 'super_admin_licensing_engine',
      sub: payload.tenant_id,
      tenant_code: payload.tenant_code,
      term: payload.term_name,
      academic_year: payload.academic_year,
      max_students: payload.max_students ?? 1000,
      max_staff: payload.max_staff ?? 200,
      nbf,
      exp,
      status: 'active',
      iat: nowSeconds
    };

    const token = signEdDsaJwt(licensePayload, privateKey);
    const licenseKey = `LIC-${(payload.term_name || 'TERM').replace(/\s+/g, '')}-${payload.academic_year}-${token.slice(-16)}`.toUpperCase();

    return {
      token,
      license_key: licenseKey,
      payload: licensePayload
    };
  }

  static verifyToken(token) {
    const { publicKey } = this.getKeyPair();

    try {
      return verifyEdDsaJwt(token, publicKey);
    } catch (err) {
      return { isValid: false, error: err.message };
    }
  }
}

module.exports = LicenseTokenGenerator;
