package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

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

// Message types
type (
	logFilesLoadedMsg     struct{ logFiles []LogFile }
	fileContentLoadedMsg  struct{ content string }
	backupDetailsLoadedMsg struct{ details BackupDetails }
	errorMsg              struct{ error string }
)

// BackupDirectory represents a backup service directory
type BackupDirectory struct {
	Name         string    `json:"name"`
	Path         string    `json:"path"`
	FileCount    int       `json:"file_count"`
	TotalSize    int64     `json:"total_size"`
	LastModified time.Time `json:"last_modified"`
	Description  string    `json:"description"`
}

// BackupFile represents an individual backup file
type BackupFile struct {
	Name         string    `json:"name"`
	Path         string    `json:"path"`
	Size         int64     `json:"size"`
	ModifiedTime time.Time `json:"modified_time"`
	IsCompressed bool      `json:"is_compressed"`
	Service      string    `json:"service"`
}

// LogFile represents a log file
type LogFile struct {
	Name         string    `json:"name"`
	Path         string    `json:"path"`
	Size         int64     `json:"size"`
	Date         time.Time `json:"date"`
	Service      string    `json:"service"`
	Content      string    `json:"content,omitempty"`
}

// BackupDetails represents detailed information about a backup
type BackupDetails struct {
	Directory    BackupDirectory `json:"directory"`
	Files        []BackupFile    `json:"files"`
	TotalFiles   int             `json:"total_files"`
	TotalSize    int64           `json:"total_size"`
	OldestBackup time.Time       `json:"oldest_backup"`
	NewestBackup time.Time       `json:"newest_backup"`
}

// LogEntry represents a log entry from backup operations
type LogEntry struct {
	Timestamp time.Time `json:"timestamp"`
	Service   string    `json:"service"`
	Level     string    `json:"level"`
	Message   string    `json:"message"`
}

// BackupItem represents a backup service directory or view option in the list
type BackupItem struct {
	title       string
	description string
	itemType    string // "directory", "logs", "about"
	path        string // path to backup directory or logs
	service     string
}

func (i BackupItem) FilterValue() string { return i.title }
func (i BackupItem) Title() string       { return i.title }
func (i BackupItem) Description() string { return i.description }

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

	statusBarStyle = lipgloss.NewStyle().
			Foreground(lipgloss.AdaptiveColor{Light: "#343433", Dark: "#C1C6B2"}).
			Background(lipgloss.AdaptiveColor{Light: "#D9DCCF", Dark: "#353533"})

	idleStyle    = lipgloss.NewStyle().Foreground(lipgloss.Color("#6B7280"))

	// Style for the selected item in the list
	selectedItemStyle = lipgloss.NewStyle().
				Foreground(lipgloss.Color("170")).
				Background(lipgloss.Color("57"))

	docStyle = lipgloss.NewStyle().Margin(1, 2)
)

// Key bindings
type keyMap struct {
	Up         key.Binding
	Down       key.Binding
	Left       key.Binding
	Right      key.Binding
	Help       key.Binding
	Quit       key.Binding
	Enter      key.Binding
	Tab        key.Binding
	Escape     key.Binding
	Refresh    key.Binding
	ViewLogs   key.Binding
	ViewStatus key.Binding
	ViewConfig key.Binding
	Clear      key.Binding
}

func (k keyMap) ShortHelp() []key.Binding {
	return []key.Binding{k.Help, k.Quit}
}

func (k keyMap) FullHelp() [][]key.Binding {
	return [][]key.Binding{
		{k.Up, k.Down, k.Enter},
		{k.Tab, k.ViewLogs, k.ViewStatus, k.ViewConfig},
		{k.Refresh, k.Clear},
		{k.Help, k.Quit},
	}
}

