// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package times

import (
	stdctx "context"
	"fmt"
	"strings"
	"time"

	"gitea.dev/sdk"

	"gitea.dev/tea/cmd/flags"
	"gitea.dev/tea/modules/context"
	"gitea.dev/tea/modules/print"
	"gitea.dev/tea/modules/utils"
	"github.com/araddon/dateparse"
	"github.com/urfave/cli/v3"
)

// NOTE: not using NewCsvFlag, as we don't want an alias & default value.
var timeFieldsFlag = &flags.CsvFlag{
	AvailableFields: print.TrackedTimeFields,
	StringFlag: cli.StringFlag{
		Name: "fields",
		Usage: fmt.Sprintf(`Comma-separated list of fields to print. Available values:
	%s
`, strings.Join(print.TrackedTimeFields, ",")),
	},
}

// CmdTrackedTimesList represents a sub command of times to list them
var CmdTrackedTimesList = cli.Command{
	Name:    "list",
	Aliases: []string{"ls"},
	Action:  RunTimesList,
	Usage:   "List tracked times on issues & pulls",
	Description: `List tracked times, across repos, or on a single repo or issue:
- given a username all times on a repo by that user are shown,
- given a issue index with '#' prefix, all times on that issue are listed,
- given --mine, your times are listed across all repositories.
Depending on your permissions on the repository, only your own tracked times might be listed.`,
	ArgsUsage: "[username | #issue]",

	Flags: append([]cli.Flag{
		&cli.StringFlag{
			Name:    "from",
			Aliases: []string{"f"},
			Usage:   "Show only times tracked after this date",
		},
		&cli.StringFlag{
			Name:    "until",
			Aliases: []string{"u"},
			Usage:   "Show only times tracked before this date",
		},
		&cli.BoolFlag{
			Name:    "total",
			Aliases: []string{"t"},
			Usage:   "Print the total duration at the end",
		},
		&cli.BoolFlag{
			Name:    "mine",
			Aliases: []string{"m"},
			Usage:   "Show all times tracked by you across all repositories (overrides command arguments)",
		},
		timeFieldsFlag,
		&flags.PaginationPageFlag,
		&flags.PaginationLimitFlag,
	}, flags.AllDefaultFlags...),
}

// RunTimesList list repositories
func RunTimesList(requestCtx stdctx.Context, cmd *cli.Command) error {
	ctx, err := context.InitCommand(cmd)
	if err != nil {
		return err
	}
	if err := ctx.Ensure(context.CtxRequirement{RemoteRepo: true}); err != nil {
		return err
	}
	client := ctx.Login.Client()

	var times []*gitea.TrackedTime
	var from, until time.Time
	var fields []string

	if ctx.IsSet("from") {
		from, err = dateparse.ParseLocal(ctx.String("from"))
		if err != nil {
			return err
		}
	}
	if ctx.IsSet("until") {
		until, err = dateparse.ParseLocal(ctx.String("until"))
		if err != nil {
			return err
		}
	}

	opts := gitea.ListTrackedTimesOptions{
		ListOptions: flags.GetListOptions(cmd),
		Since:       from,
		Before:      until,
	}

	user := ctx.Args().First()
	if ctx.Bool("mine") {
		times, _, err = client.Issues.ListMyTrackedTimes(requestCtx, opts)
		fields = []string{"created", "repo", "issue", "duration"}
	} else if user == "" {
		// get all tracked times on the repo
		times, _, err = client.Issues.ListRepoTrackedTimes(requestCtx, ctx.Owner, ctx.Repo, opts)
		fields = []string{"created", "issue", "user", "duration"}
	} else if strings.HasPrefix(user, "#") {
		// get all tracked times on the specified issue
		issue, parseErr := utils.ArgToIndex(user)
		if parseErr != nil {
			return parseErr
		}
		times, _, err = client.Issues.ListIssueTrackedTimes(requestCtx, ctx.Owner, ctx.Repo, issue, opts)
		fields = []string{"created", "user", "duration"}
	} else {
		// get all tracked times by the specified user
		opts.User = user
		times, _, err = client.Issues.ListRepoTrackedTimes(requestCtx, ctx.Owner, ctx.Repo, opts)
		fields = []string{"created", "issue", "duration"}
	}

	if err != nil {
		return err
	}

	if ctx.IsSet("fields") {
		if fields, err = timeFieldsFlag.GetValues(cmd); err != nil {
			return err
		}
	}

	return print.TrackedTimesList(times, ctx.Output, fields, ctx.Bool("total"))
}
