package main

import (
	"fmt"
	"sync"
	"time"
)

// ANSI color codes
const (
	ColorReset  = "\033[0m"
	ColorRed    = "\033[31m"
	ColorGreen  = "\033[32m"
	ColorYellow = "\033[33m"
	ColorBlue   = "\033[34m"
	ColorPurple = "\033[35m"
	ColorCyan   = "\033[36m"
	ColorWhite  = "\033[37m"
	ColorBold   = "\033[1m"
)

// ProgressTracker tracks checking progress
type ProgressTracker struct {
	Total       int
	Checked     int
	WithBalance int
	TotalValue  float64
	StartTime   time.Time
	mu          sync.Mutex
}

// NewProgressTracker creates a new progress tracker
func NewProgressTracker(total int) *ProgressTracker {
	return &ProgressTracker{
		Total:     total,
		StartTime: time.Now(),
	}
}

// Increment increments progress counters
func (pt *ProgressTracker) Increment(balance float64) {
	pt.mu.Lock()
	defer pt.mu.Unlock()
	pt.Checked++
	pt.TotalValue += balance
	if balance > 0 {
		pt.WithBalance++
	}
}

// GetStats returns current statistics
func (pt *ProgressTracker) GetStats() (int, int, int, float64, time.Duration) {
	pt.mu.Lock()
	defer pt.mu.Unlock()
	elapsed := time.Since(pt.StartTime)
	return pt.Total, pt.Checked, pt.WithBalance, pt.TotalValue, elapsed
}

// CalculateETA calculates estimated time to completion
func (pt *ProgressTracker) CalculateETA() string {
	pt.mu.Lock()
	defer pt.mu.Unlock()

	if pt.Checked == 0 {
		return "calculating..."
	}

	elapsed := time.Since(pt.StartTime)
	avgTimePerKey := elapsed / time.Duration(pt.Checked)
	remaining := pt.Total - pt.Checked
	eta := avgTimePerKey * time.Duration(remaining)

	if eta < time.Second {
		return "< 1s"
	} else if eta < time.Minute {
		return fmt.Sprintf("%ds", int(eta.Seconds()))
	} else if eta < time.Hour {
		mins := int(eta.Minutes())
		secs := int(eta.Seconds()) % 60
		return fmt.Sprintf("%dm %ds", mins, secs)
	} else {
		hours := int(eta.Hours())
		mins := int(eta.Minutes()) % 60
		return fmt.Sprintf("%dh %dm", hours, mins)
	}
}

type StatusDisplay struct {
	tracker  *ProgressTracker
	stopChan chan bool
	wg       sync.WaitGroup
}

// NewStatusDisplay creates new status display
func NewStatusDisplay(tracker *ProgressTracker) *StatusDisplay {
	return &StatusDisplay{
		tracker:  tracker,
		stopChan: make(chan bool),
	}
}

// Start starts the display update loop
func (sd *StatusDisplay) Start() {
	sd.wg.Add(1)
	go sd.updateLoop()
}

// Stop stops the display
func (sd *StatusDisplay) Stop() {
	sd.stopChan <- true
	sd.wg.Wait()
	sd.clearLine()
}

func (sd *StatusDisplay) clearLine() {
	fmt.Print("\r\033[K")
}

func (sd *StatusDisplay) updateLoop() {
	defer sd.wg.Done()
	ticker := time.NewTicker(100 * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-sd.stopChan:
			return
		case <-ticker.C:
			sd.update()
		}
	}
}

func (sd *StatusDisplay) update() {
	total, checked, withBalance, totalValue, _ := sd.tracker.GetStats()
	eta := sd.tracker.CalculateETA()

	percentage := 0
	if total > 0 {
		percentage = (checked * 100) / total
	}

	progressColor := ColorYellow
	if percentage >= 100 {
		progressColor = ColorGreen
	} else if percentage >= 75 {
		progressColor = ColorCyan
	}

	status := fmt.Sprintf("%s%s[%d%%]%s %s%d/%d%s checked | %s%d%s with balance | %s$%.2f%s total | ETA: %s%s%s",
		ColorBold, progressColor, percentage, ColorReset,
		ColorCyan, checked, total, ColorReset,
		ColorGreen, withBalance, ColorReset,
		ColorYellow, totalValue, ColorReset,
		ColorPurple, eta, ColorReset,
	)

	sd.clearLine()
	fmt.Print("\r" + status)
}

func ColorPrint(color, text string) {
	fmt.Print(color + text + ColorReset)
}

func ColorPrintln(color, text string) {
	fmt.Println(color + text + ColorReset)
}

func colorPrint(color, text string) {
	fmt.Print(color + text + ColorReset)
}

func colorPrintln(color, text string) {
	fmt.Println(color + text + ColorReset)
}
