package gui

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

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

// Запуск HTTP сервера
func startServer() string {
	addr := "127.0.0.1:8765"
	
	http.HandleFunc("/", handleIndex)
	http.HandleFunc("/api/status", handleStatus)
	http.HandleFunc("/api/wireguard/list", handleWireGuardList)
	http.HandleFunc("/api/wireguard/add", handleWireGuardAdd)
	http.HandleFunc("/api/wireguard/delete", handleWireGuardDelete)
	http.HandleFunc("/api/wireguard/connect", handleWireGuardConnect)
	http.HandleFunc("/api/vless/list", handleVLESSList)
	http.HandleFunc("/api/vless/add", handleVLESSAdd)
	http.HandleFunc("/api/vless/delete", handleVLESSDelete)
	http.HandleFunc("/api/vless/connect", handleVLESSConnect)
	http.HandleFunc("/api/vless/test", handleVLESSTest)
	http.HandleFunc("/api/subscriptions/list", handleSubscriptionsList)
	http.HandleFunc("/api/subscriptions/add", handleSubscriptionsAdd)
	http.HandleFunc("/api/subscriptions/delete", handleSubscriptionsDelete)
	http.HandleFunc("/api/subscriptions/update", handleSubscriptionsUpdate)
	http.HandleFunc("/api/subscriptions/show", handleSubscriptionsShow)
	http.HandleFunc("/api/subscriptions/test", handleSubscriptionsTest)
	http.HandleFunc("/api/disconnect", handleDisconnect)
	
	go http.ListenAndServe(addr, nil)
	
	return "http://" + addr
}

// API handlers
func handleStatus(w http.ResponseWriter, r *http.Request) {
	state, err := vpn.GetStatus()
	
	response := map[string]interface{}{
		"connected": false,
		"info":      "",
	}
	
	if err == nil && state.Connected {
		response["connected"] = true
		
		info := fmt.Sprintf("Конфиг: %s | Тип: %s", state.ConfigName, state.ConfigType)
		
		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
				info += fmt.Sprintf(" | Время: %02d:%02d:%02d", hours, minutes, seconds)
			}
		}
		
		if state.ConfigType == "vless" {
			info += " | Прокси: 127.0.0.1:10808"
		} else if state.ConfigType == "wireguard" {
			stats, err := wireguard.GetStats(state.Interface)
			if err == nil {
				info += fmt.Sprintf(" | ↓%s ↑%s", stats["rx"], stats["tx"])
			}
		}
		
		response["info"] = info
	}
	
	json.NewEncoder(w).Encode(response)
}

func handleWireGuardList(w http.ResponseWriter, r *http.Request) {
	configs, _ := config.LoadConfigs()
	json.NewEncoder(w).Encode(configs.WireGuard)
}

func handleWireGuardAdd(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Name   string `json:"name"`
		Config string `json:"config"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	err := wireguard.AddConfig(req.Name, req.Config)
	json.NewEncoder(w).Encode(map[string]interface{}{
		"success": err == nil,
		"message": func() string {
			if err != nil {
				return err.Error()
			}
			return "Конфиг добавлен"
		}(),
	})
}

func handleWireGuardDelete(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Index int `json:"index"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	configs, _ := config.LoadConfigs()
	if req.Index >= 0 && req.Index < len(configs.WireGuard) {
		name := configs.WireGuard[req.Index].Name
		wireguard.DeleteConfig(name)
	}
	
	json.NewEncoder(w).Encode(map[string]bool{"success": true})
}

