package interaction

import (
	"fmt"
	"strings"
	"tunnel_pls/internal/types"

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

func (m *model) slugUpdate(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
	var cmd tea.Cmd

	if m.tunnelType != types.TunnelTypeHTTP {
		m.editingSlug = false
		m.slugError = ""
		return m, tea.Batch(tea.ClearScreen, textinput.Blink)
	}

	switch msg.String() {
	case "esc", "ctrl+c":
		m.editingSlug = false
		m.slugError = ""
		return m, tea.Batch(tea.ClearScreen, textinput.Blink)
	case "enter":
		inputValue := m.slugInput.Value()
		if err := m.interaction.sessionRegistry.Update(m.interaction.user, types.SessionKey{
			Id:   m.interaction.slug.String(),
			Type: types.TunnelTypeHTTP,
		}, types.SessionKey{
			Id:   inputValue,
			Type: types.TunnelTypeHTTP,
		}); err != nil {
			m.slugError = err.Error()
			return m, nil
		}
		m.editingSlug = false
		m.slugError = ""
		return m, tea.Batch(tea.ClearScreen, textinput.Blink)
	default:
		if key.Matches(msg, m.keymap.random) {
			newSubdomain, err := m.randomizer.String(20)
			if err != nil {
				return m, cmd
			}
			m.slugInput.SetValue(newSubdomain)
		}
		m.slugError = ""
		m.slugInput, cmd = m.slugInput.Update(msg)
		return m, cmd
	}
}

func (m *model) slugView() string {
	isCompact := shouldUseCompactLayout(m.width, BreakpointMedium)
	isVeryCompact := shouldUseCompactLayout(m.width, BreakpointTiny)

	var b strings.Builder
	b.WriteString(m.renderSlugTitle(isVeryCompact))

	if m.tunnelType != types.TunnelTypeHTTP {
		b.WriteString(m.renderTCPWarning(isVeryCompact, isCompact))
		return b.String()
	}

	b.WriteString(m.renderSlugRules(isVeryCompact, isCompact))
	b.WriteString(m.renderSlugInstruction(isVeryCompact))
	b.WriteString(m.renderSlugInput(isVeryCompact, isCompact))
	b.WriteString(m.renderSlugPreview(isVeryCompact))
	b.WriteString(m.renderSlugHelp(isVeryCompact))

	return b.String()
}

func (m *model) renderSlugTitle(isVeryCompact bool) string {
	titleStyle := lipgloss.NewStyle().
		Bold(true).
		Foreground(lipgloss.Color(ColorPrimary)).
		PaddingTop(1).
		PaddingBottom(1)

	title := "🔧 Edit Subdomain"
	if isVeryCompact {
		title = "Edit Subdomain"
	}

	return titleStyle.Render(title) + "\n\n"
}

func (m *model) renderTCPWarning(isVeryCompact, isCompact bool) string {
	boxPadding := getPaddingValue(isVeryCompact, isCompact)
	boxMargin := getMarginValue(isCompact, 1, 2)
	warningBoxWidth := getResponsiveWidth(m.width, 10, 30, 60)

	warningBoxStyle := lipgloss.NewStyle().
		Foreground(lipgloss.Color(ColorWarning)).
		Background(lipgloss.Color(ColorWarningBg)).
		Bold(true).
		Border(lipgloss.RoundedBorder()).
		BorderForeground(lipgloss.Color(ColorWarning)).
		Padding(1, boxPadding).
		MarginTop(boxMargin).
		MarginBottom(boxMargin).
		Width(warningBoxWidth)

	helpStyle := lipgloss.NewStyle().
		Foreground(lipgloss.Color(ColorDarkGray)).
		Italic(true).
		MarginTop(1)

	warningText := m.getTCPWarningText(isVeryCompact)
	helpText := m.getTCPHelpText(isVeryCompact)

	var b strings.Builder
	b.WriteString(warningBoxStyle.Render(warningText))
	b.WriteString("\n\n")
	b.WriteString(helpStyle.Render(helpText))

	return b.String()
}

func (m *model) getTCPWarningText(isVeryCompact bool) string {
	if isVeryCompact {
		return "⚠️ TCP tunnels don't support custom subdomains."
	}
	return "⚠️ TCP tunnels cannot have custom subdomains. Only HTTP/HTTPS tunnels support subdomain customization."
}

func (m *model) getTCPHelpText(isVeryCompact bool) string {
	if isVeryCompact {
		return "Press any key to go back"
	}
	return "Press Enter or Esc to go back"
}

func (m *model) renderSlugRules(isVeryCompact, isCompact bool) string {
	boxPadding := getPaddingValue(isVeryCompact, isCompact)
	rulesBoxWidth := getResponsiveWidth(m.width, 10, 30, 60)

	rulesBoxStyle := lipgloss.NewStyle().
		Foreground(lipgloss.Color(ColorWhite)).
		Border(lipgloss.RoundedBorder()).
		BorderForeground(lipgloss.Color(ColorPrimary)).
		Padding(0, boxPadding).
		MarginTop(1).
		MarginBottom(1).
		Width(rulesBoxWidth)

	rulesContent := m.getRulesContent(isVeryCompact, isCompact)
	return rulesBoxStyle.Render(rulesContent) + "\n"
}

func (m *model) getRulesContent(isVeryCompact, isCompact bool) string {
	if isVeryCompact {
		return "Rules:\n3-20 chars\na-z, 0-9, -\nNo leading/trailing -"
	}

	if isCompact {
		return "📋 Rules:\n  • 3-20 chars\n  • a-z, 0-9, -\n  • No leading/trailing -"
	}

	return "📋 Rules: \n\t• 3-20 chars \n\t• a-z, 0-9, - \n\t• No leading/trailing -"
}

func (m *model) renderSlugInstruction(isVeryCompact bool) string {
	instructionStyle := lipgloss.NewStyle().
		Foreground(lipgloss.Color(ColorWhite)).
		MarginTop(1)

	instruction := "Enter your custom subdomain:"
	if isVeryCompact {
		instruction = "Custom subdomain:"
	}

	return instructionStyle.Render(instruction) + "\n"
}

func (m *model) renderSlugInput(isVeryCompact, isCompact bool) string {
	boxPadding := getPaddingValue(isVeryCompact, isCompact)
	boxMargin := getMarginValue(isCompact, 1, 2)

	if m.slugError != "" {
		return m.renderErrorInput(boxPadding, boxMargin)
	}

	return m.renderNormalInput(boxPadding, boxMargin)
}

func (m *model) renderErrorInput(boxPadding, boxMargin int) string {
	errorInputBoxStyle := lipgloss.NewStyle().
		Border(lipgloss.RoundedBorder()).
		BorderForeground(lipgloss.Color(ColorError)).
		Padding(1, boxPadding).
		MarginTop(boxMargin).
		MarginBottom(1)

	errorBoxStyle := lipgloss.NewStyle().
		Foreground(lipgloss.Color(ColorError)).
		Background(lipgloss.Color(ColorErrorBg)).
		Bold(true).
		Border(lipgloss.RoundedBorder()).
		BorderForeground(lipgloss.Color(ColorError)).
		Padding(0, boxPadding).
		MarginTop(1).
		MarginBottom(1)

	var b strings.Builder
	b.WriteString(errorInputBoxStyle.Render(m.slugInput.View()))
	b.WriteString("\n")
	b.WriteString(errorBoxStyle.Render("❌ " + m.slugError))
	b.WriteString("\n")

	return b.String()
}

func (m *model) renderNormalInput(boxPadding, boxMargin int) string {
	inputBoxStyle := lipgloss.NewStyle().
		Border(lipgloss.RoundedBorder()).
		BorderForeground(lipgloss.Color(ColorPrimary)).
		Padding(1, boxPadding).
		MarginTop(boxMargin).
		MarginBottom(boxMargin)

	return inputBoxStyle.Render(m.slugInput.View()) + "\n"
}

func (m *model) renderSlugPreview(isVeryCompact bool) string {
	previewURL := buildURL(m.protocol, m.slugInput.Value(), m.domain)
	previewWidth := getResponsiveWidth(m.width, 10, 30, 80)

	if isVeryCompact {
		previewURL = truncateString(previewURL, previewWidth-10)
	}

	previewStyle := lipgloss.NewStyle().
		Foreground(lipgloss.Color(ColorSecondary)).
		Italic(true).
		Width(previewWidth)

	return previewStyle.Render(fmt.Sprintf("Preview: %s", previewURL)) + "\n"
}

func (m *model) renderSlugHelp(isVeryCompact bool) string {
	helpStyle := lipgloss.NewStyle().
		Foreground(lipgloss.Color(ColorDarkGray)).
		Italic(true).
		MarginTop(1)

	helpText := "Press Enter to save • CTRL+R for random • Esc to cancel"
	if isVeryCompact {
		helpText = "Enter: save • CTRL+R: random • Esc: cancel"
	}

	return helpStyle.Render(helpText)
}

func getPaddingValue(isVeryCompact, isCompact bool) int {
	if isVeryCompact || isCompact {
		return 1
	}
	return 2
}
