package ui

import (
	"fmt"
	"os"
	"time"

	"github.com/charmbracelet/lipgloss"
	"github.com/charmbracelet/lipgloss/table"
	terminal "golang.org/x/term"
)

var (
	// ANSI256 256 colors, 8-bit

	Blue    = lipgloss.Color("21")
	Magenta = lipgloss.Color("13")
	Gray    = lipgloss.Color("238")
	White   = lipgloss.Color("15")
	Red     = lipgloss.Color("9")
	Green   = lipgloss.Color("10")
	Yellow  = lipgloss.Color("11")

	// styling
	headerStyle = lipgloss.NewStyle().
			Background(Blue).
			Foreground(White).
			Padding(0, 1).
			Italic(true)
	infoStyle = headerStyle.Copy().
			Foreground(White).
			Background(Gray)
	subHeaderStyle = headerStyle.Copy().
			Background(lipgloss.NoColor{})
	errorStyle = lipgloss.NewStyle().Foreground(Red)
)

type TableBuilder struct {
	tableHeader []string
	rows        [][]string
	Table       *table.Table
	padding     int
}

func NewTableBuilder() *TableBuilder {
	return &TableBuilder{
		Table:   table.New(),
		padding: 1,
	}
}

func (t *TableBuilder) Reset() {
	t.tableHeader = nil
	t.rows = nil
	t.Table = table.New()
}

func (t *TableBuilder) AddTableHeader(strs ...string) {
	t.tableHeader = append(t.tableHeader, strs...)
}

func (t *TableBuilder) AddRow(strs ...string) {
	t.rows = append(t.rows, strs)
}

func (t *TableBuilder) Width(w int) {
	t.Table.Width(w)
}

func (t *TableBuilder) colWidth(colNumber int) int {
	var maxWidth int
	for _, row := range t.rows {
		for col, v := range row {
			if col == colNumber && maxWidth < len(v)+t.padding*2 {
				maxWidth = len(v) + t.padding*2
			}
		}
	}
	return maxWidth
}

func (t *TableBuilder) CreateTable() *table.Table {
	width, _, _ := terminal.GetSize(0)
	t.Table.
		BorderRow(false).BorderColumn(false).
		BorderLeft(false).BorderRight(false).BorderTop(false).BorderBottom(false).
		//Border(lipgloss.RoundedBorder()).
		//BorderRow(true).
		//BorderStyle(BorderStyle).
		StyleFunc(func(row, col int) lipgloss.Style {
			re := lipgloss.NewRenderer(os.Stdout)
			if row == -1 {
				// Align(lipgloss.Center)
				return re.NewStyle().Bold(true).Align(lipgloss.Left).Padding(0, 2, 0, 0).Foreground(Green)
			}
			return re.NewStyle().Padding(0, 2, 0, 0).Align(lipgloss.Left)
		}).
		Headers(t.tableHeader...).
		Rows(t.rows...)

	switch {
	case width < 100:
		t.Table.Width(width)
	case len(t.tableHeader) > 8:
		t.Table.Width(width)
	}

	return t.Table
}

// Justify Выравнивание по ширине терминала
func (t *TableBuilder) Justify() {
	width, _, _ := terminal.GetSize(0)
	t.Table.Width(width)
}

func Header(s string) string {
	return headerStyle.Render(s)
}

func SubHeader(s string) string {
	return subHeaderStyle.Render(s)
}

func Info(s string) string {
	return infoStyle.Render(s)
}

func StringBar(strs ...string) string {
	return lipgloss.JoinHorizontal(lipgloss.Left, strs...)
}

func ErrorBar(s string) string {
	return errorStyle.Render(s)
}

func SetColor(color lipgloss.Color, str string) string {
	return lipgloss.NewStyle().Foreground(color).Render(str)
}

func Spinner(stop chan bool, description string) {
	spinner := []rune{'|', '\\', '-', '/'}
	for {
		for _, r := range spinner {
			select {
			case <-stop:
				fmt.Printf("\r")
				return
			default:
				fmt.Printf("\r%c %s", r, description)
				time.Sleep(100 * time.Millisecond)
			}
		}
	}
}
