package config

import (
	"fmt"
	"strings"
)

// ProfileInfo is a safe summary for UI lists (no secrets beyond proxy URI the user already owns).
type ProfileInfo struct {
	Name     string `json:"name"`
	Protocol string `json:"protocol"`
	Proxy    string `json:"proxy"`
	Host     string `json:"host"`
	Active   bool   `json:"active"`
}

// ListProfiles returns UI-friendly profile summaries.
func (c *Config) ListProfiles() []ProfileInfo {
	out := make([]ProfileInfo, 0, len(c.Profiles))
	for _, p := range c.Profiles {
		out = append(out, ProfileInfo{
			Name:     p.Name,
			Protocol: string(p.Protocol),
			Proxy:    p.Proxy,
			Host:     proxyHost(p.Proxy),
			Active:   p.Name == c.Active,
		})
	}
	return out
}

func proxyHost(proxy string) string {
	proxy = strings.TrimSpace(proxy)
	if proxy == "" {
		return ""
	}
	if i := strings.Index(proxy, "://"); i >= 0 {
		proxy = proxy[i+3:]
	}
	if at := strings.LastIndex(proxy, "@"); at >= 0 {
		proxy = proxy[at+1:]
	}
	if i := strings.IndexAny(proxy, "/?#"); i >= 0 {
		proxy = proxy[:i]
	}
	return proxy
}

// SetActive switches the active profile name.
func (c *Config) SetActive(name string) error {
	name = strings.TrimSpace(name)
	for _, p := range c.Profiles {
		if p.Name == name {
			c.Active = name
			return nil
		}
	}
	return fmt.Errorf("profile %q not found", name)
}

// UpsertProfile creates or updates a profile by name.
func (c *Config) UpsertProfile(name, proxy string) error {
	return c.UpsertProfileWithProtocol(name, proxy, "")
}

// UpsertProfileWithProtocol creates/updates a profile and optionally sets protocol.
func (c *Config) UpsertProfileWithProtocol(name, proxy string, proto Protocol) error {
	name = strings.TrimSpace(name)
	if name == "" {
		return fmt.Errorf("имя профиля пустое")
	}
	proxy = strings.TrimSpace(proxy)
	if proto == "" {
		proto = DetectProtocol(proxy)
	}
	if proto == "" {
		proto = ProtocolNaive
	}

	for i := range c.Profiles {
		if c.Profiles[i].Name == name {
			c.Profiles[i].Proxy = proxy
			c.Profiles[i].Protocol = proto
			if len(c.Profiles[i].Listen) == 0 {
				c.Profiles[i].Listen = defaultListen()
			}
			c.Active = name
			return nil
		}
	}

	c.Profiles = append(c.Profiles, Profile{
		Name:     name,
		Protocol: proto,
		Proxy:    proxy,
		Listen:   defaultListen(),
	})
	c.Active = name
	return nil
}

// RenameProfile renames a profile and keeps active pointer in sync.
func (c *Config) RenameProfile(oldName, newName string) error {
	oldName = strings.TrimSpace(oldName)
	newName = strings.TrimSpace(newName)
	if oldName == "" || newName == "" {
		return fmt.Errorf("имя профиля пустое")
	}
	if oldName == newName {
		return nil
	}
	for _, p := range c.Profiles {
		if p.Name == newName {
			return fmt.Errorf("профиль %q уже существует", newName)
		}
	}
	for i := range c.Profiles {
		if c.Profiles[i].Name == oldName {
			c.Profiles[i].Name = newName
			if c.Active == oldName {
				c.Active = newName
			}
			return nil
		}
	}
	return fmt.Errorf("profile %q not found", oldName)
}

// DeleteProfile removes a profile. Keeps at least one profile.
func (c *Config) DeleteProfile(name string) error {
	name = strings.TrimSpace(name)
	if len(c.Profiles) <= 1 {
		return fmt.Errorf("нельзя удалить последний профиль")
	}
	idx := -1
	for i, p := range c.Profiles {
		if p.Name == name {
			idx = i
			break
		}
	}
	if idx < 0 {
		return fmt.Errorf("profile %q not found", name)
	}
	c.Profiles = append(c.Profiles[:idx], c.Profiles[idx+1:]...)
	if c.Active == name {
		c.Active = c.Profiles[0].Name
	}
	return nil
}

func defaultListen() []string {
	return []string{
		"socks://127.0.0.1:1080",
		"http://127.0.0.1:1081",
	}
}
