package harvester

import (
	"context"
	"fmt"

	"vanderlande.com/ittp/appstack/rig-operator/api/v1alpha1"
	template "vanderlande.com/ittp/appstack/rig-operator/internal/templates/harvester"
)

// harvesterNodePool matches the exact JSON structure required by the Helm Chart
type harvesterNodePool struct {
	Name         string `json:"name"`
	DisplayName  string `json:"displayName"`
	Quantity     int    `json:"quantity"`
	Etcd         bool   `json:"etcd"`
	ControlPlane bool   `json:"controlplane"`
	Worker       bool   `json:"worker"`
	Paused       bool   `json:"paused"`

	// Harvester Specific Fields
	CpuCount    int    `json:"cpuCount"`
	MemorySize  int    `json:"memorySize"` // GB
	DiskSize    int    `json:"diskSize"`   // GB
	ImageName   string `json:"imageName"`
	NetworkName string `json:"networkName"`
	SshUser     string `json:"sshUser"`
	VmNamespace string `json:"vmNamespace"`
	UserData    string `json:"userData"`
}

type Strategy struct {
	blueprint  *v1alpha1.HarvesterBlueprint
	userData   string
	rancherURL string
	defaults   template.Defaults
}

// NewStrategy initializes the strategy with defaults and optional overrides
func NewStrategy(hbp *v1alpha1.HarvesterBlueprint, infraUserData string, infraRancherURL string, defaults template.Defaults) *Strategy { // 1. Determine UserData priority: Infra (IBP) > Template Default
	finalUserData := infraUserData
	if finalUserData == "" {
		finalUserData = defaults.UserData
	}

	return &Strategy{
		blueprint:  hbp,
		userData:   finalUserData,
		rancherURL: infraRancherURL,
		defaults:   defaults,
	}
}

// GenerateNodePools implements provider.Strategy
func (s *Strategy) GenerateNodePools(ctx context.Context, cbp *v1alpha1.ClusterBlueprint) (interface{}, error) {
	var pools []interface{}

	// Helper to map generic req -> harvester specific struct
	mapPool := func(name string, qty, cpu, memGB, diskGB int, isEtcd, isCp, isWk bool) harvesterNodePool {
		return harvesterNodePool{
			Name:         name,
			DisplayName:  name,
			Quantity:     qty,
			Etcd:         isEtcd,
			ControlPlane: isCp,
			Worker:       isWk,
			Paused:       false,

			// Mapping: Generic (GB) -> Harvester (GB) [No conversion needed]
			CpuCount:   cpu,
			MemorySize: memGB,
			DiskSize:   diskGB,

			// Harvester Specifics from HBP
			ImageName:   s.blueprint.Spec.ImageName,
			NetworkName: s.blueprint.Spec.NetworkName,
			SshUser:     s.blueprint.Spec.SshUser,
			VmNamespace: s.blueprint.Spec.VmNamespace,
			UserData:    s.userData,
		}
	}

	// 1. Control Plane Pool
	cpQty := 1
	if cbp.Spec.ControlPlaneHA {
		cpQty = 3
	}

	// Use Defaults from YAML for CP sizing
	pools = append(pools, mapPool(
		"cp-pool",
		cpQty,
		s.defaults.CP_CPU,
		s.defaults.CP_Mem,
		s.defaults.CP_Disk,
		true, true, false,
	))

	// 2. Worker Pools
	for _, wp := range cbp.Spec.WorkerPools {
		pools = append(pools, mapPool(
			wp.Name,
			wp.Quantity,
			wp.CpuCores,
			wp.MemoryGB,
			wp.DiskGB,
			false, false, true,
		))
	}

	return pools, nil
}

// GetGlobalOverrides implements provider.Strategy
func (s *Strategy) GetGlobalOverrides(ctx context.Context, cbp *v1alpha1.ClusterBlueprint, credentialSecretName string) (map[string]interface{}, error) {
	// secret://<namespace>:<secretName>
	secretURI := fmt.Sprintf("secret://%s:%s", cbp.Namespace, credentialSecretName)

	overrides := map[string]interface{}{
		"cloud_provider_name":   "harvester",
		"cloud_provider_config": secretURI,
		//  Inject Rancher URL
		"rancher": map[string]interface{}{
			"cattle": map[string]interface{}{
				"url": s.rancherURL,
			},
		},

		"chartValues": map[string]interface{}{
			"harvester-cloud-provider": map[string]interface{}{
				"global": map[string]interface{}{
					"cattle": map[string]interface{}{
						"clusterName": cbp.Name,
					},
				},
			},
		},
	}
	return overrides, nil
}