var keys = keyMap{
	Up: key.NewBinding(
		key.WithKeys("up", "k"),
		key.WithHelp("↑/k", "move up"),
	),
	Down: key.NewBinding(
		key.WithKeys("down", "j"),
		key.WithHelp("↓/j", "move down"),
	),
	Left: key.NewBinding(
		key.WithKeys("left", "h"),
		key.WithHelp("←/h", "move left"),
	),
	Right: key.NewBinding(
		key.WithKeys("right", "l"),
		key.WithHelp("→/l", "move right"),
	),
	Help: key.NewBinding(
		key.WithKeys("?"),
		key.WithHelp("?", "toggle help"),
	),
	Quit: key.NewBinding(
		key.WithKeys("q", "ctrl+c"),
		key.WithHelp("q", "quit"),
	),
	Enter: key.NewBinding(
		key.WithKeys("enter", " "),
		key.WithHelp("enter", "browse directory"),
	),
	Tab: key.NewBinding(
		key.WithKeys("tab"),
		key.WithHelp("tab", "switch panel"),
	),
	Escape: key.NewBinding(
		key.WithKeys("esc"),
		key.WithHelp("esc", "back"),
	),
	Refresh: key.NewBinding(
		key.WithKeys("r"),
		key.WithHelp("r", "refresh"),
	),
	ViewLogs: key.NewBinding(
		key.WithKeys("v"),
		key.WithHelp("v", "view logs"),
	),
	ViewStatus: key.NewBinding(
		key.WithKeys("s"),
		key.WithHelp("s", "view status"),
	),
	ViewConfig: key.NewBinding(
		key.WithKeys("f"),
		key.WithHelp("f", "view config"),
	),
	Clear: key.NewBinding(
		key.WithKeys("c"),
		key.WithHelp("c", "clear output"),
	),
}

// Model represents the application state
type Model struct {
	list            list.Model
	viewport        viewport.Model
	keys            keyMap
	width           int
	height          int
	activePanel     int // 0: list, 1: viewport, 2: status
	showHelp        bool
	ready           bool
	logs            []LogEntry
	shellPath       string
	items           []BackupItem // Store backup items for reference
	currentView     string // "main", "logs", "status", "directory"
	currentDirPath  string // Path of currently viewed directory for refresh
}

// Initialize the model
func initialModel() Model {
	// Get the shell path (parent directory of tui)
	shellPath, _ := filepath.Abs(filepath.Dir(os.Args[0]) + "/..")

	// Create backup directory viewer items
	backupBasePath := "/mnt/share/media/backups"
	items := []list.Item{
		BackupItem{
			title:       "📦 Plex Backups",
			description: "Browse Plex Media Server backup files and history",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "plex"),
			service:     "plex",
		},
		BackupItem{
			title:       "🖼️ Immich Backups",
			description: "Browse Immich photo management backup files",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "immich"),
			service:     "immich",
		},
		BackupItem{
			title:       "🎬 Sonarr Backups",
			description: "Browse Sonarr TV series management backups",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "sonarr"),
			service:     "sonarr",
		},
		BackupItem{
			title:       "🎭 Radarr Backups",
			description: "Browse Radarr movie management backups",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "radarr"),
			service:     "radarr",
		},
		BackupItem{
			title:       "🔍 Prowlarr Backups",
			description: "Browse Prowlarr indexer management backups",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "prowlarr"),
			service:     "prowlarr",
		},
		BackupItem{
			title:       "🎯 Jellyseerr Backups",
			description: "Browse Jellyseerr request management backups",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "jellyseerr"),
			service:     "jellyseerr",
		},
		BackupItem{
			title:       "📥 SABnzbd Backups",
			description: "Browse SABnzbd download client backups",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "sabnzbd"),
			service:     "sabnzbd",
		},
		BackupItem{
			title:       "📊 Tautulli Backups",
			description: "Browse Tautulli Plex statistics backups",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "tautulli"),
			service:     "tautulli",
		},
		BackupItem{
			title:       "📚 Audiobookshelf Backups",
			description: "Browse Audiobookshelf audiobook server backups",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "audiobookshelf"),
			service:     "audiobookshelf",
		},
		BackupItem{
			title:       "🐳 Docker Data Backups",
			description: "Browse Docker container data and volumes",
			itemType:    "directory",
			path:        filepath.Join(backupBasePath, "docker-data"),
			service:     "docker-data",
		},
		BackupItem{
			title:       "📋 Backup Logs",
			description: "View backup operation logs and history",
			itemType:    "logs",
			path:        filepath.Join(backupBasePath, "logs"),
			service:     "logs",
		},
	}

	const defaultWidth = 20

	l := list.New(items, BackupItemDelegate{}, defaultWidth, 14)
	l.Title = "Backup Manager"
	l.SetShowStatusBar(false)
	l.SetFilteringEnabled(false)
	l.Styles.Title = titleStyle
	l.Styles.PaginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4)
	l.Styles.HelpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1)

	vp := viewport.New(78, 20)
	vp.SetContent("Welcome to Backup File Browser!\n\nSelect a backup directory from the list and press Enter to browse backup files.\n\nUse 'v' to view logs, 'r' to refresh status, and 'tab' to switch between panels.")

	return Model{
		list:           l,
		viewport:       vp,
		keys:           keys,
		activePanel:    0,
		showHelp:       false,
		ready:          false,
		logs:           []LogEntry{},
		shellPath:      shellPath,
		items:          convertToBackupItems(items), // Store the items
		currentView:    "main",
	}
}

