// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package goal

import (
	"errors"
	"fmt"
	"strings"

	"git.secluded.site/go-lunatask"
	"git.secluded.site/lune/internal/client"
	"git.secluded.site/lune/internal/completion"
	"git.secluded.site/lune/internal/config"
	"git.secluded.site/lune/internal/stats"
	"git.secluded.site/lune/internal/ui"
	"github.com/spf13/cobra"
)

// ErrAmbiguousGoal indicates the goal key exists in multiple areas.
var ErrAmbiguousGoal = errors.New("ambiguous goal key")

// ShowCmd displays details for a specific goal.
var ShowCmd = &cobra.Command{
	Use:   "show KEY",
	Short: "Show goal details",
	Long: `Show detailed information for a configured goal.

If the goal key exists in multiple areas, use --area to disambiguate.
Displays the goal's name, ID, deeplink, and uncompleted task count.`,
	Args:              cobra.ExactArgs(1),
	ValidArgsFunction: completion.Goals,
	RunE:              runShow,
}

func init() {
	ShowCmd.Flags().StringP("area", "a", "", "Area key (required if goal key is ambiguous)")
	_ = ShowCmd.RegisterFlagCompletionFunc("area", completion.Areas)
}

func runShow(cmd *cobra.Command, args []string) error {
	goalKey := args[0]
	areaKey, _ := cmd.Flags().GetString("area")

	cfg, err := config.Load()
	if err != nil {
		return err
	}

	match, err := resolveGoal(cfg, goalKey, areaKey)
	if err != nil {
		return err
	}

	apiClient, err := client.New()
	if err != nil {
		return err
	}

	counter := stats.NewTaskCounter(apiClient)

	return printGoalDetails(cmd, match.Goal, match.Area, counter)
}

func resolveGoal(cfg *config.Config, goalKey, areaKey string) (*config.GoalMatch, error) {
	if areaKey != "" {
		area := cfg.AreaByKey(areaKey)
		if area == nil {
			return nil, fmt.Errorf("%w: %s", ErrUnknownArea, areaKey)
		}

		goal := area.GoalByKey(goalKey)
		if goal == nil {
			return nil, fmt.Errorf("%w: %s", ErrUnknownGoal, goalKey)
		}

		return &config.GoalMatch{Goal: goal, Area: area}, nil
	}

	matches := cfg.FindGoalsByKey(goalKey)

	switch len(matches) {
	case 0:
		return nil, fmt.Errorf("%w: %s", ErrUnknownGoal, goalKey)

	case 1:
		return &matches[0], nil

	default:
		areas := make([]string, len(matches))
		for i, m := range matches {
			areas[i] = m.Area.Key
		}

		return nil, fmt.Errorf(
			"%w: %s exists in %s; use --area to specify",
			ErrAmbiguousGoal, goalKey, strings.Join(areas, ", "),
		)
	}
}

func printGoalDetails(cmd *cobra.Command, goal *config.Goal, area *config.Area, counter *stats.TaskCounter) error {
	link, _ := lunatask.BuildDeepLink(lunatask.ResourceGoal, goal.ID)

	fmt.Fprintf(cmd.OutOrStdout(), "%s (%s)\n", ui.H1.Render(goal.Name), goal.Key)
	fmt.Fprintf(cmd.OutOrStdout(), "  ID:   %s\n", goal.ID)
	fmt.Fprintf(cmd.OutOrStdout(), "  Area: %s (%s)\n", area.Name, area.Key)
	fmt.Fprintf(cmd.OutOrStdout(), "  Link: %s\n", link)

	taskCount, err := counter.UncompletedInGoal(cmd.Context(), goal.ID)
	if err != nil {
		fmt.Fprintf(cmd.OutOrStdout(), "  Tasks: %s\n", ui.Warning.Render("unable to fetch"))
	} else {
		fmt.Fprintf(cmd.OutOrStdout(), "  Tasks: %d uncompleted\n", taskCount)
	}

	return nil
}
