package tui

import (
	"context"
	"fmt"
	"strings"

	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"

	"dbbackup/internal/config"
	"dbbackup/internal/logger"
)

// Style definitions
var (
	titleStyle = lipgloss.NewStyle().
			Bold(true).
			Foreground(lipgloss.Color("#FAFAFA")).
			Background(lipgloss.Color("#7D56F4")).
			Padding(0, 1)

	menuStyle = lipgloss.NewStyle().
			Foreground(lipgloss.Color("#626262"))

	menuSelectedStyle = lipgloss.NewStyle().
				Foreground(lipgloss.Color("#FF75B7")).
				Bold(true)

	infoStyle = lipgloss.NewStyle().
			Foreground(lipgloss.Color("#626262"))

	successStyle = lipgloss.NewStyle().
			Foreground(lipgloss.Color("#04B575")).
			Bold(true)

	errorStyle = lipgloss.NewStyle().
			Foreground(lipgloss.Color("#FF6B6B")).
			Bold(true)

	dbSelectorLabelStyle = lipgloss.NewStyle().
				Foreground(lipgloss.Color("#57C7FF")).
				Bold(true)
)

type dbTypeOption struct {
	label string
	value string
}

// MenuModel represents the simple menu state
type MenuModel struct {
	choices      []string
	cursor       int
	config       *config.Config
	logger       logger.Logger
	quitting     bool
	message      string
	dbTypes      []dbTypeOption
	dbTypeCursor int

	// Background operations
	ctx    context.Context
	cancel context.CancelFunc
}

func NewMenuModel(cfg *config.Config, log logger.Logger) MenuModel {
	ctx, cancel := context.WithCancel(context.Background())

	dbTypes := []dbTypeOption{
		{label: "PostgreSQL", value: "postgres"},
		{label: "MySQL / MariaDB", value: "mysql"},
	}

	dbCursor := 0
	if cfg.IsMySQL() {
		dbCursor = 1
	}

	model := MenuModel{
		choices: []string{
			"Single Database Backup",
			"Sample Database Backup (with ratio)",
			"Cluster Backup (all databases)",
			"View Active Operations",
			"Show Operation History",
			"Database Status & Health Check",
			"Configuration Settings",
			"Clear Operation History",
			"Quit",
		},
		config:       cfg,
		logger:       log,
		ctx:          ctx,
		cancel:       cancel,
		dbTypes:      dbTypes,
		dbTypeCursor: dbCursor,
	}

	return model
}

// Init initializes the model
func (m MenuModel) Init() tea.Cmd {
	return nil
}

// Update handles messages
func (m MenuModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.KeyMsg:
		switch msg.String() {
		case "ctrl+c", "q":
			if m.cancel != nil {
				m.cancel()
			}
			m.quitting = true
			return m, tea.Quit

		case "left", "h":
			if m.dbTypeCursor > 0 {
				m.dbTypeCursor--
				m.applyDatabaseSelection()
			}

		case "right", "l":
			if m.dbTypeCursor < len(m.dbTypes)-1 {
				m.dbTypeCursor++
				m.applyDatabaseSelection()
			}

		case "t":
			if len(m.dbTypes) > 0 {
				m.dbTypeCursor = (m.dbTypeCursor + 1) % len(m.dbTypes)
				m.applyDatabaseSelection()
			}

		case "up", "k":
			if m.cursor > 0 {
				m.cursor--
			}

		case "down", "j":
			if m.cursor < len(m.choices)-1 {
				m.cursor++
			}

		case "enter", " ":
			switch m.cursor {
			case 0: // Single Database Backup
				return m.handleSingleBackup()
			case 1: // Sample Database Backup
				return m.handleSampleBackup()
			case 2: // Cluster Backup
				return m.handleClusterBackup()
			case 3: // View Active Operations
				return m.handleViewOperations()
			case 4: // Show Operation History
				return m.handleOperationHistory()
			case 5: // Database Status
				return m.handleStatus()
			case 6: // Settings
				return m.handleSettings()
			case 7: // Clear History
				m.message = "🗑️ History cleared"
			case 8: // Quit
				if m.cancel != nil {
					m.cancel()
				}
				m.quitting = true
				return m, tea.Quit
			}
		}
	}

	return m, nil
}

