// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package kubernetes

import (
	"context"
	"errors"
	"fmt"
	"sort"

	"github.com/hashicorp/terraform/internal/backend"
	"github.com/hashicorp/terraform/internal/states"
	"github.com/hashicorp/terraform/internal/states/remote"
	"github.com/hashicorp/terraform/internal/states/statemgr"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Workspaces returns a list of names for the workspaces found in k8s. The default
// workspace is always returned as the first element in the slice.
func (b *Backend) Workspaces() ([]string, error) {
	secretClient, err := b.KubernetesSecretClient()
	if err != nil {
		return nil, err
	}

	secrets, err := secretClient.List(
		context.Background(),
		metav1.ListOptions{
			LabelSelector: tfstateKey + "=true",
		},
	)
	if err != nil {
		return nil, err
	}

	// Use a map so there aren't duplicate workspaces
	m := make(map[string]struct{})
	for _, secret := range secrets.Items {
		sl := secret.GetLabels()
		ws, ok := sl[tfstateWorkspaceKey]
		if !ok {
			continue
		}

		key, ok := sl[tfstateSecretSuffixKey]
		if !ok {
			continue
		}

		// Make sure it isn't default and the key matches
		if ws != backend.DefaultStateName && key == b.nameSuffix {
			m[ws] = struct{}{}
		}
	}

	states := []string{backend.DefaultStateName}
	for k := range m {
		states = append(states, k)
	}

	sort.Strings(states[1:])
	return states, nil
}

func (b *Backend) DeleteWorkspace(name string, _ bool) error {
	if name == backend.DefaultStateName || name == "" {
		return fmt.Errorf("can't delete default state")
	}

	client, err := b.remoteClient(name)
	if err != nil {
		return err
	}

	return client.Delete()
}

func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
	c, err := b.remoteClient(name)
	if err != nil {
		return nil, err
	}

	stateMgr := &remote.State{Client: c}

	// Grab the value
	if err := stateMgr.RefreshState(); err != nil {
		return nil, err
	}

	// If we have no state, we have to create an empty state
	if v := stateMgr.State(); v == nil {

		lockInfo := statemgr.NewLockInfo()
		lockInfo.Operation = "init"
		lockID, err := stateMgr.Lock(lockInfo)
		if err != nil {
			return nil, err
		}

		secretName, err := c.createSecretName()
		if err != nil {
			return nil, err
		}

		// Local helper function so we can call it multiple places
		unlock := func(baseErr error) error {
			if err := stateMgr.Unlock(lockID); err != nil {
				const unlockErrMsg = `%v
				Additionally, unlocking the state in Kubernetes failed:

				Error message: %q
				Lock ID (gen): %v
				Secret Name: %v

				You may have to force-unlock this state in order to use it again.
				The Kubernetes backend acquires a lock during initialization to ensure
				the initial state file is created.`
				return fmt.Errorf(unlockErrMsg, baseErr, err.Error(), lockID, secretName)
			}

			return baseErr
		}

		if err := stateMgr.WriteState(states.NewState()); err != nil {
			return nil, unlock(err)
		}
		if err := stateMgr.PersistState(nil); err != nil {
			return nil, unlock(err)
		}

		// Unlock, the state should now be initialized
		if err := unlock(nil); err != nil {
			return nil, err
		}

	}

	return stateMgr, nil
}

// get a remote client configured for this state
func (b *Backend) remoteClient(name string) (*RemoteClient, error) {
	if name == "" {
		return nil, errors.New("missing state name")
	}

	secretClient, err := b.KubernetesSecretClient()
	if err != nil {
		return nil, err
	}

	leaseClient, err := b.KubernetesLeaseClient()
	if err != nil {
		return nil, err
	}

	client := &RemoteClient{
		kubernetesSecretClient: secretClient,
		kubernetesLeaseClient:  leaseClient,
		namespace:              b.namespace,
		labels:                 b.labels,
		nameSuffix:             b.nameSuffix,
		workspace:              name,
	}

	return client, nil
}

func (b *Backend) client() *RemoteClient {
	return &RemoteClient{}
}
