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

package area

import (
	"encoding/json"
	"fmt"

	"git.secluded.site/lune/internal/config"
	"git.secluded.site/lune/internal/ui"
	"github.com/charmbracelet/lipgloss"
	"github.com/charmbracelet/lipgloss/table"
	"github.com/spf13/cobra"
)

// ListCmd lists configured areas and their goals.
var ListCmd = &cobra.Command{
	Use:   "list",
	Short: "List configured areas",
	Long: `List areas configured in lune.

Areas are copied from the Lunatask desktop app during 'lune init'.
Each area may have goals associated with it.`,
	RunE: runList,
}

func init() {
	ListCmd.Flags().Bool("json", false, "Output as JSON")
}

func runList(cmd *cobra.Command, _ []string) error {
	cfg, err := config.Load()
	if err != nil {
		return err
	}

	if len(cfg.Areas) == 0 {
		fmt.Fprintln(cmd.OutOrStdout(), "No areas configured")

		return nil
	}

	jsonFlag, _ := cmd.Flags().GetBool("json")
	if jsonFlag {
		return outputJSON(cmd, cfg.Areas)
	}

	return outputTable(cmd, cfg.Areas)
}

func outputJSON(cmd *cobra.Command, areas []config.Area) error {
	enc := json.NewEncoder(cmd.OutOrStdout())
	enc.SetIndent("", "  ")

	if err := enc.Encode(areas); err != nil {
		return fmt.Errorf("encoding JSON: %w", err)
	}

	return nil
}

func outputTable(cmd *cobra.Command, areas []config.Area) error {
	rows := make([][]string, 0, len(areas))

	for _, area := range areas {
		goals := formatGoals(area.Goals)
		rows = append(rows, []string{area.Key, area.Name, goals})
	}

	tbl := table.New().
		Headers("KEY", "NAME", "GOALS").
		Rows(rows...).
		StyleFunc(func(row, col int) lipgloss.Style {
			if row == table.HeaderRow {
				return ui.TableHeaderStyle()
			}

			return lipgloss.NewStyle()
		}).
		Border(ui.TableBorder())

	fmt.Fprintln(cmd.OutOrStdout(), tbl.Render())

	return nil
}

func formatGoals(goals []config.Goal) string {
	if len(goals) == 0 {
		return "-"
	}

	keys := make([]string, len(goals))
	for i, g := range goals {
		keys[i] = g.Key
	}

	if len(keys) <= 3 {
		return joinKeys(keys)
	}

	return joinKeys(keys[:3]) + fmt.Sprintf(" (+%d)", len(keys)-3)
}

func joinKeys(keys []string) string {
	result := ""

	for i, k := range keys {
		if i > 0 {
			result += ", "
		}

		result += k
	}

	return result
}
