package lifecycle

import (
	"context"
	"fmt"
	"strings"
	"time"

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

// LocalOwnerIdentityReadyStep records a deterministic owner identity for
// CP-local personas that do not need AWS caller discovery.
type LocalOwnerIdentityReadyStep struct {
	StateDir string
	Session  *config.SessionConfig
}

func (s *LocalOwnerIdentityReadyStep) Name() cluster.StepName { return cluster.StepOwnerIdentityReady }

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

func (s *LocalOwnerIdentityReadyStep) RunWithState(_ context.Context, state *cluster.State) error {
	if strings.TrimSpace(s.StateDir) == "" {
		return fmt.Errorf("owner_identity_ready: state dir is required")
	}
	if state == nil {
		return fmt.Errorf("owner_identity_ready: lifecycle state is required")
	}
	if s.Session == nil {
		return fmt.Errorf("owner_identity_ready: session config is required")
	}
	owner, sessionTags, err := cpaws.ResolveLocalSessionIdentity(s.Session.Name)
	if err != nil {
		return fmt.Errorf("owner_identity_ready: resolve session tags: %w", err)
	}
	state.Owner = owner
	if err := cpaws.SaveSessionState(s.StateDir, &cpaws.SessionState{
		SessionID:   s.Session.Name,
		Owner:       owner,
		Region:      "local",
		Account:     "local",
		SessionTags: sessionTags,
		CreatedAt:   time.Now(),
	}); err != nil {
		return fmt.Errorf("owner_identity_ready: save state: %w", err)
	}
	return nil
}

// LocalSubstrateApplyStep writes the minimal substrate artifacts expected by
// context materialization without creating cloud resources.
type LocalSubstrateApplyStep struct {
	StateDir string
}

func (s *LocalSubstrateApplyStep) Name() cluster.StepName { return cluster.StepSubstrateApply }

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

func (s *LocalSubstrateApplyStep) RunWithState(_ context.Context, _ *cluster.State) error {
	if strings.TrimSpace(s.StateDir) == "" {
		return fmt.Errorf("substrate_apply: state dir is required")
	}
	paths := cpterraform.WorkspacePaths(s.StateDir)
	if err := cpterraform.WriteOutputs(paths.OutputsPath, map[string]cpterraform.OutputValue{}); err != nil {
		return fmt.Errorf("substrate_apply: %w", err)
	}
	if err := cpterraform.WriteContract(paths.ContractPath, &cpterraform.OutputContract{}); err != nil {
		return fmt.Errorf("substrate_apply: %w", err)
	}
	return nil
}

// LocalMetadbSeedStep records that CP-local personas do not use the Premium
// Terraform-backed metadb seed contract.
type LocalMetadbSeedStep struct {
	StateDir string
}

func (s *LocalMetadbSeedStep) Name() cluster.StepName { return cluster.StepMetadbSeed }

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

func (s *LocalMetadbSeedStep) RunWithState(_ context.Context, _ *cluster.State) error {
	if strings.TrimSpace(s.StateDir) == "" {
		return fmt.Errorf("metadb_seed: state dir is required")
	}
	if err := writeMetadbSeedReport(cluster.MetadbSeedReportPath(s.StateDir), &MetadbSeedReport{
		ServiceDSNs: map[string]string{},
	}); err != nil {
		return fmt.Errorf("metadb_seed: persist report: %w", err)
	}
	return nil
}
