// Package theme centralises dial's visual styling. The brief makes low-light
// legibility a hard requirement: generous spacing, high contrast, and no dense
// dim text. These styles encode that — the "muted" tones are still clearly
// readable, not the near-invisible grey common in dense pickers.
package theme

import (
	"hash/fnv"

	"github.com/charmbracelet/lipgloss"
)

// Theme holds the styles used across the picker.
type Theme struct {
	Title     lipgloss.Style
	Meta      lipgloss.Style // header meta / hints
	Number    lipgloss.Style // list index
	NumberSel lipgloss.Style
	Alias     lipgloss.Style // host alias, resting
	AliasSel  lipgloss.Style // host alias, highlighted
	Detail    lipgloss.Style // secondary line (hostname/user)
	DetailSel lipgloss.Style
	Tag       lipgloss.Style
	Star      lipgloss.Style
	Cursor    lipgloss.Style // the selection bar/marker
	Preview   lipgloss.Style // preview box border
	PreviewK  lipgloss.Style // preview key column
	PreviewV  lipgloss.Style // preview value column
	FilterBar lipgloss.Style
	Help      lipgloss.Style
	Warn      lipgloss.Style

	// tagPalette is a set of distinct high-contrast hues used to colour tag
	// pills and tag section headers, assigned deterministically per tag name.
	tagPalette []lipgloss.AdaptiveColor
	base       lipgloss.Style
}

// TagStyle returns the pill style for a tag, colour chosen deterministically by
// the tag name so the same tag is always the same colour. An empty tag name
// (used for the Favourites/untagged sections) gets a neutral style.
func (t Theme) TagStyle(tag string) lipgloss.Style {
	if tag == "" {
		return t.Meta
	}
	h := fnv.New32a()
	_, _ = h.Write([]byte(tag))
	c := t.tagPalette[int(h.Sum32())%len(t.tagPalette)]
	return t.base.Foreground(c)
}

// adaptive picks a colour for dark vs light backgrounds.
func adaptive(dark, light string) lipgloss.AdaptiveColor {
	return lipgloss.AdaptiveColor{Dark: dark, Light: light}
}

// New returns the theme for the given name ("dark" or "light"). Both are built
// from the same high-contrast palette; lipgloss adapts per background so a
// single definition stays readable either way.
func New(name string) Theme {
	// High-contrast, deliberately bright accents for low-light legibility.
	accent := adaptive("#7DD3FC", "#0369A1")  // sky — highlighted alias
	accent2 := adaptive("#FDE047", "#A16207") // amber — numbers/stars
	fg := adaptive("#F1F5F9", "#0F172A")      // primary text (near-white / near-black)
	muted := adaptive("#CBD5E1", "#334155")   // secondary text — still clearly readable
	faint := adaptive("#94A3B8", "#475569")   // hints; the dimmest we allow
	tag := adaptive("#86EFAC", "#15803D")     // green tags
	warn := adaptive("#FCA5A5", "#B91C1C")

	base := lipgloss.NewStyle()

	// Distinct, high-contrast hues for tag pills (dark / light variants).
	tagPalette := []lipgloss.AdaptiveColor{
		adaptive("#7DD3FC", "#0369A1"), // sky
		adaptive("#86EFAC", "#15803D"), // green
		adaptive("#FDBA74", "#C2410C"), // orange
		adaptive("#F9A8D4", "#BE185D"), // pink
		adaptive("#C4B5FD", "#6D28D9"), // violet
		adaptive("#5EEAD4", "#0F766E"), // teal
		adaptive("#FDE047", "#A16207"), // amber
		adaptive("#FCA5A5", "#B91C1C"), // red
	}

	return Theme{
		base:       base,
		tagPalette: tagPalette,
		Title:      base.Bold(true).Foreground(fg),
		Meta:      base.Foreground(faint),
		Number:    base.Foreground(faint),
		NumberSel: base.Bold(true).Foreground(accent2),
		Alias:     base.Foreground(fg),
		AliasSel:  base.Bold(true).Foreground(accent),
		Detail:    base.Foreground(muted),
		DetailSel: base.Foreground(muted),
		Tag:       base.Foreground(tag),
		Star:      base.Foreground(accent2),
		Cursor:    base.Bold(true).Foreground(accent),
		Preview:   base.BorderStyle(lipgloss.RoundedBorder()).BorderForeground(faint).Padding(0, 2),
		PreviewK:  base.Foreground(faint),
		PreviewV:  base.Foreground(fg),
		FilterBar: base.Bold(true).Foreground(accent2),
		Help:      base.Foreground(faint),
		Warn:      base.Bold(true).Foreground(warn),
	}
}
