package app

import (
	"context"
	"fmt"
	"strings"

	"coopcloud.tech/abra/pkg/client/stack"
	"coopcloud.tech/abra/pkg/config"
	apiclient "github.com/docker/docker/client"
	"github.com/sirupsen/logrus"
)

// Get retrieves an app
func Get(appName string) (config.App, error) {
	files, err := config.LoadAppFiles("")
	if err != nil {
		return config.App{}, err
	}

	app, err := config.GetApp(files, appName)
	if err != nil {
		return config.App{}, err
	}

	logrus.Debugf("retrieved '%s' for '%s'", app, appName)

	return app, nil
}

// deployedServiceSpec represents a deployed service of an app.
type deployedServiceSpec struct {
	Name    string
	Version string
}

// VersionSpec represents a deployed app and associated metadata.
type VersionSpec map[string]deployedServiceSpec

// DeployedVersions lists metadata (e.g. versions) for deployed
func DeployedVersions(ctx context.Context, cl *apiclient.Client, app config.App) (VersionSpec, bool, error) {
	services, err := stack.GetStackServices(ctx, cl, app.StackName())
	if err != nil {
		return VersionSpec{}, false, err
	}

	appSpec := make(VersionSpec)
	for _, service := range services {
		serviceName := ParseServiceName(service.Spec.Name)
		label := fmt.Sprintf("coop-cloud.%s.%s.version", app.StackName(), serviceName)
		if deployLabel, ok := service.Spec.Labels[label]; ok {
			version, _ := ParseVersionLabel(deployLabel)
			appSpec[serviceName] = deployedServiceSpec{Name: serviceName, Version: version}
		}
	}

	deployed := len(services) > 0

	if deployed {
		logrus.Debugf("detected '%s' as deployed versions of '%s'", appSpec, app.Name)
	} else {
		logrus.Debugf("detected '%s' as not deployed", app.Name)
	}

	return appSpec, len(services) > 0, nil
}

// ParseVersionLabel parses a $VERSION-$DIGEST app service label.
func ParseVersionLabel(label string) (string, string) {
	// versions may look like v4.2-abcd or v4.2-alpine-abcd
	idx := strings.LastIndex(label, "-")
	version := label[:idx]
	digest := label[idx+1:]
	logrus.Debugf("parsed '%s' as version from '%s'", version, label)
	logrus.Debugf("parsed '%s' as digest from '%s'", digest, label)
	return version, digest
}

// ParseVersionName parses a $STACK_NAME_$SERVICE_NAME service label.
func ParseServiceName(label string) string {
	idx := strings.LastIndex(label, "_")
	serviceName := label[idx+1:]
	logrus.Debugf("parsed '%s' as service name from '%s'", serviceName, label)
	return serviceName
}