// Package style provides a tiny, conservative ANSI-color helper for
// banger's CLI. The contract:
//
//   - Each helper takes the writer the styled string is going to and
//     returns either the wrapped string or the plain one.
//   - "Wrapped" only happens when the writer is a TTY AND the
//     NO_COLOR environment variable is unset.
//   - No 256-color or truecolor; no theme system; no external dep.
//
// Banger's CLI uses these for status (pass/fail/warn), error
// prefixes, and dim secondary text. Anything richer belongs in a
// dedicated TUI layer that this package isn't.
package style

import (
	"io"
	"os"
	"strings"
)

// ANSI escape sequences. Kept private — callers compose meaning via
// the named helpers (Pass/Fail/Warn/...), not raw codes.
const (
	ansiReset = "\x1b[0m"
	ansiBold  = "\x1b[1m"
	ansiDim   = "\x1b[2m"
	ansiRed   = "\x1b[31m"
	ansiGreen = "\x1b[32m"
	ansiYel   = "\x1b[33m"
)

// Pass wraps s in green when w is a TTY and NO_COLOR is unset.
func Pass(w io.Writer, s string) string { return wrap(w, ansiGreen, s) }

// Fail wraps s in red.
func Fail(w io.Writer, s string) string { return wrap(w, ansiRed, s) }

// Warn wraps s in yellow.
func Warn(w io.Writer, s string) string { return wrap(w, ansiYel, s) }

// Dim wraps s in dim.
func Dim(w io.Writer, s string) string { return wrap(w, ansiDim, s) }

// Bold wraps s in bold.
func Bold(w io.Writer, s string) string { return wrap(w, ansiBold, s) }

// SupportsColor reports whether colored output should be emitted to
// w. Exposed so callers that build multi-segment strings can avoid
// duplicating the gate per call.
func SupportsColor(w io.Writer) bool {
	if strings.TrimSpace(os.Getenv("NO_COLOR")) != "" {
		return false
	}
	file, ok := w.(*os.File)
	if !ok {
		return false
	}
	info, err := file.Stat()
	if err != nil {
		return false
	}
	return info.Mode()&os.ModeCharDevice != 0
}

func wrap(w io.Writer, code, s string) string {
	if !SupportsColor(w) {
		return s
	}
	return code + s + ansiReset
}
