// SPDX-License-Identifier: GPL-3.0-or-later

// Package term provides terminal utilities for the CLI.
package term

import (
	"os"
	"runtime"
	"strings"

	"golang.org/x/term"
)

// Terminal provides terminal detection and capabilities.
type Terminal struct {
	// Whether stdout is a TTY
	IsTTY bool
	// Terminal width in columns
	Width int
	// Terminal height in rows
	Height int
	// Whether the terminal supports colors
	HasColors bool
}

// Detect detects terminal capabilities.
func Detect() *Terminal {
	t := &Terminal{}

	// Check if stdout is a TTY
	fd := int(os.Stdout.Fd())
	t.IsTTY = term.IsTerminal(fd)

	if t.IsTTY {
		// Get terminal size
		w, h, err := term.GetSize(fd)
		if err == nil {
			t.Width = w
			t.Height = h
		} else {
			// Default sizes
			t.Width = 80
			t.Height = 24
		}

		// Assume color support if TTY (most modern terminals support it)
		t.HasColors = true

		// Check for NO_COLOR environment variable
		if os.Getenv("NO_COLOR") != "" {
			t.HasColors = false
		}

		// Check for dumb terminal
		if os.Getenv("TERM") == "dumb" {
			t.HasColors = false
		}
	} else {
		// Not a TTY - use defaults for piped output
		t.Width = 80
		t.Height = 24
		t.HasColors = false
	}

	return t
}

// IsInteractive returns whether the terminal supports interactive input.
func (t *Terminal) IsInteractive() bool {
	return t.IsTTY
}

// ShouldUseColor returns whether to use color output.
func (t *Terminal) ShouldUseColor(colorMode string) bool {
	switch colorMode {
	case "always":
		return true
	case "never":
		return false
	default: // "auto"
		return t.HasColors
	}
}

// GetWidth returns the terminal width, with a minimum.
func (t *Terminal) GetWidth() int {
	if t.Width < 40 {
		return 40
	}
	return t.Width
}

// GetHeight returns the terminal height, with a minimum.
func (t *Terminal) GetHeight() int {
	if t.Height < 10 {
		return 10
	}
	return t.Height
}

// IsWindows returns whether the current OS is Windows.
func IsWindows() bool {
	return runtime.GOOS == "windows"
}

// IsMacOS returns whether the current OS is macOS.
func IsMacOS() bool {
	return runtime.GOOS == "darwin"
}

// IsLinux returns whether the current OS is Linux.
func IsLinux() bool {
	return runtime.GOOS == "linux"
}

// SupportsUnicode returns whether the terminal likely supports Unicode.
func (t *Terminal) SupportsUnicode() bool {
	// Check common environment variables
	lang := os.Getenv("LANG")
	lcAll := os.Getenv("LC_ALL")

	// Look for UTF-8 indicators
	for _, env := range []string{lang, lcAll} {
		if contains(env, "UTF-8") || contains(env, "utf-8") || contains(env, "UTF8") || contains(env, "utf8") {
			return true
		}
	}

	// macOS and modern Linux usually support Unicode
	if IsMacOS() || IsLinux() {
		return true
	}

	return false
}

// CanShowProgress returns whether the terminal can show progress bars.
func (t *Terminal) CanShowProgress() bool {
	return t.IsTTY && t.Width > 40
}

// IsNarrow returns whether the terminal is narrow.
// If threshold is provided, it's used as the width threshold (default 80).
func (t *Terminal) IsNarrow(threshold ...int) bool {
	w := 80
	if len(threshold) > 0 && threshold[0] > 0 {
		w = threshold[0]
	}
	return t.Width < w
}

// contains checks if a string contains a substring using the standard library.
func contains(s, substr string) bool {
	return strings.Contains(s, substr)
}
