package zones

import (
	"errors"

	"github.com/rs/xid"

	"github.com/netbirdio/netbird/management/internals/modules/zones/records"
	"github.com/netbirdio/netbird/management/server/util"
	"github.com/netbirdio/netbird/shared/management/http/api"
)

type Zone struct {
	ID                 string `gorm:"primaryKey"`
	AccountID          string `gorm:"index"`
	Name               string
	Domain             string
	Enabled            bool
	EnableSearchDomain bool
	DistributionGroups []string          `gorm:"serializer:json"`
	Records            []*records.Record `gorm:"foreignKey:ZoneID;references:ID"`
}

func NewZone(accountID, name, domain string, enabled, enableSearchDomain bool, distributionGroups []string) *Zone {
	return &Zone{
		ID:                 xid.New().String(),
		AccountID:          accountID,
		Name:               name,
		Domain:             domain,
		Enabled:            enabled,
		EnableSearchDomain: enableSearchDomain,
		DistributionGroups: distributionGroups,
	}
}

func (z *Zone) ToAPIResponse() *api.Zone {
	apiRecords := make([]api.DNSRecord, 0, len(z.Records))
	for _, record := range z.Records {
		if apiRecord := record.ToAPIResponse(); apiRecord != nil {
			apiRecords = append(apiRecords, *apiRecord)
		}
	}

	return &api.Zone{
		DistributionGroups: z.DistributionGroups,
		Domain:             z.Domain,
		EnableSearchDomain: z.EnableSearchDomain,
		Enabled:            z.Enabled,
		Id:                 z.ID,
		Name:               z.Name,
		Records:            apiRecords,
	}
}

func (z *Zone) FromAPIRequest(req *api.ZoneRequest) {
	z.Name = req.Name
	z.Domain = req.Domain
	z.EnableSearchDomain = req.EnableSearchDomain
	z.DistributionGroups = req.DistributionGroups

	enabled := true
	if req.Enabled != nil {
		enabled = *req.Enabled
	}
	z.Enabled = enabled
}

func (z *Zone) Validate() error {
	if z.Name == "" {
		return errors.New("zone name is required")
	}
	if len(z.Name) > 255 {
		return errors.New("zone name exceeds maximum length of 255 characters")
	}

	if !util.IsValidDomain(z.Domain) {
		return errors.New("invalid zone domain format")
	}

	if len(z.DistributionGroups) == 0 {
		return errors.New("at least one distribution group is required")
	}

	return nil
}

func (z *Zone) EventMeta() map[string]any {
	return map[string]any{"name": z.Name, "domain": z.Domain}
}