func handleWireGuardConnect(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Index int `json:"index"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	configs, _ := config.LoadConfigs()
	if req.Index >= 0 && req.Index < len(configs.WireGuard) {
		name := configs.WireGuard[req.Index].Name
		err := wireguard.Connect(name, config.LogsDir)
		
		json.NewEncoder(w).Encode(map[string]interface{}{
			"success": err == nil,
			"message": func() string {
				if err != nil {
					return err.Error()
				}
				return "Подключено к " + name
			}(),
		})
		return
	}
	
	json.NewEncoder(w).Encode(map[string]interface{}{
		"success": false,
		"message": "Конфиг не найден",
	})
}

func handleVLESSList(w http.ResponseWriter, r *http.Request) {
	configs, _ := config.LoadConfigs()
	json.NewEncoder(w).Encode(configs.VLESS)
}

func handleVLESSAdd(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Name string `json:"name"`
		URL  string `json:"url"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	configs, err := config.LoadConfigs()
	if err == nil {
		configs.VLESS = append(configs.VLESS, config.VLESSConfig{
			Name:     req.Name,
			URL:      req.URL,
			Protocol: "VLESS",
		})
		config.SaveConfigs(configs)
	}
	
	json.NewEncoder(w).Encode(map[string]bool{"success": true})
}

func handleVLESSDelete(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Index int `json:"index"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	configs, _ := config.LoadConfigs()
	if req.Index >= 0 && req.Index < len(configs.VLESS) {
		configs.VLESS = append(configs.VLESS[:req.Index], configs.VLESS[req.Index+1:]...)
		config.SaveConfigs(configs)
	}
	
	json.NewEncoder(w).Encode(map[string]bool{"success": true})
}

func handleVLESSConnect(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Index int `json:"index"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	configs, _ := config.LoadConfigs()
	if req.Index >= 0 && req.Index < len(configs.VLESS) {
		name := configs.VLESS[req.Index].Name
		err := vless.Connect(name, config.LogsDir, config.XrayDir)
		
		json.NewEncoder(w).Encode(map[string]interface{}{
			"success": err == nil,
			"message": func() string {
				if err != nil {
					return err.Error()
				}
				return "Подключено к " + name + "\n\nSOCKS5 прокси: 127.0.0.1:10808"
			}(),
		})
		return
	}
	
	json.NewEncoder(w).Encode(map[string]interface{}{
		"success": false,
		"message": "Конфиг не найден",
	})
}

func handleVLESSTest(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Index int `json:"index"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	configs, _ := config.LoadConfigs()
	if req.Index >= 0 && req.Index < len(configs.VLESS) {
		cfg := configs.VLESS[req.Index]
		success, ping, err := vless.PingServer(cfg.URL, 5*time.Second)
		
		if err != nil || !success {
			msg := "Сервер недоступен"
			if err != nil {
				msg += "\n\nОшибка: " + err.Error()
			}
			json.NewEncoder(w).Encode(map[string]string{"message": msg})
			return
		}
		
		quality := "Плохо"
		if ping < 50 {
			quality = "Отлично"
		} else if ping < 100 {
			quality = "Хорошо"
		} else if ping < 200 {
			quality = "Средне"
		}
		
		msg := fmt.Sprintf("✓ Сервер доступен\n\nПинг: %.2f мс\nКачество: %s", ping, quality)
		json.NewEncoder(w).Encode(map[string]string{"message": msg})
		return
	}
	
	json.NewEncoder(w).Encode(map[string]string{"message": "Конфиг не найден"})
}

func handleSubscriptionsList(w http.ResponseWriter, r *http.Request) {
	subs, _ := config.LoadSubscriptions()
	json.NewEncoder(w).Encode(subs.Subscriptions)
}

func handleSubscriptionsAdd(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Name string `json:"name"`
		URL  string `json:"url"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	subs, err := config.LoadSubscriptions()
	if err == nil {
		subs.Subscriptions = append(subs.Subscriptions, config.Subscription{
			Name: req.Name,
			URL:  req.URL,
		})
		config.SaveSubscriptions(subs)
	}
	
	json.NewEncoder(w).Encode(map[string]bool{"success": true})
}

