package extnet

import (
	"context"
	"encoding/json"
	"net/http"
	"strconv"

	"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)

type Route struct {
	// Destination network
	Destination string `url:"destination" json:"destination" validate:"required"`

	//Destination network mask in 255.255.255.255 format
	Netmask string `url:"netmask" json:"netmask" validate:"required"`

	//Next hop host, IP address from ViNS ID free IP pool
	Gateway string `url:"gateway" json:"gateway" validate:"required"`
}

// CreateRequest struct to create external network
type CreateRequest struct {
	// External network name
	// Required: true
	Name string `url:"name" json:"name" validate:"required"`

	// Grid (platform) ID
	// Required: true
	GID uint64 `url:"gid" json:"gid" validate:"required"`

	// IP network CIDR
	// For example 192.168.0.0/24
	// Required: true
	IPCIDR string `url:"ipcidr" json:"ipcidr" validate:"required"`

	// VLAN ID
	// Required: true
	VLANID uint64 `url:"vlanId" json:"vlanId" validate:"required"`

	// External network gateway IP address
	// Required: false
	Gateway string `url:"gateway,omitempty" json:"gateway,omitempty"`

	// List of DNS addresses
	// Required: false
	DNS []string `url:"dns,omitempty" json:"dns,omitempty"`

	// Maximum transmission unit
	// Default: 1500
	// Required: false
	MTU uint `url:"mtu,omitempty" json:"mtu,omitempty"`

	// List of NTP addresses
	// Required: false
	NTP []string `url:"ntp,omitempty" json:"ntp,omitempty"`

	// IPs to check network availability
	// Required: false
	CheckIPs []string `url:"checkIps,omitempty" json:"checkIps,omitempty"`

	// If true - platform DHCP server will not be created
	// Required: false
	Virtual bool `url:"virtual,omitempty" json:"virtual,omitempty"`

	// Optional description
	// Required: false
	Description string `url:"desc,omitempty" json:"desc,omitempty"`

	// Start of IP range to be explicitly included
	// Required: false
	StartIP string `url:"startIP,omitempty" json:"startIP,omitempty"`

	// End of IP range to be explicitly included
	// Required: false
	EndIP string `url:"endIP,omitempty" json:"endIP,omitempty"`

	// IP to create primary vnfdev with
	// Required: false
	PriVNFDevIP string `url:"priVnfdevIP,omitempty" json:"priVnfdevIP,omitempty"`

	// IP to create secondary vnfdev with
	// Required: false
	SecVNFDevIP string `url:"secVnfdevIP,omitempty" json:"secVnfdevIP,omitempty"`

	// Number of pre created reservations
	// Required: false
	PreReservationsNum uint64 `url:"preReservationsNum,omitempty" json:"preReservationsNum,omitempty"`

	// OpenvSwith bridge name for ExtNet connection
	// Required: false
	OVSBridge string `url:"ovsBridge,omitempty" json:"ovsBridge,omitempty"`

	// List of static routes, each item must have destination, netmask, and gateway fields
	// Required: false
	Routes []Route `url:"-" json:"routes,omitempty" validate:"omitempty,dive"`

	// Zone ID
	// Required: false
	ZoneID uint64 `url:"zoneId,omitempty" json:"zoneId,omitempty"`

	// High Availability mode is enabled, default False
	// Required: false
	// Default: false
	HAMode bool `url:"highlyAvailable,omitempty" json:"highlyAvailable,omitempty"`

	// Enable security groups for external network
	// Required: false
	// Default: false
	EnableSecGroups interface{} `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty" validate:"omitempty,isBool"`
}

type wrapperCreateRequest struct {
	CreateRequest
	Routes []string `url:"routes,omitempty"`
}

// Create creates new external network into platform
func (e ExtNet) Create(ctx context.Context, req CreateRequest) (uint64, error) {
	err := validators.ValidateRequest(req)
	if err != nil {
		return 0, validators.ValidationErrors(validators.GetErrors(err))
	}

	var routes []string

	if len(req.Routes) != 0 {
		routes = make([]string, 0, len(req.Routes))

		for r := range req.Routes {
			b, err := json.Marshal(req.Routes[r])
			if err != nil {
				return 0, err
			}

			routes = append(routes, string(b))
		}
	} else {
		routes = []string{}
	}

	reqWrapped := wrapperCreateRequest{
		CreateRequest: req,
		Routes:        routes,
	}

	url := "/cloudbroker/extnet/create"

	res, err := e.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped)
	if err != nil {
		return 0, err
	}

	result, err := strconv.ParseUint(string(res), 10, 64)
	if err != nil {
		return 0, err
	}

	return result, nil
}
