package main

import (
	"fmt"
	"strings"

	tea "github.com/charmbracelet/bubbletea"
)

type mainTab int

const (
	tabDashboard mainTab = iota
	tabEditor
)

var mainTabNames = []string{"Dashboard", "Editor"}

type saveResultMsg struct {
	output string
	err    error
}

type Model struct {
	tab         mainTab
	dashboard   DashboardModel
	editor      EditorModel
	profile     *Profile
	profilePath string
	dirty       bool
	statusMsg   string
	errMsg      string
	width       int
	height      int
	quitting    bool
}

func NewModel() (Model, tea.Cmd) {
	profilePath, _ := DefaultProfilePath()
	p, err := LoadProfile(profilePath)
	if err != nil {
		p = &Profile{}
	}

	checks := RunChecks()

	m := Model{
		tab:         tabDashboard,
		dashboard:   NewDashboardModel(checks),
		editor:      NewEditorModel(p),
		profile:     p,
		profilePath: profilePath,
	}

	return m, nil
}

func (m Model) Init() tea.Cmd {
	return nil
}

func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.WindowSizeMsg:
		m.width = msg.Width
		m.height = msg.Height
		m.dashboard.width = msg.Width
		m.editor.width = msg.Width
		return m, nil

	case saveResultMsg:
		if msg.err != nil {
			m.errMsg = fmt.Sprintf("Save failed: %v", msg.err)
		} else {
			m.dirty = false
			m.statusMsg = "Saved & validated: " + msg.output
			m.errMsg = ""
		}
		return m, nil

	case tea.KeyMsg:
		switch msg.String() {
		case "ctrl+c", "q":
			if m.dirty {
				m.statusMsg = "Unsaved changes! Press Q to force quit, or s to save."
				return m, nil
			}
			m.quitting = true
			return m, tea.Quit
		case "Q":
			m.quitting = true
			return m, tea.Quit
		case "tab":
			if m.tab == tabDashboard {
				m.tab = tabEditor
			} else {
				m.tab = tabDashboard
			}
			m.statusMsg = ""
			m.errMsg = ""
			return m, nil
		case "s":
			if m.tab == tabEditor {
				m.editor.SyncToProfile(m.profile)
				cmd := saveAndValidateCmd(m.profilePath, m.profile)
				m.statusMsg = "Saving..."
				return m, cmd
			}
		}
	}

	switch m.tab {
	case tabDashboard:
		var cmd tea.Cmd
		m.dashboard, cmd = m.dashboard.Update(msg)
		return m, cmd
	case tabEditor:
		var cmd tea.Cmd
		m.editor, cmd = m.editor.Update(msg)
		if !m.dirty {
			m.dirty = true
		}
		return m, cmd
	}

	return m, nil
}

func (m Model) View() string {
	if m.quitting {
		return ""
	}

	var b strings.Builder

	title := "nono-tui"
	if m.dirty {
		title += " *"
	}
	b.WriteString(titleStyle.Render(" " + title + " "))

	tabs := []string{}
	for i, name := range mainTabNames {
		if mainTab(i) == m.tab {
			tabs = append(tabs, activeTabStyle.Render(name))
		} else {
			tabs = append(tabs, tabStyle.Render(name))
		}
	}
	b.WriteString("  " + strings.Join(tabs, " "))

	b.WriteString("\n\n")

	switch m.tab {
	case tabDashboard:
		b.WriteString(m.dashboard.View())
	case tabEditor:
		b.WriteString(m.editor.View())
	}

	b.WriteString("\n\n")

	if m.errMsg != "" {
		b.WriteString(errorStyle.Render("  " + m.errMsg))
	} else if m.statusMsg != "" {
		b.WriteString(successStyle.Render("  " + m.statusMsg))
	} else {
		b.WriteString(helpStyle.Render("  q:quit  Tab:switch tabs"))
	}

	return b.String()
}