func handleSubscriptionsDelete(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Index int `json:"index"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	subs, _ := config.LoadSubscriptions()
	if req.Index >= 0 && req.Index < len(subs.Subscriptions) {
		subs.Subscriptions = append(subs.Subscriptions[:req.Index], subs.Subscriptions[req.Index+1:]...)
		config.SaveSubscriptions(subs)
	}
	
	json.NewEncoder(w).Encode(map[string]bool{"success": true})
}

func handleSubscriptionsUpdate(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Index int `json:"index"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	subs, _ := config.LoadSubscriptions()
	if req.Index >= 0 && req.Index < len(subs.Subscriptions) {
		name := subs.Subscriptions[req.Index].Name
		err := subscription.UpdateSubscription(name, config.LogsDir)
		
		json.NewEncoder(w).Encode(map[string]interface{}{
			"success": err == nil,
			"message": func() string {
				if err != nil {
					return err.Error()
				}
				return "Конфиги обновлены из подписки"
			}(),
		})
		return
	}
	
	json.NewEncoder(w).Encode(map[string]interface{}{
		"success": false,
		"message": "Подписка не найдена",
	})
}

func handleSubscriptionsShow(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Index int `json:"index"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	subs, _ := config.LoadSubscriptions()
	if req.Index >= 0 && req.Index < len(subs.Subscriptions) {
		subName := subs.Subscriptions[req.Index].Name
		
		configs, _ := config.LoadConfigs()
		var subConfigs []config.VLESSConfig
		for _, cfg := range configs.VLESS {
			if cfg.Subscription == subName {
				subConfigs = append(subConfigs, cfg)
			}
		}
		
		if len(subConfigs) == 0 {
			json.NewEncoder(w).Encode(map[string]string{
				"message": "Нет конфигов из этой подписки.\n\nСначала обновите конфиги из подписки.",
			})
			return
		}
		
		msg := fmt.Sprintf("Конфиги из '%s':\n\n", subName)
		for i, cfg := range subConfigs {
			protocol := cfg.Protocol
			if protocol == "" {
				protocol = "Unknown"
			}
			msg += fmt.Sprintf("%d. [%s] %s\n", i+1, protocol, cfg.Name)
		}
		
		json.NewEncoder(w).Encode(map[string]string{"message": msg})
		return
	}
	
	json.NewEncoder(w).Encode(map[string]string{"message": "Подписка не найдена"})
}

func handleSubscriptionsTest(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Index int `json:"index"`
	}
	json.NewDecoder(r.Body).Decode(&req)
	
	subs, _ := config.LoadSubscriptions()
	if req.Index >= 0 && req.Index < len(subs.Subscriptions) {
		subName := subs.Subscriptions[req.Index].Name
		
		configs, _ := config.LoadConfigs()
		var subConfigs []config.VLESSConfig
		for _, cfg := range configs.VLESS {
			if cfg.Subscription == subName {
				subConfigs = append(subConfigs, cfg)
			}
		}
		
		if len(subConfigs) == 0 {
			json.NewEncoder(w).Encode(map[string]string{"message": "Нет конфигов из этой подписки"})
			return
		}
		
		// Тестирование (упрощенная версия - первые 10)
		msg := fmt.Sprintf("Тестирование серверов из '%s'...\n\n", subName)
		tested := 0
		for i, cfg := range subConfigs {
			if i >= 10 {
				break
			}
			tested++
			success, ping, _ := vless.PingServer(cfg.URL, 3*time.Second)
			if success {
				msg += fmt.Sprintf("✓ %s - %.2f мс\n", cfg.Name, ping)
			} else {
				msg += fmt.Sprintf("✗ %s - недоступен\n", cfg.Name)
			}
		}
		
		if len(subConfigs) > 10 {
			msg += fmt.Sprintf("\n(Показано %d из %d серверов)", tested, len(subConfigs))
		}
		
		json.NewEncoder(w).Encode(map[string]string{"message": msg})
		return
	}
	
	json.NewEncoder(w).Encode(map[string]string{"message": "Подписка не найдена"})
}

func handleDisconnect(w http.ResponseWriter, r *http.Request) {
	state, err := vpn.GetStatus()
	if err != nil || !state.Connected {
		json.NewEncoder(w).Encode(map[string]interface{}{
			"success": false,
			"message": "VPN не подключен",
		})
		return
	}
	
	err = vpn.Disconnect(config.LogsDir)
	json.NewEncoder(w).Encode(map[string]interface{}{
		"success": err == nil,
		"message": func() string {
			if err != nil {
				return err.Error()
			}
			return "Отключено от VPN"
		}(),
	})
}
