package opt_test

import (
	"strings"
	"testing"

	"git.sr.ht/~rjarry/go-opt/v2"
	"github.com/stretchr/testify/assert"
)

type CompleteStruct struct {
	Name    string   `opt:"-n,--name" required:"true" complete:"CompleteName" desc:"Ninja turtle name."`
	Delay   float64  `opt:"--delay"`
	Zero    bool     `opt:"-z" description:"Print zero values"`
	Backoff bool     `opt:"-B,--backoff" desc:"Increase delay on error"`
	Tags    []string `opt:"..." complete:"CompleteTag"`
}

func (c *CompleteStruct) CompleteName(arg string) []string {
	var names []string
	for _, n := range []string{"leonardo", "michelangelo", "rafaelo", "donatello"} {
		if strings.HasPrefix(n, arg) {
			names = append(names, n)
		}
	}
	return names
}

func (c *CompleteStruct) CompleteTag(arg string) []string {
	var results []string
	prefix := ""
	if strings.HasPrefix(arg, "-") {
		prefix = "-"
	} else if strings.HasPrefix(arg, "+") {
		prefix = "+"
	}
	tags := []string{"unread", "sent", "important", "inbox", "trash"}
	for _, t := range tags {
		t = prefix + t
		if strings.HasPrefix(t, arg) {
			results = append(results, t)
		}
	}
	return results
}

func TestComplete(t *testing.T) {
	vectors := []struct {
		cmdline     string
		completions []opt.Completion
		prefix      string
	}{
		{
			"foo --delay 33..33.3 -n",
			[]opt.Completion{{Value: "-n ", Description: "Ninja turtle name."}},
			"foo --delay 33..33.3 ",
		},
		{
			"foo --delay 33..33.3 -n ",
			[]opt.Completion{
				{Value: "leonardo", Description: "Ninja turtle name."},
				{Value: "michelangelo", Description: "Ninja turtle name."},
				{Value: "rafaelo", Description: "Ninja turtle name."},
				{Value: "donatello", Description: "Ninja turtle name."},
			},
			"foo --delay 33..33.3 -n ",
		},
		{
			"foo --delay 33..33.3 -n don",
			[]opt.Completion{{Value: "donatello", Description: "Ninja turtle name."}},
			"foo --delay 33..33.3 -n ",
		},
		{
			"foo --delay 33..33.3 --name=",
			[]opt.Completion{
				{Value: "leonardo", Description: "Ninja turtle name."},
				{Value: "michelangelo", Description: "Ninja turtle name."},
				{Value: "rafaelo", Description: "Ninja turtle name."},
				{Value: "donatello", Description: "Ninja turtle name."},
			},
			"foo --delay 33..33.3 --name=",
		},
		{
			"foo --delay 33..33.3 --name=leo",
			[]opt.Completion{{Value: "leonardo", Description: "Ninja turtle name."}},
			"foo --delay 33..33.3 --name=",
		},
		{
			"foo --nam",
			[]opt.Completion{{Value: "--name ", Description: "Ninja turtle name."}},
			"foo ",
		},
		{
			"foo --delay 33..33.3 --backoff",
			[]opt.Completion{{Value: "--backoff ", Description: "Increase delay on error"}},
			"foo --delay 33..33.3 ",
		},
		{
			"foo --delay 33..33.3 -",
			[]opt.Completion{
				{Value: "-unread"},
				{Value: "-sent"},
				{Value: "-important"},
				{Value: "-inbox"},
				{Value: "-trash"},
				{Value: "-n ", Description: "Ninja turtle name."},
				{Value: "--name ", Description: "Ninja turtle name."},
				{Value: "-z ", Description: "Print zero values"},
				{Value: "-B ", Description: "Increase delay on error"},
				{Value: "--backoff ", Description: "Increase delay on error"},
			},
			"foo --delay 33..33.3 ",
		},
		{
			"foo --delay 33..33.3 ",
			[]opt.Completion{
				{Value: "unread"},
				{Value: "sent"},
				{Value: "important"},
				{Value: "inbox"},
				{Value: "trash"},
				{Value: "-n ", Description: "Ninja turtle name."},
				{Value: "--name ", Description: "Ninja turtle name."},
				{Value: "-z ", Description: "Print zero values"},
				{Value: "-B ", Description: "Increase delay on error"},
				{Value: "--backoff ", Description: "Increase delay on error"},
			},
			"foo --delay 33..33.3 ",
		},
		{
			"foo --delay 33..33.3 -n leonardo i",
			[]opt.Completion{{Value: "important"}, {Value: "inbox"}},
			"foo --delay 33..33.3 -n leonardo ",
		},
		{
			"foo +",
			[]opt.Completion{
				{Value: "+unread"},
				{Value: "+sent"},
				{Value: "+important"},
				{Value: "+inbox"},
				{Value: "+trash"},
			},
			"foo ",
		},
		{
			"foo -i",
			[]opt.Completion{{Value: "-important"}, {Value: "-inbox"}},
			"foo ",
		},
	}

	for _, v := range vectors {
		t.Run(v.cmdline, func(t *testing.T) {
			args := opt.LexArgs(v.cmdline)
			spec := opt.NewCmdSpec(args.Arg(0), new(CompleteStruct))
			completions, prefix := spec.GetCompletions(args)
			assert.Equal(t, v.completions, completions)
			assert.Equal(t, v.prefix, prefix)
		})
	}
}
