'use strict';

const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

const PROGRAMDATA = process.env.ProgramData || 'C:\\ProgramData';
const AGENT_DATA_DIR = process.env.ARKHON_AGENT_DATA_DIR || path.join(PROGRAMDATA, 'ARKHON', 'Agent');
const CONFIG_PATH = process.env.CONFIG_PATH || path.join(AGENT_DATA_DIR, 'config');
const PROTOCOL_VERSION = 'arkhon-agent-v1';

function readJson(filePath, fallback = null) {
  try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); } catch (_) { return fallback; }
}

function decryptProtectedString(value) {
  const text = String(value || '').trim();
  if (!text) return '';
  if (process.platform !== 'win32') {
    if (text.startsWith('DEV:')) return Buffer.from(text.slice(4), 'base64').toString('utf8');
    const keyMaterial = process.env.ARKHON_SECRETS_KEY;
    if (text.startsWith('AESGCM:v1:') && keyMaterial) {
      const [saltB64, ivB64, tagB64, encryptedB64] = text.slice('AESGCM:v1:'.length).split(':');
      const key = crypto.scryptSync(keyMaterial, Buffer.from(saltB64, 'base64'), 32);
      const decipher = crypto.createDecipheriv('aes-256-gcm', key, Buffer.from(ivB64, 'base64'));
      decipher.setAuthTag(Buffer.from(tagB64, 'base64'));
      return Buffer.concat([decipher.update(Buffer.from(encryptedB64, 'base64')), decipher.final()]).toString('utf8');
    }
    return Buffer.from(text, 'base64').toString('utf8');
  }
  const script = `
    Add-Type -AssemblyName System.Security;
    $bytes = [Convert]::FromBase64String('${text.replace(/'/g, "''")}');
    $dec = [System.Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'LocalMachine');
    [System.Text.Encoding]::UTF8.GetString($dec)
  `.trim().replace(/\n\s+/g, ' ');
  return execSync(`powershell -NonInteractive -Command "${script}"`).toString().trim();
}

function loadEncryptedJson(filePath) {
  try {
    const raw = fs.readFileSync(filePath, 'utf8').trim();
    if (!raw) return {};
    return JSON.parse(decryptProtectedString(raw));
  } catch (_) {
    return {};
  }
}

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

function nonce() {
  return crypto.randomBytes(24).toString('base64url');
}

function signingPayload({ method, path: requestPath, timestamp, requestNonce, bodyHash }) {
  return [PROTOCOL_VERSION, String(method || 'POST').toUpperCase(), requestPath || '/', timestamp, requestNonce, bodyHash].join('\n');
}

function signRequest({ method, path: requestPath, timestamp, requestNonce, body, secret }) {
  const bodyHash = sha256(body || '');
  return crypto.createHmac('sha256', secret).update(signingPayload({ method, path: requestPath, timestamp, requestNonce, bodyHash })).digest('hex');
}

function readAgentCredentials() {
  const connector = readJson(path.join(CONFIG_PATH, 'connector.json'), {});
  const encrypted = loadEncryptedJson(path.join(CONFIG_PATH, 'connector-secret.enc'));
  const agentId = process.env.ARKHON_AGENT_ID || process.env.ARKHON_CONNECTOR_ID || connector.agent_id || connector.connector_id || '';
  const agentKeyId = process.env.ARKHON_AGENT_KEY_ID || process.env.ARKHON_CONNECTOR_KEY_ID || connector.agent_key_id || connector.connector_key_id || '';
  const agentKey = process.env.ARKHON_AGENT_KEY || process.env.ARKHON_CONNECTOR_SECRET || encrypted.ARKHON_AGENT_KEY || encrypted.ARKHON_CONNECTOR_SECRET || encrypted.agentKey || encrypted.connectorSecret || '';
  const tenantId = process.env.ARKHON_TENANT_ID || process.env.TENANT_ID || connector.tenant_id || '';
  const branchId = process.env.ARKHON_BRANCH_ID || process.env.BRANCH_ID || connector.branch_id || '';
  return {
    cloudUrl: (process.env.ARKHON_CLOUD_BASE_URL || process.env.ARKHON_CLOUD_URL || connector.cloud_url || '').replace(/\/+$/, ''),
    agentId,
    agentKeyId,
    agentKey,
    tenantId,
    branchId,
    hwid: process.env.ARKHON_HARDWARE_ID || connector.hardware_id || connector.hardwareId || connector.hwid || process.env.ARKHON_DEVICE_ID || connector.device_id || '',
    deviceId: process.env.ARKHON_DEVICE_ID || connector.device_id || connector.deviceId || '',
    installId: connector.install_id || process.env.ARKHON_INSTALL_ID || '',
    canSign: !!(agentId && agentKeyId && agentKey),
  };
}

function authHeaders(credentials, { method = 'POST', path: requestPath = '/', body = '' } = {}) {
  const timestamp = Date.now().toString();
  const requestNonce = nonce();
  const bodyHash = sha256(body || '');
  return {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(body || ''),
    'User-Agent': 'ARKHON-Updater-Service',
    'x-agent-id': credentials.agentId,
    'x-agent-key-id': credentials.agentKeyId,
    'x-agent-timestamp': timestamp,
    'x-agent-nonce': requestNonce,
    'x-agent-body-sha256': bodyHash,
    'x-agent-signature': signRequest({ method, path: requestPath, timestamp, requestNonce, body, secret: credentials.agentKey }),
    'x-arkhon-protocol': PROTOCOL_VERSION,
  };
}

function maskedCredentialSummary(credentials = {}) {
  const mask = (value) => {
    const text = String(value || '');
    if (!text) return null;
    if (text.length <= 8) return '****';
    return `${text.slice(0, 4)}****${text.slice(-4)}`;
  };
  return {
    cloudUrl: credentials.cloudUrl || null,
    agentId: mask(credentials.agentId),
    agentKeyId: mask(credentials.agentKeyId),
    tenantId: mask(credentials.tenantId),
    branchId: mask(credentials.branchId),
    hwid: mask(credentials.hwid),
    hasAgentKey: !!credentials.agentKey,
    canSign: !!credentials.canSign,
  };
}

module.exports = {
  PROTOCOL_VERSION,
  readAgentCredentials,
  authHeaders,
  signRequest,
  maskedCredentialSummary,
};
