package config

import (
	"bufio"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"vrc_osc_go/internal/common"
)

type Config struct {
	OSC    OSCConfig
	VrcLog VrcLogConfig
}

type OSCConfig struct {
	Host string
	Port int
}

type VrcLogConfig struct {
	SelfName     string
	GuestNames   []string
	GuestFile    string
	StaffNames   []string
	MissingCount int
	LogPatterns  []string
}

func Load(path string) (*Config, error) {
	cfg := &Config{
		OSC: OSCConfig{Host: "127.0.0.1", Port: 9001},
	}
	if path == "" {
		path = filepath.Join(common.RootDir(), "config", "config.toml")
	} else if !filepath.IsAbs(path) {
		path = filepath.Join(common.RootDir(), path)
	}
	file, err := os.Open(path)
	if err != nil {
		return cfg, nil
	}
	defer file.Close()

	var section string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		line = strings.TrimPrefix(line, "\ufeff")
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
			section = strings.Trim(line, "[]")
			continue
		}
		parts := strings.SplitN(line, "=", 2)
		if len(parts) != 2 {
			continue
		}
		key := strings.TrimSpace(parts[0])
		val := strings.TrimSpace(parts[1])
		val = strings.Trim(val, "\"'")
		switch section {
		case "osc":
			switch key {
			case "host":
				cfg.OSC.Host = val
			case "port":
				if n, err := strconv.Atoi(val); err == nil {
					cfg.OSC.Port = n
				}
			}
		case "self":
			if key == "name" {
				cfg.VrcLog.SelfName = val
			}
		case "notice":
			if key == "missing_count" {
				if n, err := strconv.Atoi(val); err == nil {
					cfg.VrcLog.MissingCount = n
				}
			}
		case "vrc_log":
			if key == "patterns" {
				cfg.VrcLog.LogPatterns = parseList(val)
			}
		case "staff":
			if key == "names" {
				cfg.VrcLog.StaffNames = parseList(val)
			}
		case "guest":
			switch key {
			case "names":
				cfg.VrcLog.GuestNames = parseList(val)
			case "file":
				cfg.VrcLog.GuestFile = val
			}
		}
	}
	if cfg.VrcLog.GuestFile != "" {
		if !filepath.IsAbs(cfg.VrcLog.GuestFile) {
			cfg.VrcLog.GuestFile = filepath.Join(common.RootDir(), cfg.VrcLog.GuestFile)
		}
		if names, err := loadLines(cfg.VrcLog.GuestFile); err == nil {
			cfg.VrcLog.GuestNames = names
		}
	}
	return cfg, scanner.Err()
}

func parseList(value string) []string {
	value = strings.TrimSpace(value)
	value = strings.TrimPrefix(value, "[")
	value = strings.TrimSuffix(value, "]")
	if value == "" {
		return nil
	}
	parts := strings.Split(value, ",")
	out := make([]string, 0, len(parts))
	for _, part := range parts {
		part = strings.TrimSpace(strings.Trim(part, "\"'"))
		if part != "" {
			out = append(out, part)
		}
	}
	return out
}

func loadLines(path string) ([]string, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}
	lines := strings.Split(string(data), "\n")
	out := make([]string, 0, len(lines))
	for _, line := range lines {
		line = strings.TrimSpace(strings.TrimPrefix(line, "\ufeff"))
		if line != "" && !strings.HasPrefix(line, "#") {
			out = append(out, line)
		}
	}
	return out, nil
}
