package cli

import (
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"
	"time"

	"vpn-client/internal/config"
	"vpn-client/internal/wireguard"
)

// MonitorConnection показывает статус подключения в реальном времени
func MonitorConnection() error {
	// Проверяем, что есть активное подключение
	state, err := config.LoadState()
	if err != nil {
		return fmt.Errorf("ошибка загрузки состояния: %w", err)
	}

	if !state.Connected {
		fmt.Println("VPN не подключен")
		return nil
	}

	fmt.Println("Нажмите 'q' или Ctrl+C для выхода из мониторинга\n")
	time.Sleep(1 * time.Second)

	// Создаем канал для остановки мониторинга
	stopChan := make(chan bool, 1)

	// Запускаем горутину для чтения клавиш
	go func() {
		for {
			var input string
			fmt.Scanln(&input)
			if strings.ToLower(input) == "q" || strings.ToLower(input) == "й" {
				stopChan <- true
				return
			}
		}
	}()

	// Запускаем мониторинг
	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			clearScreen()
			displayRealtimeStatus(state)
			fmt.Printf("\n%s Нажмите 'q' и Enter для выхода\n", cyan("ℹ"))
		case <-stopChan:
			fmt.Println("\n\nВыход из мониторинга...")
			time.Sleep(500 * time.Millisecond)
			return nil
		}
	}
}

func displayRealtimeStatus(state *config.ConnectionState) {
	// Перезагружаем состояние для актуальных данных
	currentState, err := config.LoadState()
	if err != nil || !currentState.Connected {
		fmt.Println("❌ Подключение потеряно")
		return
	}

	// Заголовок
	fmt.Println(strings.Repeat("═", 70))
	fmt.Println(bold("📊 VPN МОНИТОРИНГ В РЕАЛЬНОМ ВРЕМЕНИ"))
	fmt.Println(strings.Repeat("═", 70))

	// Статус подключения
	fmt.Printf("\n%s %s\n", green("●"), bold("ПОДКЛЮЧЕНО"))
	fmt.Printf("Конфигурация: %s\n", cyan(currentState.ConfigName))
	fmt.Printf("Тип: %s\n", currentState.ConfigType)

	// Время подключения
	if currentState.StartTime != "" {
		startTime, err := time.Parse(time.RFC3339, currentState.StartTime)
		if err == nil {
			duration := time.Since(startTime)
			hours := int(duration.Hours())
			minutes := int(duration.Minutes()) % 60
			seconds := int(duration.Seconds()) % 60
			fmt.Printf("Время подключения: %s\n", 
				yellow(fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)))
		}
	}

	// Текущее время
	fmt.Printf("Текущее время: %s\n", time.Now().Format("15:04:05"))

	fmt.Println(strings.Repeat("─", 70))

	// Специфичная информация по типу подключения
	if currentState.ConfigType == "vless" {
		displayVLESSStats(currentState)
	} else if currentState.ConfigType == "wireguard" {
		displayWireGuardStats(currentState)
	}

	fmt.Println(strings.Repeat("═", 70))
	fmt.Printf("\n%s Нажмите 'q' и Enter для выхода\n", 
		cyan("ℹ"))
}

func displayVLESSStats(state *config.ConnectionState) {
	fmt.Println("\n" + bold("VLESS/Xray Прокси"))
	fmt.Printf("Адрес прокси: %s\n", green("127.0.0.1:10808"))
	fmt.Printf("Протокол: SOCKS5\n")
	fmt.Printf("PID процесса: %d\n", state.ProcessPID)

	if state.LogFile != "" {
		fmt.Printf("\n%s Логи\n", bold("📝"))
		fmt.Printf("  Трафик: %s\n", state.LogFile)
		
		// Показываем размер лог-файла
		if info, err := os.Stat(state.LogFile); err == nil {
			size := info.Size()
			sizeStr := formatBytes(size)
			fmt.Printf("  Размер лога: %s\n", sizeStr)
		}
	}

	// Проверяем, что процесс еще работает (улучшенная проверка для Windows)
	if state.ProcessPID > 0 {
		processRunning := checkProcessRunning(state.ProcessPID)
		if !processRunning {
			fmt.Printf("\n%s Процесс Xray не отвечает!\n", red("⚠"))
		}
	}
}

// checkProcessRunning проверяет, работает ли процесс
func checkProcessRunning(pid int) bool {
	process, err := os.FindProcess(pid)
	if err != nil {
		return false
	}
	
	// На Windows FindProcess всегда успешен, нужна дополнительная проверка
	// Пытаемся получить информацию о процессе через tasklist
	if runtime.GOOS == "windows" {
		cmd := exec.Command("tasklist", "/FI", fmt.Sprintf("PID eq %d", pid), "/NH")
		output, err := cmd.Output()
		if err != nil {
			return false
		}
		// Если процесс существует, в выводе будет его PID
		return strings.Contains(string(output), fmt.Sprintf("%d", pid))
	}
	
	// На Unix используем сигнал 0
	err = process.Signal(syscall.Signal(0))
	return err == nil
}

func displayWireGuardStats(state *config.ConnectionState) {
	fmt.Println("\n" + bold("WireGuard Туннель"))
	fmt.Printf("Интерфейс: %s\n", state.Interface)

	// Получаем статистику WireGuard
	stats, err := wireguard.GetStats(state.Interface)
	if err != nil {
		fmt.Printf("\n%s Ошибка получения статистики: %v\n", red("⚠"), err)
		return
	}

	fmt.Printf("\n%s Статистика трафика\n", bold("📊"))
	
	// Парсим и форматируем данные
	if rx, ok := stats["rx"]; ok {
		fmt.Printf("  %s Получено: %s\n", green("↓"), rx)
	}
	
	if tx, ok := stats["tx"]; ok {
		fmt.Printf("  %s Отправлено: %s\n", yellow("↑"), tx)
	}

	// Дополнительная информация
	if endpoint, ok := stats["endpoint"]; ok && endpoint != "" {
		fmt.Printf("\n%s Сервер\n", bold("🌐"))
		fmt.Printf("  Endpoint: %s\n", endpoint)
	}

	if handshake, ok := stats["latest_handshake"]; ok && handshake != "" {
		fmt.Printf("  Последний handshake: %s\n", handshake)
	}
}

func formatBytes(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])
}

// ShowQuickStatus показывает краткий статус (для главного меню)
func ShowQuickStatus() string {
	state, err := config.LoadState()
	if err != nil || !state.Connected {
		return fmt.Sprintf("%s Не подключено", red("○"))
	}

	// Вычисляем время подключения
	var timeStr string
	if state.StartTime != "" {
		startTime, err := time.Parse(time.RFC3339, state.StartTime)
		if err == nil {
			duration := time.Since(startTime)
			hours := int(duration.Hours())
			minutes := int(duration.Minutes()) % 60
			seconds := int(duration.Seconds()) % 60
			timeStr = fmt.Sprintf(" [%02d:%02d:%02d]", hours, minutes, seconds)
		}
	}

	return fmt.Sprintf("%s Подключено: %s%s", 
		green("●"), 
		cyan(state.ConfigName), 
		yellow(timeStr))
}
