package main

// Ayar dosyası: %APPDATA%\FikoYT\file-server.json
// Dosya yoksa ilk açılış sayılır ve ayar penceresi otomatik açılır.

import (
	"encoding/json"
	"errors"
	"net"
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

type Config struct {
	Dinle         string   `json:"dinle"`
	Everything    string   `json:"everything"`
	IzinliKoken   string   `json:"izinliKoken"`
	Kokler        []string `json:"kokler"`
	WindowsAcilis bool     `json:"windowsAcilis"`
}

func varsayilanConfig() Config {
	return Config{
		Dinle:       "127.0.0.1:7777",
		Everything:  "http://127.0.0.1:8888",
		IzinliKoken: "https://fikoyt.com",
		Kokler:      []string{},
	}
}

func configYolu() (string, error) {
	dir, err := os.UserConfigDir()
	if err != nil {
		return "", err
	}
	return filepath.Join(dir, "FikoYT", "file-server.json"), nil
}

// configOku: ayarı, dosyanın var olup olmadığını ve hatayı döner.
func configOku() (Config, bool, error) {
	yol, err := configYolu()
	if err != nil {
		return varsayilanConfig(), false, err
	}
	veri, err := os.ReadFile(yol)
	if errors.Is(err, os.ErrNotExist) {
		return varsayilanConfig(), false, nil
	}
	if err != nil {
		return varsayilanConfig(), true, err
	}
	cfg := varsayilanConfig()
	if err := json.Unmarshal(veri, &cfg); err != nil {
		return varsayilanConfig(), true, err
	}
	return cfg, true, nil
}

func configYaz(cfg Config) error {
	yol, err := configYolu()
	if err != nil {
		return err
	}
	if err := os.MkdirAll(filepath.Dir(yol), 0o755); err != nil {
		return err
	}
	veri, err := json.MarshalIndent(cfg, "", "  ")
	if err != nil {
		return err
	}
	return os.WriteFile(yol, veri, 0o644)
}

// dogrula: güvenlik sınırları. Sunucu yalnızca loopback'te dinler,
// Everything adresi de yerel olmak zorundadır.
func (c *Config) dogrula() error {
	c.Dinle = strings.TrimSpace(c.Dinle)
	c.Everything = strings.TrimSpace(c.Everything)
	c.IzinliKoken = strings.TrimSpace(c.IzinliKoken)

	host, port, err := net.SplitHostPort(c.Dinle)
	if err != nil {
		return errors.New("dinleme adresi 127.0.0.1:7777 biçiminde olmalı")
	}
	if host != "127.0.0.1" && host != "localhost" {
		return errors.New("dinleme adresi yalnızca 127.0.0.1 olabilir")
	}
	if p, err := strconv.Atoi(port); err != nil || p < 1024 || p > 65535 {
		return errors.New("port 1024-65535 aralığında olmalı")
	}

	eu, err := url.Parse(c.Everything)
	if err != nil || eu.Scheme != "http" || (eu.Hostname() != "127.0.0.1" && eu.Hostname() != "localhost") {
		return errors.New("Everything adresi http://127.0.0.1:8888 biçiminde olmalı")
	}

	if c.IzinliKoken != "" {
		ku, err := url.Parse(c.IzinliKoken)
		if err != nil || (ku.Scheme != "https" && ku.Scheme != "http") || ku.Host == "" {
			return errors.New("izinli köken https://... biçiminde olmalı")
		}
	}

	temiz := []string{}
	for _, k := range c.Kokler {
		if k = strings.TrimSpace(k); k != "" {
			temiz = append(temiz, k)
		}
	}
	c.Kokler = temiz
	return nil
}