// BackupItemDelegate for custom rendering
type BackupItemDelegate struct{}

func (d BackupItemDelegate) Height() int                             { return 1 }
func (d BackupItemDelegate) Spacing() int                            { return 0 }
func (d BackupItemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil }
func (d BackupItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
	i, ok := listItem.(BackupItem)
	if !ok {
		return
	}

	itemTitle := fmt.Sprintf("%d. %s", index+1, i.title)

	if index == m.Index() {
		fmt.Fprint(w, selectedItemStyle.Render("> "+itemTitle))
	} else {
		// Add leading spaces to align with the selected item's "> " prefix
		fmt.Fprint(w, idleStyle.Render("  "+itemTitle))
	}
}

// Helper function to convert list items to BackupItems
func convertToBackupItems(items []list.Item) []BackupItem {
	backupItems := make([]BackupItem, len(items))
	for i, item := range items {
		if bi, ok := item.(BackupItem); ok {
			backupItems[i] = bi
		}
	}
	return backupItems
}

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

func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	var cmd tea.Cmd
	var cmds []tea.Cmd

	switch msg := msg.(type) {
	case tea.WindowSizeMsg:
		m.width = msg.Width
		m.height = msg.Height

		if !m.ready {
			// Since this program can be run in a variety of terminals and
			// we want to ensure the viewport takes up the right amount of space,
			// we calculate the viewport height based on the terminal height.
			m.viewport.Width = msg.Width - 4
			m.viewport.Height = msg.Height - 10
			m.ready = true

			// Show description for the first selected item instead of generic welcome
			if len(m.items) > 0 {
				m.showItemDescription()
			} else {
				m.viewport.SetContent("Welcome to Backup File Browser!\n\nSelect a backup directory from the list and press Enter to browse backup files.\n\nUse 'v' to view logs, 's' to view status, and 'tab' to switch between panels.")
			}
		} else {
			m.viewport.Width = msg.Width - 4
			m.viewport.Height = msg.Height - 10
		}

		h, v := docStyle.GetFrameSize()
		m.list.SetSize(msg.Width-h, msg.Height-v)

	case tea.KeyMsg:
		switch {
		case key.Matches(msg, m.keys.Quit):
			return m, tea.Quit

		case key.Matches(msg, m.keys.Tab):
			m.activePanel = (m.activePanel + 1) % 2

		case key.Matches(msg, m.keys.Refresh):
			// Refresh current view
			switch m.currentView {
			case "main":
				if len(m.items) > 0 {
					m.showItemDescription()
				}
			case "directory":
				// Reload the current directory
				if m.currentDirPath != "" {
					cmds = append(cmds, m.loadBackupDirectory(m.currentDirPath))
				}
			case "logs":
				// Reload log files
				cmds = append(cmds, m.loadLogFiles())
			}

		case key.Matches(msg, m.keys.ViewLogs):
			m.showLogs()
			m.currentView = "logs"

		case key.Matches(msg, m.keys.ViewStatus):
			m.showStatus()
			m.currentView = "status"

		case key.Matches(msg, m.keys.ViewConfig):
			m.showConfig()
			m.currentView = "config"

		case key.Matches(msg, m.keys.Clear):
			m.viewport.SetContent("Output cleared.\n\nSelect a backup directory from the list and press Enter to browse.")
			m.currentView = "main"
			m.currentDirPath = "" // Clear directory path
			// Show description for currently selected item
			m.showItemDescription()

		case key.Matches(msg, m.keys.Escape) && m.currentView != "main":
			m.viewport.SetContent("Welcome to Backup File Browser!\n\nSelect a backup directory from the list and press Enter to browse.\n\nUse 'v' to view logs, 's' for status, and 'tab' to switch between panels.")
			m.currentView = "main"
			m.currentDirPath = "" // Clear directory path
			// Show description for currently selected item
			m.showItemDescription()

		case key.Matches(msg, m.keys.Enter) && m.activePanel == 0:
			if i, ok := m.list.SelectedItem().(BackupItem); ok {
				switch i.itemType {
				case "directory":
					// Store the directory path for refresh functionality
					m.currentDirPath = i.path
					// Load backup directory details
					cmds = append(cmds, m.loadBackupDirectory(i.path))
				case "logs":
					// Load log files
					cmds = append(cmds, m.loadLogFiles())
				default:
					// Show item description for other types
					m.showItemDescription()
				}
			}

		case key.Matches(msg, m.keys.Help):
			m.showHelp = !m.showHelp
		}

		// Update the focused component (CRITICAL: this must be outside the switch)
		prevIndex := m.list.Index()
		if m.activePanel == 0 {
			m.list, cmd = m.list.Update(msg)
			// Check if selection changed and we're in main view
			if m.list.Index() != prevIndex && m.currentView == "main" {
				m.showItemDescription()
			}
		} else {
			m.viewport, cmd = m.viewport.Update(msg)
		}
		cmds = append(cmds, cmd)

	case backupDetailsLoadedMsg:
		m.showBackupDetails(msg.details)
		m.currentView = "directory"

	case logFilesLoadedMsg:
		m.showLogFiles(msg.logFiles)
		m.currentView = "logs"

	case fileContentLoadedMsg:
		m.viewport.SetContent(msg.content)
		m.currentView = "file"

	case errorMsg:
		m.viewport.SetContent(fmt.Sprintf("Error: %s", msg.error))
		m.currentView = "error"
	}

	return m, tea.Batch(cmds...)
}



