package lock

import (
	"context"
	"os"

	"gopkg.in/yaml.v3"

	"edge-infra.dev/pkg/f8n/warehouse/packagelock"
	"edge-infra.dev/pkg/f8n/warehouse/release"
	"edge-infra.dev/pkg/lib/cli/rags"
	"edge-infra.dev/pkg/lib/cli/sink"
)

func New() *sink.Command {
	var (
		configPath string
		outputPath string
	)
	cmd := &sink.Command{
		Use:   "lock [flags]",
		Short: "lock a Release OCI artifact into a packagelock",
		Flags: []*rags.Rag{
			// Shared config flag used in Releaser creation
			{
				Name:  "output",
				Short: "o",
				Usage: "output path for packagelock.yaml file",
				Value: &rags.String{Var: &outputPath},
			},
			{
				Name:  "config",
				Short: "c",
				Usage: "config path for the release information",
				Value: &rags.String{Var: &configPath},
			},
		},
		Exec: func(_ context.Context, r sink.Run) error {
			envBytes, err := os.ReadFile(configPath)
			if err != nil {
				r.Log.Error(err, "couldn't open config")
				return err
			}
			environment := &release.Environment{Log: r.Log}

			err = yaml.Unmarshal(envBytes, environment)
			if err != nil {
				return err
			}

			releases, err := environment.PullReleases()
			if err != nil {
				r.Log.Error(err, "pull")
				return err
			}

			pl, err := environment.LockReleases(releases)
			if err != nil {
				r.Log.Error(err, "lock")
				return err
			}

			plr, err := packagelock.NewRules()
			if err != nil {
				r.Log.Error(err, "rules")
				return err
			}

			plBytes, err := plr.MarshalPackageLockYAML(pl)
			if err != nil {
				r.Log.Error(err, "marshal")
				return err
			}

			if outputPath == "" {
				_, err = r.Out().Write(plBytes)
				if err != nil {
					return err
				}
				return nil
			}

			err = os.WriteFile(outputPath, plBytes, 0644)
			if err != nil {
				return err
			}

			return nil
		},
	}
	return cmd
}