package main

import (
	"fmt"
	"strings"

	"github.com/charmbracelet/bubbles/textinput"
	tea "github.com/charmbracelet/bubbletea"
)

type listMode int

const (
	listBrowse listMode = iota
	listAdding
	listEditing
)

type EditableList struct {
	title  string
	items  []string
	cursor int
	mode   listMode
	input  textinput.Model
}

func NewEditableList(title string, items []string) EditableList {
	ti := textinput.New()
	ti.Placeholder = "enter value..."
	ti.CharLimit = 200
	return EditableList{
		title: title,
		items: items,
		mode:  listBrowse,
		input: ti,
	}
}

func (l EditableList) Items() []string {
	return l.items
}

func (l EditableList) IsEditing() bool {
	return l.mode != listBrowse
}

func (l EditableList) Update(msg tea.Msg) (EditableList, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.KeyMsg:
		switch l.mode {
		case listBrowse:
			switch msg.String() {
			case "up", "k":
				if l.cursor > 0 {
					l.cursor--
				}
			case "down", "j":
				if l.cursor < len(l.items)-1 {
					l.cursor++
				}
			case "a":
				l.mode = listAdding
				l.input.SetValue("")
				l.input.Focus()
				return l, textinput.Blink
			case "x", "delete":
				if len(l.items) > 0 && l.cursor < len(l.items) {
					l.items = append(l.items[:l.cursor], l.items[l.cursor+1:]...)
					if l.cursor > len(l.items)-1 {
						l.cursor = len(l.items) - 1
					}
					if l.cursor < 0 {
						l.cursor = 0
					}
				}
			case "enter":
				if len(l.items) > 0 {
					l.mode = listEditing
					l.input.SetValue(l.items[l.cursor])
					l.input.Focus()
					return l, textinput.Blink
				}
			}
		case listAdding, listEditing:
			switch msg.String() {
			case "enter":
				val := strings.TrimSpace(l.input.Value())
				if val != "" {
					if l.mode == listAdding {
						l.items = append(l.items, val)
						l.cursor = len(l.items) - 1
					} else {
						l.items[l.cursor] = val
					}
				}
				l.mode = listBrowse
				l.input.Blur()
			case "esc":
				l.mode = listBrowse
				l.input.Blur()
			default:
				var cmd tea.Cmd
				l.input, cmd = l.input.Update(msg)
				return l, cmd
			}
		}
	}
	return l, nil
}

func (l EditableList) View() string {
	var b strings.Builder

	switch l.mode {
	case listAdding:
		b.WriteString(fmt.Sprintf("%s (adding)\n", l.title))
		b.WriteString(fmt.Sprintf("> %s\n", l.input.View()))
		b.WriteString(helpStyle.Render("  enter to confirm · esc to cancel"))
	case listEditing:
		b.WriteString(fmt.Sprintf("%s (editing)\n", l.title))
		b.WriteString(fmt.Sprintf("> %s\n", l.input.View()))
		b.WriteString(helpStyle.Render("  enter to confirm · esc to cancel"))
	default:
		b.WriteString(l.title + "\n")
		if len(l.items) == 0 {
			b.WriteString(helpStyle.Render("  (empty)"))
		}
		for i, item := range l.items {
			cursor := "  "
			if i == l.cursor {
				cursor = cursorStyle.Render("> ")
			}
			b.WriteString(fmt.Sprintf("%s%s\n", cursor, item))
		}
	}

	content := b.String()
	style := boxStyle
	if l.mode != listBrowse {
		style = activeBoxStyle
	}
	return style.Render(strings.TrimRight(content, "\n"))
}