func (m Model) View() string {
	if !m.ready {
		return "\n  Initializing..."
	}

	// Create status bar
	statusBar := m.createStatusBar()

	// Create help section
	helpText := ""
	if m.showHelp {
		help := m.keys.FullHelp()
		var helpLines []string
		for i, group := range help {
			var groupHelp []string
			for _, binding := range group {
				groupHelp = append(groupHelp, fmt.Sprintf("%s: %s", binding.Help().Key, binding.Help().Desc))
			}
			helpLines = append(helpLines, strings.Join(groupHelp, " | "))
			if i < len(help)-1 {
				helpLines = append(helpLines, "")
			}
		}
		helpText = "\n" + strings.Join(helpLines, "\n")
	}

	// Create viewport style based on active panel and current view
	viewportStyle := lipgloss.NewStyle().Border(lipgloss.RoundedBorder())
	if m.activePanel == 1 {
		viewportStyle = viewportStyle.BorderStyle(lipgloss.ThickBorder()).BorderForeground(lipgloss.Color("#7D56F4"))
	}

	// Add view indicator to viewport title
	viewportTitle := ""
	switch m.currentView {
	case "logs":
		viewportTitle = "📋 Backup Logs"
	case "status":
		viewportTitle = "📊 Backup Status"
	case "config":
		viewportTitle = "⚙️ Configuration"
	default:
		viewportTitle = "💻 Output"
	}

	// Layout based on active panel
	return lipgloss.JoinVertical(lipgloss.Left,
		titleStyle.Render("🔧 Media & Plex Backup Manager"),
		lipgloss.JoinHorizontal(lipgloss.Top,
			lipgloss.NewStyle().
				Border(lipgloss.RoundedBorder()).
				BorderForeground(func() lipgloss.Color {
					if m.activePanel == 0 {
						return lipgloss.Color("#7D56F4")
					}
					return lipgloss.Color("#444444")
				}()).
				Width(50).
				Render(m.list.View()),
			viewportStyle.
				Width(m.width-54).
				Render(lipgloss.JoinVertical(lipgloss.Left,
					lipgloss.NewStyle().
						Foreground(lipgloss.Color("#7D56F4")).
						Bold(true).
						Render(viewportTitle),
					m.viewport.View(),
				)),
		),
		statusBar,
		helpText,
	)
}

func (m Model) createStatusBar() string {
	var parts []string

	// Add current view indicator
	viewIndicator := fmt.Sprintf("View: %s", strings.ToUpper(m.currentView))
	parts = append(parts, idleStyle.Render(viewIndicator))

	// Add file browser status
	parts = append(parts, idleStyle.Render("Mode: Browse Only"))

	// Add navigation help
	if m.activePanel == 0 {
		parts = append(parts, "Panel: Backup List (Press Tab to switch)")
	} else {
		parts = append(parts, "Panel: Output (Press Tab to switch)")
	}

	return statusBarStyle.Render(strings.Join(parts, " | "))
}

