// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of K9s

package ui

import (
	"context"
	"fmt"
	"log/slog"
	"os"
	"strings"

	"github.com/derailed/k9s/internal"
	"github.com/derailed/k9s/internal/config"
	"github.com/derailed/k9s/internal/slogs"
	"k8s.io/apimachinery/pkg/labels"
)

const (
	// DefaultColorName indicator to keep term colors.
	DefaultColorName = "default"

	// SearchFmt represents a filter view title.
	SearchFmt = "<[filter:bg:r]/%s[fg:bg:-]> "

	// NSTitleFmt represents a namespaced view title.
	NSTitleFmt = " [fg:bg:b]%s([hilite:bg:b]%s[fg:bg:-])[fg:bg:-][[count:bg:b]%s[fg:bg:-]][fg:bg:-] "

	// TitleFmt represents a standard view title.
	TitleFmt = " [fg:bg:b]%s[fg:bg:-][[count:bg:b]%s[fg:bg:-]][fg:bg:-] "

	descIndicator = "↓"
	ascIndicator  = "↑"

	// FullFmat specifies a namespaced dump file name.
	FullFmat = "%s-%s-%d.csv"

	// NoNSFmat specifies a cluster wide dump file name.
	NoNSFmat = "%s-%d.csv"
)

func mustExtractStyles(ctx context.Context) *config.Styles {
	styles, ok := ctx.Value(internal.KeyStyles).(*config.Styles)
	if !ok {
		slog.Error("Expecting valid styles. Exiting!")
		os.Exit(1)
	}
	return styles
}

// TrimCell removes superfluous padding.
func TrimCell(tv *SelectTable, row, col int) string {
	c := tv.GetCell(row, col)
	if c == nil {
		slog.Error("Trim cell failed", slogs.Error, fmt.Errorf("no cell at [%d:%d]", row, col))
		return ""
	}
	return strings.TrimSpace(c.Text)
}

// ExtractLabelSelector extracts label query.
func ExtractLabelSelector(s string) (labels.Selector, error) {
	selStr := s
	if strings.Index(s, "-l") == 0 {
		selStr = strings.TrimSpace(s[2:])
	}

	return labels.Parse(selStr)
}

// SkinTitle decorates a title.
func SkinTitle(fmat string, style *config.Frame) string {
	bgColor := style.Title.BgColor
	if bgColor == config.DefaultColor {
		bgColor = config.TransparentColor
	}
	fmat = strings.ReplaceAll(fmat, "[fg:bg", "["+style.Title.FgColor.String()+":"+bgColor.String())
	fmat = strings.Replace(fmat, "[hilite", "["+style.Title.HighlightColor.String(), 1)
	fmat = strings.Replace(fmat, "[key", "["+style.Menu.NumKeyColor.String(), 1)
	fmat = strings.Replace(fmat, "[filter", "["+style.Title.FilterColor.String(), 1)
	fmat = strings.Replace(fmat, "[count", "["+style.Title.CounterColor.String(), 1)
	fmat = strings.ReplaceAll(fmat, ":bg:", ":"+bgColor.String()+":")

	return fmat
}

func columnIndicator(sort, selected, asc bool, style *config.Table, name string) string {
	// Build the column name with selection indicator
	displayName := name
	if selected {
		// Make selected column bold
		displayName = fmt.Sprintf("[::b]%s[::-]", name)
	}

	// Add sort indicator if this column is sorted
	suffix := ""
	if sort {
		order := descIndicator
		if asc {
			order = ascIndicator
		}
		suffix = fmt.Sprintf("[%s::b]%s[::]", style.Header.SorterColor, order)
	}

	return displayName + suffix
}

func formatCell(field string, padding int) string {
	if IsASCII(field) {
		return Pad(field, padding)
	}

	return field
}
