package ui

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/aki/amux/internal/worktree"
)

// Error prints an error message with formatting
func Error(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "%s %s\n", ErrorIcon, ErrorStyle.Render(fmt.Sprintf(format, args...)))
}

// Success prints a success message with formatting
func Success(format string, args ...interface{}) {
	fmt.Printf("%s %s\n", SuccessIcon, SuccessStyle.Render(fmt.Sprintf(format, args...)))
}

// Info prints an informational message with formatting
func Info(format string, args ...interface{}) {
	fmt.Printf("%s %s\n", InfoIcon, InfoStyle.Render(fmt.Sprintf(format, args...)))
}

// Warning prints a warning message with formatting
func Warning(format string, args ...interface{}) {
	fmt.Printf("%s %s\n", WarningIcon, WarningStyle.Render(fmt.Sprintf(format, args...)))
}

// Output prints plain text without any formatting or icons
func Output(format string, args ...interface{}) {
	fmt.Printf(format, args...)
}

// OutputLine prints plain text with a newline
func OutputLine(format string, args ...interface{}) {
	fmt.Printf(format+"\n", args...)
}

// PrintKeyValue prints a key-value pair with styling
func PrintKeyValue(key, value string) {
	OutputLine("%s %s", DimStyle.Render(key+":"), value)
}

// PrintIndented prints text with indentation
func PrintIndented(indent int, format string, args ...interface{}) {
	padding := strings.Repeat(" ", indent)
	OutputLine("%s%s", padding, fmt.Sprintf(format, args...))
}

// Separator prints a separator line
func Separator(char string, width int) {
	OutputLine("%s", strings.Repeat(char, width))
}

// Prompt displays a prompt and reads user input
func Prompt(message string) string {
	Output("%s", message)
	reader := bufio.NewReader(os.Stdin)
	input, _ := reader.ReadString('\n')
	return strings.TrimSpace(input)
}

// PrintTSV prints tab-separated values
func PrintTSV(rows [][]string) {
	for _, row := range rows {
		OutputLine("%s", strings.Join(row, "\t"))
	}
}

// Raw prints raw content without any processing
func Raw(content string) {
	Output("%s", content)
}

// PrintWorktree displays a single worktree with formatting
func PrintWorktree(w *worktree.Worktree) {
	// Calculate age from last modified time
	age := time.Since(w.UpdatedAt)
	ageStr := FormatDuration(age)

	OutputLine("%s %s %s",
		"📁",
		BoldStyle.Render(w.Branch),
		DimStyle.Render(fmt.Sprintf("updated %s ago", ageStr)),
	)

	if w.Description != "" {
		OutputLine("   %s", w.Description)
	}

	OutputLine("   %s %s", DimStyle.Render("Branch:"), w.Branch)
	OutputLine("   %s %s", DimStyle.Render("Path:"), w.Path)

	OutputLine("   %s %s", DimStyle.Render("Created:"), FormatTime(w.CreatedAt))
	OutputLine("   %s %s", DimStyle.Render("Updated:"), FormatTime(w.UpdatedAt))

	// Show consistency status
	var statusStr string
	switch w.Status {
	case worktree.StatusConsistent:
		statusStr = SuccessStyle.Render("✓ Consistent")
	case worktree.StatusFolderMissing:
		statusStr = WarningStyle.Render("⚠ Folder missing (run 'amux wt rm' to clean up)")
	case worktree.StatusWorktreeMissing:
		statusStr = WarningStyle.Render("⚠ Git worktree missing (run 'amux wt rm' to clean up)")
	case worktree.StatusOrphaned:
		statusStr = ErrorStyle.Render("✗ Orphaned (both folder and worktree missing)")
	default:
		statusStr = DimStyle.Render("Unknown")
	}
	OutputLine("   %s %s", DimStyle.Render("Status:"), statusStr)

	// Show active sessions
	sessionCount := w.SessionCount()
	if sessionCount > 0 {
		sessionIDs, err := w.SessionIDs()
		if err == nil && len(sessionIDs) > 0 {
			OutputLine("   %s %d active session(s):", DimStyle.Render("Sessions:"), sessionCount)
			for _, sessionID := range sessionIDs {
				OutputLine("     - %s", sessionID)
			}
		} else {
			OutputLine("   %s %d", DimStyle.Render("Sessions:"), sessionCount)
		}
	} else {
		OutputLine("   %s %s", DimStyle.Render("Sessions:"), DimStyle.Render("none"))
	}
}