func (m *Model) showLogs() {
	var content strings.Builder
	content.WriteString("=== BACKUP LOGS ===\n\n")

	if len(m.logs) == 0 {
		content.WriteString("No logs available.\n")
	} else {
		// Sort logs by timestamp (newest first)
		sort.Slice(m.logs, func(i, j int) bool {
			return m.logs[i].Timestamp.After(m.logs[j].Timestamp)
		})

		for _, entry := range m.logs {
			timestamp := entry.Timestamp.Format("2006-01-02 15:04:05")
			content.WriteString(fmt.Sprintf("[%s] %s - %s: %s\n",
				timestamp, entry.Service, entry.Level, entry.Message))
		}
	}

	m.viewport.SetContent(content.String())
}

func (m *Model) showStatus() {
	var content strings.Builder
	content.WriteString("=== BACKUP DIRECTORY STATUS ===\n\n")

	content.WriteString("📂 Available Backup Directories:\n\n")

	for _, item := range m.items {
		if item.itemType == "directory" {
			content.WriteString(fmt.Sprintf("🔧 Service: %s\n", strings.ToUpper(item.service)))
			content.WriteString(fmt.Sprintf("   Path: %s\n", item.path))
			content.WriteString("   Type: Backup Directory\n")
			content.WriteString("   Status: Available for browsing\n")
			content.WriteString("\n")
		}
	}

	content.WriteString("📊 SUMMARY:\n")
	directoryCount := 0
	for _, item := range m.items {
		if item.itemType == "directory" {
			directoryCount++
		}
	}
	content.WriteString(fmt.Sprintf("   Available Directories: %d\n", directoryCount))
	content.WriteString("   Mode: Read-Only Browser\n")

	m.viewport.SetContent(content.String())
}

func (m *Model) showConfig() {
	var content strings.Builder
	content.WriteString("=== BACKUP CONFIGURATION ===\n\n")

	// System Information
	content.WriteString("🖥️ SYSTEM INFO:\n")
	content.WriteString(fmt.Sprintf("   Shell Path: %s\n", m.shellPath))
	content.WriteString(fmt.Sprintf("   Terminal Size: %dx%d\n", m.width, m.height))
	content.WriteString(fmt.Sprintf("   Active Services: %d\n", len(m.items)))
	content.WriteString("\n")

	// Available Backup Services
	content.WriteString("📦 AVAILABLE SERVICES:\n")
	for i, item := range m.items {
		content.WriteString(fmt.Sprintf("   %d. %s\n", i+1, strings.TrimPrefix(item.title, "📦 ")))
		content.WriteString(fmt.Sprintf("      Type: %s\n", item.itemType))
		content.WriteString(fmt.Sprintf("      Path: %s\n", item.path))
		content.WriteString(fmt.Sprintf("      Service: %s\n", item.service))

		// Check if path exists
		if _, err := os.Stat(item.path); os.IsNotExist(err) {
			content.WriteString("      ⚠️ Status: Path not found\n")
		} else {
			content.WriteString("      ✅ Status: Available\n")
		}
		content.WriteString("\n")
	}

	// Key Bindings Summary
	content.WriteString("⌨️ KEY BINDINGS:\n")
	content.WriteString("   Navigation: ↑/↓ or k/j (move), Tab (switch panels)\n")
	content.WriteString("   Actions: Enter (browse), x (back), c (clear)\n")
	content.WriteString("   Views: v (logs), s (status), f (config)\n")
	content.WriteString("   System: r (refresh), ? (help), q (quit)\n\n")

	// Performance Tips
	content.WriteString("💡 TIPS:\n")
	content.WriteString("   • Browse backup directories with Enter\n")
	content.WriteString("   • Check 's' for detailed status information\n")
	content.WriteString("   • Use 'x' to go back to main view\n")

	m.viewport.SetContent(content.String())
}

