package lifecycle

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	cpaws "github.com/tidbcloud/controlplane9/internal/aws"
	"github.com/tidbcloud/controlplane9/internal/cluster"
	"github.com/tidbcloud/controlplane9/internal/config"
	cp9errors "github.com/tidbcloud/controlplane9/internal/errors"
	"github.com/tidbcloud/controlplane9/internal/host"
	cpterraform "github.com/tidbcloud/controlplane9/internal/terraform"
)

// RemoteEKSHostReadyStep makes Terraform's remote EKS output the selected
// kubectl target for downstream render/apply/readiness steps.
type RemoteEKSHostReadyStep struct {
	StateDir string
}

func (s *RemoteEKSHostReadyStep) Name() cluster.StepName { return cluster.StepHostReady }

func (s *RemoteEKSHostReadyStep) Run(_ context.Context) error {
	return fmt.Errorf("host_ready requires lifecycle state")
}

func (s *RemoteEKSHostReadyStep) RunWithState(_ context.Context, state *cluster.State) error {
	if strings.TrimSpace(s.StateDir) == "" {
		return cp9errors.New(cp9errors.CategoryConfig, "host_ready: state dir is required")
	}
	if state == nil {
		return cp9errors.New(cp9errors.CategoryConfig, "host_ready: lifecycle state is required")
	}
	remote, err := loadRemoteEKSArtifact(s.StateDir)
	if err != nil {
		return fmt.Errorf("host_ready: %w", err)
	}
	contextName := strings.TrimSpace(remote.KubeconfigContext)
	if contextName == "" {
		contextName = strings.TrimSpace(remote.ClusterName)
	}
	if contextName == "" {
		return cp9errors.New(cp9errors.CategoryConfig, "remote EKS kubeconfig context is required")
	}
	sessionName := firstNonEmpty(state.SessionName, state.ClusterName)
	if sessionName == "" {
		return cp9errors.New(cp9errors.CategoryConfig, "host_ready: session name is required")
	}
	selected := &host.Session{
		Mode:           config.HostModeRemoteEKS,
		StateDir:       s.StateDir,
		ClusterName:    strings.TrimSpace(remote.ClusterName),
		Namespace:      sessionName,
		KubeconfigPath: filepath.Join(s.StateDir, "remote-eks", "kubeconfig.yaml"),
		Context:        contextName,
		Region:         strings.TrimSpace(remote.Region),
	}
	if awsState, err := cpaws.LoadSessionState(s.StateDir); err == nil {
		selected.Profile = strings.TrimSpace(awsState.Profile)
		if selected.Region == "" {
			selected.Region = strings.TrimSpace(awsState.Region)
		}
	} else if !os.IsNotExist(err) {
		return fmt.Errorf("host_ready: load AWS session state: %w", err)
	}
	if selected.ClusterName == "" {
		return cp9errors.New(cp9errors.CategoryConfig, "remote EKS cluster_name is required")
	}
	if err := host.Save(s.StateDir, selected); err != nil {
		return fmt.Errorf("persist remote EKS selected host: %w", err)
	}
	state.HostMode = config.HostModeRemoteEKS
	return nil
}

func loadRemoteEKSArtifact(stateDir string) (*cpterraform.RemoteEKSOutput, error) {
	path := filepath.Join(stateDir, "remote-eks", "remote-eks.json")
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, cp9errors.Newf(cp9errors.CategoryResource, "load remote EKS artifact: %v", err)
	}
	var remote cpterraform.RemoteEKSOutput
	if err := json.Unmarshal(data, &remote); err != nil {
		return nil, cp9errors.Newf(cp9errors.CategoryConfig, "parse remote EKS artifact: %v", err)
	}
	if !remote.Enabled {
		return nil, cp9errors.New(cp9errors.CategoryConfig, "remote EKS artifact is not enabled")
	}
	return &remote, nil
}

func firstNonEmpty(values ...string) string {
	for _, value := range values {
		value = strings.TrimSpace(value)
		if value != "" {
			return value
		}
	}
	return ""
}
