package entity

import (
	"strings"
	"time"
)

const (
	DefaultWorkspaceID   = "00000000-0000-0000-0000-000000000010"
	DefaultWorkspaceName = "default"
)

type WorkspaceStatus string

const (
	WorkspaceActive    WorkspaceStatus = "active"
	WorkspaceSuspended WorkspaceStatus = "suspended"
)

type Workspace struct {
	ID               string
	Name             string
	Status           WorkspaceStatus
	K8sNamespace     string
	K8sSAName        string
	DefaultClusterID string
	QuotaCPU         string
	QuotaMemory      string
	QuotaGPU         string
	QuotaGPUMem      string
	CreatedBy        string
	CreatedAt        time.Time
	UpdatedAt        time.Time
}

func NewWorkspace(name, createdBy string) *Workspace {
	now := time.Now()
	return &Workspace{
		Name:         name,
		Status:       WorkspaceActive,
		K8sNamespace: NamespaceForWorkspace(name),
		K8sSAName:    ServiceAccountForWorkspace(name),
		CreatedBy:    createdBy,
		CreatedAt:    now,
		UpdatedAt:    now,
	}
}

func NamespaceForWorkspace(name string) string {
	if name == "" {
		name = DefaultWorkspaceName
	}
	return prefixedDNSLabel("ocdp-ws-", name)
}

func NamespaceForUser(username string) string {
	if username == "" {
		username = "user"
	}
	return prefixedDNSLabel("ocdp-u-", username)
}

func ServiceAccountForWorkspace(name string) string {
	if name == "" {
		name = DefaultWorkspaceName
	}
	return prefixedDNSLabel("ocdp-ws-", name)
}

func ServiceAccountForNamespace(namespace string) string {
	if namespace == "" {
		namespace = DefaultWorkspaceName
	}
	return prefixedDNSLabel("ocdp-sa-", namespace)
}

func prefixedDNSLabel(prefix, value string) string {
	label := normalizeDNSLabel(value)
	maxLabelLen := 63 - len(prefix)
	if maxLabelLen < 1 {
		maxLabelLen = 1
	}
	if len(label) > maxLabelLen {
		label = strings.Trim(label[:maxLabelLen], "-")
	}
	if label == "" {
		label = DefaultWorkspaceName
		if len(label) > maxLabelLen {
			label = label[:maxLabelLen]
		}
	}
	return prefix + label
}

func normalizeDNSLabel(value string) string {
	out := make([]rune, 0, len(value))
	lastDash := false
	for _, r := range value {
		valid := (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9')
		if r >= 'A' && r <= 'Z' {
			r = r + ('a' - 'A')
			valid = true
		}
		if valid {
			out = append(out, r)
			lastDash = false
			continue
		}
		if !lastDash && len(out) > 0 {
			out = append(out, '-')
			lastDash = true
		}
	}
	for len(out) > 0 && out[len(out)-1] == '-' {
		out = out[:len(out)-1]
	}
	if len(out) == 0 {
		return DefaultWorkspaceName
	}
	return string(out)
}

type WorkspaceClusterBinding struct {
	ID             string
	WorkspaceID    string
	ClusterID      string
	Namespace      string
	ServiceAccount string
	QuotaCPU       string
	QuotaMemory    string
	QuotaGPU       string
	QuotaGPUMem    string
	Status         string
	CreatedAt      time.Time
	UpdatedAt      time.Time
}

type AuditLog struct {
	ID           string
	WorkspaceID  string
	UserID       string
	Action       string
	ResourceType string
	ResourceID   string
	ResourceName string
	Details      map[string]interface{}
	IPAddress    string
	UserAgent    string
	CreatedAt    time.Time
}