// showItemDescription displays detailed information about the currently selected menu item
func (m *Model) showItemDescription() {
	// Use the list's actual selection index instead of a separate field
	selectedIndex := m.list.Index()
	if selectedIndex < 0 || selectedIndex >= len(m.items) {
		return
	}

	item := m.items[selectedIndex]

	var content strings.Builder
	content.WriteString(fmt.Sprintf("📋 %s\n", item.title))
	content.WriteString(strings.Repeat("=", len(item.title)+3) + "\n\n")

	content.WriteString(fmt.Sprintf("📝 Description:\n%s\n\n", item.description))

	// Add detailed information based on service type
	switch item.service {
	case "plex":
		content.WriteString("🎬 Plex Media Server Backups:\n")
		content.WriteString("• Database and metadata backups\n")
		content.WriteString("• Configuration and preferences\n")
		content.WriteString("• Plugin and custom data\n")
		content.WriteString("• Compressed archive files (.tar.gz)\n\n")

		content.WriteString("📁 Typical Contents:\n")
		content.WriteString("• Library database files\n")
		content.WriteString("• User preferences and settings\n")
		content.WriteString("• Custom artwork and thumbnails\n")
		content.WriteString("• Plugin configurations\n\n")

	case "immich":
		content.WriteString("📸 Immich Photo Management Backups:\n")
		content.WriteString("• PostgreSQL database dumps\n")
		content.WriteString("• Uploaded photos and videos\n")
		content.WriteString("• User settings and albums\n")
		content.WriteString("• Machine learning models\n\n")

		content.WriteString("📁 Typical Contents:\n")
		content.WriteString("• Database backup files (.sql)\n")
		content.WriteString("• Media file archives\n")
		content.WriteString("• Configuration backups\n")
		content.WriteString("• Thumbnail caches\n\n")

	case "sonarr":
		content.WriteString("📺 Sonarr TV Series Management:\n")
		content.WriteString("• Series tracking database\n")
		content.WriteString("• Download client configurations\n")
		content.WriteString("• Quality profiles and settings\n")
		content.WriteString("• Custom scripts and metadata\n\n")

	case "radarr":
		content.WriteString("🎬 Radarr Movie Management:\n")
		content.WriteString("• Movie collection database\n")
		content.WriteString("• Indexer and download settings\n")
		content.WriteString("• Quality and format preferences\n")
		content.WriteString("• Custom filters and lists\n\n")

	case "prowlarr":
		content.WriteString("🔍 Prowlarr Indexer Management:\n")
		content.WriteString("• Indexer configurations\n")
		content.WriteString("• API keys and credentials\n")
		content.WriteString("• Sync profiles and settings\n")
		content.WriteString("• Application mappings\n\n")

	case "jellyseerr":
		content.WriteString("🎯 Jellyseerr Request Management:\n")
		content.WriteString("• User request history\n")
		content.WriteString("• Notification configurations\n")
		content.WriteString("• Integration settings\n")
		content.WriteString("• Custom user permissions\n\n")

	case "sabnzbd":
		content.WriteString("📥 SABnzbd Download Client:\n")
		content.WriteString("• Server and category configs\n")
		content.WriteString("• Download queue history\n")
		content.WriteString("• Post-processing scripts\n")
		content.WriteString("• User settings and passwords\n\n")

	case "tautulli":
		content.WriteString("📊 Tautulli Plex Statistics:\n")
		content.WriteString("• View history and statistics\n")
		content.WriteString("• User activity tracking\n")
		content.WriteString("• Notification configurations\n")
		content.WriteString("• Custom dashboard settings\n\n")

	case "audiobookshelf":
		content.WriteString("📚 Audiobookshelf Server:\n")
		content.WriteString("• Library and user data\n")
		content.WriteString("• Listening progress tracking\n")
		content.WriteString("• Playlist and collection info\n")
		content.WriteString("• Server configuration\n\n")

	case "docker-data":
		content.WriteString("🐳 Docker Container Data:\n")
		content.WriteString("• Volume and bind mount backups\n")
		content.WriteString("• Container persistent data\n")
		content.WriteString("• Application state files\n")
		content.WriteString("• Configuration volumes\n\n")

	case "logs":
		content.WriteString("📋 Backup Operation Logs:\n")
		content.WriteString("• Daily backup operation logs\n")
		content.WriteString("• Error and success reports\n")
		content.WriteString("• Backup timing and performance\n")
		content.WriteString("• System health monitoring\n\n")
	}

	// Add usage instructions based on item type
	content.WriteString("\n🚀 Actions:\n")
	switch item.itemType {
	case "directory":
		content.WriteString("• Press Enter to browse backup files\n")
		content.WriteString("• View file sizes and modification dates\n")
		content.WriteString("• Check backup history and trends\n")
		content.WriteString("• Navigate with arrow keys\n")
	case "logs":
		content.WriteString("• Press Enter to view log files\n")
		content.WriteString("• Browse by date and time\n")
		content.WriteString("• View backup operation details\n")
		content.WriteString("• Check for errors or warnings\n")
	}

	content.WriteString("\n💡 Navigation:\n")
	content.WriteString("• Tab: Switch between panels\n")
	content.WriteString("• r: Refresh current view\n")
	content.WriteString("• ?: Toggle help\n")
	content.WriteString("• q: Quit application\n")

	// Add path information
	content.WriteString(fmt.Sprintf("\n📁 Path: %s\n", item.path))

	m.viewport.SetContent(content.String())
}