// FormatDuration formats a duration into a human-readable string
func FormatDuration(d time.Duration) string {
	if d < time.Minute {
		return "< 1m"
	}
	if d < time.Hour {
		return fmt.Sprintf("%dm", int(d.Minutes()))
	}
	if d < 24*time.Hour {
		return fmt.Sprintf("%dh", int(d.Hours()))
	}
	return fmt.Sprintf("%dd", int(d.Hours()/24))
}

// PrintWorktreeList displays a list of worktrees using a table
func PrintWorktreeList(worktrees []*worktree.Worktree) {
	if len(worktrees) == 0 {
		Info("No worktrees found")
		return
	}

	// Create table
	tbl := NewTable("BRANCH", "AGE", "STATUS", "DESCRIPTION")

	// Add rows
	for _, w := range worktrees {
		age := FormatDuration(time.Since(w.UpdatedAt))
		description := w.Description
		if description == "" {
			description = "-"
		}

		// Format status with appropriate icon and session info
		var status string
		sessionCount := w.SessionCount()

		// Base status
		switch w.Status {
		case worktree.StatusConsistent:
			status = SuccessStyle.Render("✓ ok")
		case worktree.StatusFolderMissing:
			status = WarningStyle.Render("⚠ folder missing")
		case worktree.StatusWorktreeMissing:
			status = WarningStyle.Render("⚠ worktree missing")
		case worktree.StatusOrphaned:
			status = ErrorStyle.Render("✗ orphaned")
		default:
			status = DimStyle.Render("unknown")
		}

		// Add session info if any sessions are active
		if sessionCount > 0 {
			sessionInfo := fmt.Sprintf("%d active", sessionCount)
			// Highlight if 3 or more sessions
			if sessionCount >= 3 {
				sessionInfo = WarningStyle.Render(sessionInfo)
			}
			status = fmt.Sprintf("%s • %s", status, sessionInfo)
		}

		tbl.AddRow(w.Branch, age, status, description)
	}

	// Print with header
	PrintSectionHeader(WorkspaceIcon, "Worktrees", len(worktrees))
	tbl.Print()
}

// PrintWorktreeDetails displays detailed information about a single worktree
func PrintWorktreeDetails(w *worktree.Worktree) {
	OutputLine("%s Worktree Details\n", WorkspaceIcon)
	PrintWorktree(w)
}

// FormatTime formats a time for display
func FormatTime(t time.Time) string {
	if t.IsZero() {
		return "never"
	}

	now := time.Now()

	diff := now.Sub(t)

	switch {

	case diff < time.Minute:

		return "just now"

	case diff < time.Hour:

		minutes := int(diff.Minutes())

		if minutes == 1 {
			return "1 minute ago"
		}

		return fmt.Sprintf("%d minutes ago", minutes)

	case diff < 24*time.Hour:

		hours := int(diff.Hours())

		if hours == 1 {
			return "1 hour ago"
		}

		return fmt.Sprintf("%d hours ago", hours)

	case diff < 7*24*time.Hour:

		days := int(diff.Hours() / 24)

		if days == 1 {
			return "1 day ago"
		}

		return fmt.Sprintf("%d days ago", days)

	default:

		return t.Format("2006-01-02 15:04")

	}
}

// FormatSize formats a file size in bytes to a human-readable string
func FormatSize(bytes int64) string {
	const (
		KB = 1024
		MB = KB * 1024
		GB = MB * 1024
	)

	switch {
	case bytes < KB:
		return fmt.Sprintf("%dB", bytes)
	case bytes < MB:
		return fmt.Sprintf("%.1fKB", float64(bytes)/KB)
	case bytes < GB:
		return fmt.Sprintf("%.1fMB", float64(bytes)/MB)
	default:
		return fmt.Sprintf("%.1fGB", float64(bytes)/GB)
	}
}

// Confirm asks the user for confirmation
func Confirm(prompt string) bool {
	reader := bufio.NewReader(os.Stdin)
	fmt.Printf("%s [y/N]: ", prompt)

	response, err := reader.ReadString('\n')
	if err != nil {
		return false
	}

	response = strings.TrimSpace(strings.ToLower(response))
	return response == "y" || response == "yes"
}

// ConfirmWithDefault asks the user for confirmation with a default value
func ConfirmWithDefault(prompt string, defaultYes bool) bool {
	reader := bufio.NewReader(os.Stdin)

	if defaultYes {
		fmt.Printf("%s [Y/n]: ", prompt)
	} else {
		fmt.Printf("%s [y/N]: ", prompt)
	}

	response, err := reader.ReadString('\n')
	if err != nil {
		return defaultYes
	}

	response = strings.TrimSpace(strings.ToLower(response))

	// If empty response, use default
	if response == "" {
		return defaultYes
	}

	return response == "y" || response == "yes"
}
