package cmds

import (
	"agent/commons/debug"
	"agent/defines/dcmds"
	"agent/defines/derrs"
	"agent/defines/devent/daction"
	"agent/defines/devent/dcategory"
	"agent/modules/ports/api"
	"agent/modules/ports/internal"
	"context"

	"github.com/google/uuid"
)

type PortCloseCmd struct {
	dcmds.ServiceToAgentCmd
}

func (c *PortCloseCmd) Category() []Category {
	return []Category{dcategory.Agent, dcategory.Tunnel, dcategory.Port}
}

func (c *PortCloseCmd) Action() Action {
	return daction.Close
}

func (c *PortCloseCmd) Execute(ctx context.Context, eventIn IEvent) (eventOut IEvent, err error) {
	debug.Log("PortCloseCmd")

	meta := eventIn.Meta()

	var portUuids []uuid.UUID
	if raw, ok := meta["port_uuids"].([]any); !ok || len(raw) == 0 {
		return nil, derrs.NewIncorrectParamsError()
	} else {
		for _, val := range raw {
			rawUuid, ok := val.(string)
			if !ok {
				continue
			}
			portUuid, err := uuid.Parse(rawUuid)
			if err != nil {
				debug.Logf("Failed to parse port UUID %s: %v\n", rawUuid, err)
				continue
			}
			portUuids = append(portUuids, portUuid)
		}
	}

	for _, portUuid := range portUuids {
		if port, ok := internal.Ports.Load(portUuid); ok {
			if tunPort, ok := port.(api.PortItem); ok {
				if err = tunPort.Close(); err != nil {
					debug.Logf("Failed to close port %s: %v\n", portUuid, err)
				}
			} else {
				debug.Logf("Port %s does not implement PortItem interface\n", portUuid)
			}
		}
	}

	return nil, nil
}