// showBackupDetails displays detailed information about backup files in a directory
func (m *Model) showBackupDetails(details BackupDetails) {
	var content strings.Builder
	content.WriteString(fmt.Sprintf("📁 %s Backup Directory\n", details.Directory.Name))
	content.WriteString(strings.Repeat("=", len(details.Directory.Name)+20) + "\n\n")

	// Directory summary
	content.WriteString("📊 Directory Summary:\n")
	content.WriteString(fmt.Sprintf("   📁 Path: %s\n", details.Directory.Path))

	// Show if this is using a scheduled subfolder
	if strings.HasSuffix(details.Directory.Path, "/scheduled") {
		content.WriteString("   📅 Source: Scheduled backups (from 'scheduled' subfolder)\n")
	}

	content.WriteString(fmt.Sprintf("   📄 Files: %d\n", details.TotalFiles))
	content.WriteString(fmt.Sprintf("   💾 Total Size: %s\n", formatSize(details.TotalSize)))

	if !details.NewestBackup.IsZero() {
		content.WriteString(fmt.Sprintf("   🕒 Newest: %s\n", details.NewestBackup.Format("2006-01-02 15:04:05")))
	}
	if !details.OldestBackup.IsZero() {
		content.WriteString(fmt.Sprintf("   📅 Oldest: %s\n", details.OldestBackup.Format("2006-01-02 15:04:05")))
	}
	content.WriteString("\n")

	// File listings
	if len(details.Files) > 0 {
		content.WriteString("📄 Backup Files:\n")
		content.WriteString("   Name                          Size       Modified\n")
		content.WriteString("   " + strings.Repeat("-", 50) + "\n")

		for _, file := range details.Files {
			// Truncate filename if too long
			displayName := file.Name
			if len(displayName) > 25 {
				displayName = displayName[:22] + "..."
			}

			compressionIndicator := ""
			if file.IsCompressed {
				compressionIndicator = "📦 "
			}

			content.WriteString(fmt.Sprintf("   %s%-25s %8s   %s\n",
				compressionIndicator,
				displayName,
				formatSize(file.Size),
				file.ModifiedTime.Format("2006-01-02 15:04")))
		}
	} else {
		content.WriteString("📂 No backup files found in this directory.\n")
	}

	content.WriteString("\n💡 Navigation:\n")
	content.WriteString("   • x: Return to main view\n")
	content.WriteString("   • r: Refresh directory listing\n")
	content.WriteString("   • ?: Toggle help\n")

	m.viewport.SetContent(content.String())
}

// showLogFiles displays log files for browsing
func (m *Model) showLogFiles(logFiles []LogFile) {
	var content strings.Builder
	content.WriteString("📋 Backup Operation Logs\n")
	content.WriteString("=========================\n\n")

	if len(logFiles) == 0 {
		content.WriteString("📂 No log files found.\n")
		content.WriteString("Log files are typically stored in /mnt/share/media/backups/logs/\n")
	} else {
		content.WriteString("📄 Available Log Files:\n")
		content.WriteString("   Filename                     Size      Date\n")
		content.WriteString("   " + strings.Repeat("-", 45) + "\n")

		for _, logFile := range logFiles {
			displayName := logFile.Name
			if len(displayName) > 25 {
				displayName = displayName[:22] + "..."
			}

			dateStr := "Unknown"
			if !logFile.Date.IsZero() {
				dateStr = logFile.Date.Format("2006-01-02 15:04")
			}

			content.WriteString(fmt.Sprintf("   %-25s %8s   %s\n",
				displayName,
				formatSize(logFile.Size),
				dateStr))
		}

		content.WriteString(fmt.Sprintf("\n📊 Total: %d log files\n", len(logFiles)))
	}

	content.WriteString("\n💡 Navigation:\n")
	content.WriteString("   • Enter: View log content (when a specific log is selected)\n")
	content.WriteString("   • x: Return to main view\n")
	content.WriteString("   • r: Refresh log listing\n")

	m.viewport.SetContent(content.String())
}

// formatSize converts bytes to human readable format
func formatSize(bytes int64) string {
	const unit = 1024
	if bytes < unit {
		return fmt.Sprintf("%d B", bytes)
	}
	div, exp := int64(unit), 0
	for n := bytes / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
}

