package app

import (
	"context"
	"sort"

	"coopcloud.tech/abra/cli/internal"
	"coopcloud.tech/abra/pkg/autocomplete"
	"coopcloud.tech/abra/pkg/client"
	"coopcloud.tech/abra/pkg/formatter"
	"coopcloud.tech/abra/pkg/recipe"
	"coopcloud.tech/abra/pkg/upstream/stack"
	"github.com/docker/distribution/reference"
	"github.com/olekukonko/tablewriter"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

func sortServiceByName(versions [][]string) func(i, j int) bool {
	return func(i, j int) bool {
		// NOTE(d1): corresponds to the `tableCol` definition below
		if versions[i][1] == "app" {
			return true
		}
		return versions[i][1] < versions[j][1]
	}
}

// getImagePath returns the image name
func getImagePath(image string) (string, error) {
	img, err := reference.ParseNormalizedNamed(image)
	if err != nil {
		return "", err
	}

	path := reference.Path(img)

	path = formatter.StripTagMeta(path)

	logrus.Debugf("parsed %s from %s", path, image)

	return path, nil
}

var appVersionCommand = cli.Command{
	Name:      "version",
	Aliases:   []string{"v"},
	ArgsUsage: "<domain>",
	Flags: []cli.Flag{
		internal.DebugFlag,
		internal.NoInputFlag,
		internal.OfflineFlag,
	},
	Before:       internal.SubCommandBefore,
	Usage:        "Show version info of a deployed app",
	BashComplete: autocomplete.AppNameComplete,
	Action: func(c *cli.Context) error {
		app := internal.ValidateApp(c)
		stackName := app.StackName()

		cl, err := client.New(app.Server)
		if err != nil {
			logrus.Fatal(err)
		}

		logrus.Debugf("checking whether %s is already deployed", stackName)

		isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName)
		if err != nil {
			logrus.Fatal(err)
		}

		if !isDeployed {
			logrus.Fatalf("%s is not deployed?", app.Name)
		}

		if deployedVersion == "unknown" {
			logrus.Fatalf("failed to determine version of deployed %s", app.Name)
		}

		recipeMeta, err := recipe.GetRecipeMeta(app.Recipe, internal.Offline)
		if err != nil {
			logrus.Fatal(err)
		}

		versionsMeta := make(map[string]recipe.ServiceMeta)
		for _, recipeVersion := range recipeMeta.Versions {
			if currentVersion, exists := recipeVersion[deployedVersion]; exists {
				versionsMeta = currentVersion
			}
		}

		if len(versionsMeta) == 0 {
			logrus.Fatalf("could not retrieve deployed version (%s) from recipe catalogue?", deployedVersion)
		}

		tableCol := []string{"version", "service", "image", "tag"}
		table := formatter.CreateTable(tableCol)

		var versions [][]string
		for serviceName, versionMeta := range versionsMeta {
			versions = append(versions, []string{deployedVersion, serviceName, versionMeta.Image, versionMeta.Tag})
		}

		sort.Slice(versions, sortServiceByName(versions))

		for _, version := range versions {
			table.Append(version)
		}

		table.SetAutoMergeCellsByColumnIndex([]int{0})
		table.SetAlignment(tablewriter.ALIGN_LEFT)
		table.Render()

		return nil
	},
}