package action

import tea "github.com/charmbracelet/bubbletea"

// ChangeToEndOfLine implements Action (C) - changes from cursor to end of line
type ChangeToEndOfLine struct {
	Count int
}

func (a ChangeToEndOfLine) Execute(m Model) tea.Cmd {
	pos := m.CursorX()
	line := m.Line(m.CursorY())

	// Save deleted text to register
	if pos < len(line) {
		m.UpdateDefaultRegister(CharwiseRegister, []string{line[pos:]})
	}

	// Delete to end of line
	m.SetLine(m.CursorY(), line[:pos])

	// Enter insert mode
	m.SetMode(InsertMode)

	return nil
}

// Ensure ChangeToEndOfLine implements Repeatable
var _ Repeatable = ChangeToEndOfLine{}

func (a ChangeToEndOfLine) WithCount(n int) Action {
	return ChangeToEndOfLine{Count: n}
}

// SubstituteChar implements Action (s) - deletes character and enters insert mode
type SubstituteChar struct {
	Count int
}

func (a SubstituteChar) Execute(m Model) tea.Cmd {
	pos := m.CursorX()
	line := m.Line(m.CursorY())

	// Calculate how many chars to delete (limited by line length)
	count := min(a.Count, len(line)-pos)

	if count > 0 {
		// Save deleted text to register
		m.UpdateDefaultRegister(CharwiseRegister, []string{line[pos : pos+count]})

		// Delete the characters
		m.SetLine(m.CursorY(), line[:pos]+line[pos+count:])
	}

	// Enter insert mode
	m.SetMode(InsertMode)

	return nil
}

// Ensure SubstituteChar implements Repeatable
var _ Repeatable = SubstituteChar{}

func (a SubstituteChar) WithCount(n int) Action {
	return SubstituteChar{Count: n}
}

// SubstituteLine implements Action (S) - clears line and enters insert mode
type SubstituteLine struct {
	Count int
}

func (a SubstituteLine) Execute(m Model) tea.Cmd {
	y := m.CursorY()

	// Calculate how many lines to substitute
	count := min(a.Count, m.LineCount()-y)

	var lines []string

	// Collect and delete lines
	for range count {
		lines = append(lines, m.Line(y))
		m.DeleteLine(y)
	}

	// Save deleted lines to register
	m.UpdateDefaultRegister(LinewiseRegister, lines)

	// Insert empty line at original position
	insertY := min(y, m.LineCount())
	m.InsertLine(insertY, "")

	// Position cursor
	m.SetCursorY(insertY)
	m.SetCursorX(0)

	// Enter insert mode
	m.SetMode(InsertMode)

	return nil
}

// Ensure SubstituteLine implements Repeatable
var _ Repeatable = SubstituteLine{}

func (a SubstituteLine) WithCount(n int) Action {
	return SubstituteLine{Count: n}
}