// loadBackupDirectory loads backup files from a directory
func (m *Model) loadBackupDirectory(dirPath string) tea.Cmd {
	return func() tea.Msg {
		// Check if there's a "scheduled" subfolder - if so, use that instead
		scheduledPath := filepath.Join(dirPath, "scheduled")
		actualPath := dirPath

		if info, err := os.Stat(scheduledPath); err == nil && info.IsDir() {
			actualPath = scheduledPath
		}

		files, err := os.ReadDir(actualPath)
		if err != nil {
			return errorMsg{error: fmt.Sprintf("Failed to read directory %s: %v", actualPath, err)}
		}

		var backupFiles []BackupFile
		var totalSize int64
		var lastModified time.Time

		for _, file := range files {
			if file.IsDir() {
				continue
			}

			info, err := file.Info()
			if err != nil {
				continue
			}

			backupFile := BackupFile{
				Name:         file.Name(),
				Path:         filepath.Join(actualPath, file.Name()),
				Size:         info.Size(),
				ModifiedTime: info.ModTime(),
				IsCompressed: strings.HasSuffix(file.Name(), ".tar.gz") || strings.HasSuffix(file.Name(), ".zip"),
				Service:      filepath.Base(dirPath), // Keep using original dirPath for service name
			}

			backupFiles = append(backupFiles, backupFile)
			totalSize += info.Size()

			if info.ModTime().After(lastModified) {
				lastModified = info.ModTime()
			}
		}

		// Sort files by modification time (newest first)
		sort.Slice(backupFiles, func(i, j int) bool {
			return backupFiles[i].ModifiedTime.After(backupFiles[j].ModifiedTime)
		})

		var oldestBackup, newestBackup time.Time
		if len(backupFiles) > 0 {
			newestBackup = backupFiles[0].ModifiedTime
			oldestBackup = backupFiles[len(backupFiles)-1].ModifiedTime
		}

		details := BackupDetails{
			Directory: BackupDirectory{
				Name:         filepath.Base(dirPath),
				Path:         actualPath, // Show the actual path where files are located
				FileCount:    len(backupFiles),
				TotalSize:    totalSize,
				LastModified: lastModified,
			},
			Files:        backupFiles,
			TotalFiles:   len(backupFiles),
			TotalSize:    totalSize,
			OldestBackup: oldestBackup,
			NewestBackup: newestBackup,
		}

		return backupDetailsLoadedMsg{details: details}
	}
}

// loadLogFiles loads log files from the logs directory
func (m *Model) loadLogFiles() tea.Cmd {
	return func() tea.Msg {
		logsPath := "/mnt/share/media/backups/logs"
		files, err := os.ReadDir(logsPath)
		if err != nil {
			return errorMsg{error: fmt.Sprintf("Failed to read logs directory: %v", err)}
		}

		var logFiles []LogFile

		for _, file := range files {
			if file.IsDir() {
				continue
			}

			info, err := file.Info()
			if err != nil {
				continue
			}

			// Parse log file name to extract date and service
			name := file.Name()
			var logDate time.Time
			var service string

			// Parse backup_log_YYYYMMDD_HHMMSS.md format
			if strings.HasPrefix(name, "backup_log_") && strings.HasSuffix(name, ".md") {
				datePart := strings.TrimPrefix(name, "backup_log_")
				datePart = strings.TrimSuffix(datePart, ".md")

				if len(datePart) >= 15 { // YYYYMMDD_HHMMSS
					if parsedDate, err := time.Parse("20060102_150405", datePart); err == nil {
						logDate = parsedDate
					}
				}
				service = "system"
			}

			logFile := LogFile{
				Name:    name,
				Path:    filepath.Join(logsPath, name),
				Size:    info.Size(),
				Date:    logDate,
				Service: service,
			}

			logFiles = append(logFiles, logFile)
		}

		// Sort by date (newest first)
		sort.Slice(logFiles, func(i, j int) bool {
			return logFiles[i].Date.After(logFiles[j].Date)
		})

		return logFilesLoadedMsg{logFiles: logFiles}
	}
}

// main function to initialize and run the TUI application
func main() {
	p := tea.NewProgram(initialModel(), tea.WithAltScreen())
	if _, err := p.Run(); err != nil {
		fmt.Printf("Alas, there's been an error: %v", err)
		os.Exit(1)
	}
}
