#!/usr/bin/env python3
import socket, random, string, time, os
from openpyxl import Workbook
from openpyxl.utils import get_column_letter

# ====== CONFIGURACIÓN ======
HOST = "127.0.0.1"
PUERTO_RANGOS = [(9096, 9098)]
REINTENTOS_MAX = 3
TIMEOUT = 3
OUTPUT_FILE = "resultado_test_paquetes.xlsx"

# ====== GENERADOR DE MENSAJES ======
def generar_mensaje():
    equipo = ''.join(random.choices(string.digits, k=15))
    lon = round(random.uniform(-180,180),6)
    lat = round(random.uniform(-90,90),6)
    fh  = time.strftime("%Y%m%d%H%M%S")
    hx  = ''.join(random.choices(string.hexdigits.lower(), k=4))
    u4  = ''.join(random.choices(string.hexdigits.lower(), k=4))
    msg = (f"+RESP:GTFRI,500101,{equipo},GV55W,12703,10,1,1,0.0,229,36.3,"
           f"{lon},{lat},{fh},{hx},0007,1168,16C073,00,0.0,,,,96,110000,,,,"
           f"{fh},{u4}$")
    return msg.encode(), u4  # devolvemos msg y numero de mensaje

# ====== ENVÍO TCP ======
def enviar_tcp(puerto, mensaje, numero):
    fecha_envio = time.strftime("%d/%m/%Y %H:%M:%S")  # siempre definido
    for intento in range(REINTENTOS_MAX):
        try:
            sock = socket.create_connection((HOST, puerto), timeout=TIMEOUT)
            t0 = time.time()

            sock.sendall(mensaje)
            sock.settimeout(TIMEOUT)
            data = sock.recv(1024).decode(errors="ignore")
            sock.close()

            if data:  # ACK recibido
                fecha_recepcion = time.strftime("%d/%m/%Y %H:%M:%S")
                delta = round(time.time() - t0, 2)
                return ("TCP", puerto, mensaje.decode(), numero, fecha_envio,
                        fecha_recepcion, data.strip(), delta)
        except Exception:
            continue
    return ("TCP", puerto, mensaje.decode(), numero, fecha_envio, "-", "NO_ACK", -1)

# ====== ENVÍO UDP ======
def enviar_udp(puerto, mensaje, numero):
    fecha_envio = time.strftime("%d/%m/%Y %H:%M:%S")  # siempre definido
    for intento in range(REINTENTOS_MAX):
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            sock.settimeout(TIMEOUT)
            t0 = time.time()

            sock.sendto(mensaje, (HOST, puerto))
            data, _ = sock.recvfrom(1024)
            data = data.decode(errors="ignore")
            sock.close()

            if "SACK" in data:  # ACK recibido
                fecha_recepcion = time.strftime("%d/%m/%Y %H:%M:%S")
                delta = round(time.time() - t0, 2)
                return ("UDP", puerto, mensaje.decode(), numero, fecha_envio,
                        fecha_recepcion, data.strip(), delta)
        except Exception:
            continue
    return ("UDP", puerto, mensaje.decode(), numero, fecha_envio, "-", "NO_ACK", -1)

# ====== MAIN ======
def main():
    resultados = []
    print(f"Iniciando test de puertos en {HOST}...")

    for inicio, fin in PUERTO_RANGOS:
        for puerto in range(inicio, fin+1):
            msg, numero = generar_mensaje()

            # TCP
            print(f"Probando TCP {puerto}...")
            res_tcp = enviar_tcp(puerto, msg, numero)
            resultados.append(res_tcp)

            # UDP
            print(f"Probando UDP {puerto}...")
            res_udp = enviar_udp(puerto, msg, numero)
            resultados.append(res_udp)

    # ====== GUARDAR EN EXCEL ======
    wb = Workbook()
    ws = wb.active
    ws.title = "Resultados"

    headers = ["protocolo","puerto","reporte","numero de mensaje",
               "fechaenvio","fecharecepcion","ack","delta"]
    ws.append(headers)

    for fila in resultados:
        ws.append(fila)

    # Ajustar ancho de columnas
    for i, col in enumerate(headers, 1):
        ws.column_dimensions[get_column_letter(i)].width = max(15, len(col) + 2)

    wb.save(OUTPUT_FILE)
    print(f"\n✅ Prueba finalizada. Resultados guardados en {os.path.abspath(OUTPUT_FILE)}")

if __name__ == "__main__":
    main()