// View renders the simple menu
func (m MenuModel) View() string {
	if m.quitting {
		return "Thanks for using DB Backup Tool!\n"
	}

	var s string

	// Header
	header := titleStyle.Render("🗄️  Database Backup Tool - Interactive Menu")
	s += fmt.Sprintf("\n%s\n\n", header)

	if len(m.dbTypes) > 0 {
		options := make([]string, len(m.dbTypes))
		for i, opt := range m.dbTypes {
			if m.dbTypeCursor == i {
				options[i] = menuSelectedStyle.Render(opt.label)
			} else {
				options[i] = menuStyle.Render(opt.label)
			}
		}
		selector := fmt.Sprintf("Target Engine: %s", strings.Join(options, menuStyle.Render("  |  ")))
		s += dbSelectorLabelStyle.Render(selector) + "\n"
		hint := infoStyle.Render("Switch with ←/→ or t • Cluster backup requires PostgreSQL")
		s += hint + "\n\n"
	}

	// Database info
	dbInfo := infoStyle.Render(fmt.Sprintf("Database: %s@%s:%d (%s)",
		m.config.User, m.config.Host, m.config.Port, m.config.DisplayDatabaseType()))
	s += fmt.Sprintf("%s\n\n", dbInfo)

	// Menu items
	for i, choice := range m.choices {
		cursor := " "
		if m.cursor == i {
			cursor = ">"
			s += menuSelectedStyle.Render(fmt.Sprintf("%s %s", cursor, choice))
		} else {
			s += menuStyle.Render(fmt.Sprintf("%s %s", cursor, choice))
		}
		s += "\n"
	}

	// Message area
	if m.message != "" {
		s += "\n" + m.message + "\n"
	}

	// Footer
	footer := infoStyle.Render("\n⌨️ Press ↑/↓ to navigate • Enter to select • q to quit")
	s += footer

	return s
}

// handleSingleBackup opens database selector for single backup
func (m MenuModel) handleSingleBackup() (tea.Model, tea.Cmd) {
	selector := NewDatabaseSelector(m.config, m.logger, m, "🗄️  Single Database Backup", "single")
	return selector, selector.Init()
}

// handleSampleBackup opens database selector for sample backup
func (m MenuModel) handleSampleBackup() (tea.Model, tea.Cmd) {
	selector := NewDatabaseSelector(m.config, m.logger, m, "📊 Sample Database Backup", "sample")
	return selector, selector.Init()
}

// handleClusterBackup shows confirmation and executes cluster backup
func (m MenuModel) handleClusterBackup() (tea.Model, tea.Cmd) {
	if !m.config.IsPostgreSQL() {
		m.message = errorStyle.Render("❌ Cluster backup is available only for PostgreSQL targets")
		return m, nil
	}
	confirm := NewConfirmationModel(m.config, m.logger, m,
		"🗄️  Cluster Backup",
		"This will backup ALL databases in the cluster. Continue?")
	return confirm, nil
}

// handleViewOperations shows active operations
func (m MenuModel) handleViewOperations() (tea.Model, tea.Cmd) {
	ops := NewOperationsView(m.config, m.logger, m)
	return ops, nil
}

// handleOperationHistory shows operation history
func (m MenuModel) handleOperationHistory() (tea.Model, tea.Cmd) {
	history := NewHistoryView(m.config, m.logger, m)
	return history, nil
}

// handleStatus shows database status
func (m MenuModel) handleStatus() (tea.Model, tea.Cmd) {
	status := NewStatusView(m.config, m.logger, m)
	return status, status.Init()
}

// handleSettings opens settings
func (m MenuModel) handleSettings() (tea.Model, tea.Cmd) {
	// Create and return the settings model
	settingsModel := NewSettingsModel(m.config, m.logger, m)
	return settingsModel, nil
}

func (m *MenuModel) applyDatabaseSelection() {
	if m == nil || len(m.dbTypes) == 0 {
		return
	}
	if m.dbTypeCursor < 0 || m.dbTypeCursor >= len(m.dbTypes) {
		return
	}

	selection := m.dbTypes[m.dbTypeCursor]
	if err := m.config.SetDatabaseType(selection.value); err != nil {
		m.message = errorStyle.Render(fmt.Sprintf("❌ %v", err))
		return
	}

	// Refresh default port if unchanged
	if m.config.Port == 0 {
		m.config.Port = m.config.GetDefaultPort()
	}

	m.message = successStyle.Render(fmt.Sprintf("🔀 Target database set to %s", m.config.DisplayDatabaseType()))
	if m.logger != nil {
		m.logger.Info("updated target database type", "type", m.config.DatabaseType, "port", m.config.Port)
	}
}

// RunInteractiveMenu starts the simple TUI
func RunInteractiveMenu(cfg *config.Config, log logger.Logger) error {
	m := NewMenuModel(cfg, log)
	p := tea.NewProgram(m)

	if _, err := p.Run(); err != nil {
		return fmt.Errorf("error running interactive menu: %w", err)
	}

	return nil
}
