#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <iomanip>
#include "Medidor.h"

int main(int argc, char *argv[]) {
    if (argc != 3) {
        std::cerr << "Uso: " << argv[0] << " <dirección IP> <puerto>" << std::endl;
        return 1;
    }

    const char* ip_address = argv[1];
    int port = atoi(argv[2]);

    if (port <= 0 || port > 65535) {
        std::cerr << "Error: El puerto debe estar entre 1 y 65535." << std::endl;
        return 1;
    }

    int sock = 0;
    struct sockaddr_in serv_addr;
    
    // Crear socket
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        std::cerr << "Error de creación de socket" << std::endl;
        return -1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);

    // Convertir dirección IP de texto a binario
    if (inet_pton(AF_INET, ip_address, &serv_addr.sin_addr) <= 0) {
        std::cerr << "Dirección inválida / Dirección no soportada" << std::endl;
        return -1;
    }

    // Conectar al servidor
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        std::cerr << "Conexión fallida" << std::endl;
        return -1;
    }

    std::cout << "Conectado al medidor Circutor en " << ip_address << ":" << port << std::endl;

    Medidor medidor;
    medidor.setSocket(sock);

    // Iniciar comunicación con el medidor
    if (medidor.autenticarMedidor() == COMUNICACION_EXITOSA) {
        // Leer todos los grupos de valores instantáneos
        int grupos[] = {192, 193, 194};
        for (int grupo : grupos) {
            if (medidor.leerInstantaneos(grupo) != COMUNICACION_EXITOSA) {
                std::cerr << "Error al leer valores instantáneos del grupo " << grupo << std::endl;
            }
        }

        // Imprimir valores crudos de los registros
        std::cout << "\nValores crudos de los registros:" << std::endl;
        for (int i = 0; i < REGISTROS_MAXIMOS; i++) {
            std::cout << "Registro " << i << ": " << std::scientific << std::setprecision(6) 
                      << medidor.getRegistros(i) << std::endl;
        }

        // Imprimir valores interpretados
        std::cout << "Valores instantáneos interpretados:" << std::endl;
        std::cout << std::fixed << std::setprecision(3);
        std::cout << "Energías:" << std::endl;
        std::cout << "  Activa importada: " << medidor.getRegistros(0) << " kWh" << std::endl;
        std::cout << "  Activa exportada: " << medidor.getRegistros(1) << " kWh" << std::endl;
        std::cout << "  Reactiva Q1: " << medidor.getRegistros(2) << " kVArh" << std::endl;
        std::cout << "  Reactiva Q2: " << medidor.getRegistros(3) << " kVArh" << std::endl;
        std::cout << "  Reactiva Q3: " << medidor.getRegistros(4) << " kVArh" << std::endl;
        std::cout << "  Reactiva Q4: " << medidor.getRegistros(5) << " kVArh" << std::endl;

        std::cout << "Potencias:" << std::endl;
        std::cout << "  Activa total: " << medidor.getRegistros(6) << " kW" << std::endl;
        std::cout << "  Reactiva total: " << medidor.getRegistros(7) << " kVAr" << std::endl;
        std::cout << "  Factor de potencia total: " << medidor.getRegistros(8) << std::endl;
        for (int i = 0; i < 3; i++) {
            std::cout << "  Fase " << (i+1) << ":" << std::endl;
            std::cout << "    Potencia activa: " << medidor.getRegistros(9 + i*3) << " kW" << std::endl;
            std::cout << "    Potencia reactiva: " << medidor.getRegistros(10 + i*3) << " kVAr" << std::endl;
            std::cout << "    Factor de potencia: " << medidor.getRegistros(11 + i*3) << std::endl;
        }

        std::cout << "Tensiones y Corrientes:" << std::endl;
        for (int i = 0; i < 3; i++) {
            std::cout << "  Fase " << (i+1) << ":" << std::endl;
            std::cout << "    Tensión: " << medidor.getRegistros(18 + i) * 0.1 << " V" << std::endl;
            std::cout << "    Corriente: " << medidor.getRegistros(21 + i) * 0.01 << " A" << std::endl;
        }
    } else {
        std::cerr << "Error en la autenticación con el medidor" << std::endl;
        close(sock);
        return -1;
    }

    close(sock);
    return 0;
}