package main

// Hesap profilleri: bridge'de oturum acan her fikoyt kullanicisinin verisi kendi klasorunde tutulur.
//   %AppData%\FikoYT\profiller\<anahtar>\  (oturum, izinler, eslesmeler, eklenti ayarlari, cihaz kimligi)
// Anahtar, kullanici adindan turetilir ve yalnizca guvenli karakterler icerir.
// Global "aktif profil" kavrami yoktur: etkin tum hesaplar ayni anda calisir; her istek
// yalnizca kendi token'inin profiline erisir.

import (
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var profilAnahtarDesen = regexp.MustCompile(`^[a-z0-9_.-]{1,64}$`)

// Tek hesap donemindeki dosyalar. Ilk profil etkinlestirilirken bu dosyalar
// kok klasordan yeni profilin klasorune tasinir.
var eskiTekHesapDosyalari = []string{
	"oturum.json",
	"bridge-izin.json",
	"eslesmeler.json",
	"cihaz-kimlik",
	"cihaz-gizli",
	"cihaz-makine",
	"eklenti-ayar",
	"bridge-yetki.json",
	"bridge-kurulu.json",
}

// profilAnahtari: kullanici adindan dosya sistemine guvenli anahtar uretir.
func profilAnahtari(kullaniciAdi string) (string, error) {
	s := strings.ToLower(strings.TrimSpace(kullaniciAdi))
	var b strings.Builder
	for _, r := range s {
		switch {
		case r >= 'a' && r <= 'z', r >= '0' && r <= '9', r == '_', r == '.', r == '-':
			b.WriteRune(r)
		default:
			b.WriteRune('_')
		}
	}
	anahtar := b.String()
	if len(anahtar) > 64 {
		anahtar = anahtar[:64]
	}
	if !profilAnahtarDesen.MatchString(anahtar) {
		return "", fmt.Errorf("gecersiz profil anahtari")
	}
	return anahtar, nil
}

// profilKlasoru: bir profilin veri klasorunu dondurur ve yoksa olusturur.
func profilKlasoru(anahtar string) (string, error) {
	if !profilAnahtarDesen.MatchString(anahtar) {
		return "", fmt.Errorf("gecersiz profil anahtari")
	}
	kok, err := veriKlasoru()
	if err != nil {
		return "", err
	}
	yol := filepath.Join(kok, "profiller", anahtar)
	if err := os.MkdirAll(yol, 0o700); err != nil {
		return "", err
	}
	return yol, nil
}

// profilKlasorTasi: eski anahtarli (kullanici adi) profil klasorunu yeni anahtara (kullanici kimligi) tasir.
// Yeni klasor yoksa klasor yeniden adlandirilir; varsa eksik dosyalar tasinir, mevcut dosyalar korunur.
func profilKlasorTasi(kok, eski, yeni string) error {
	if eski == "" || eski == yeni {
		return nil
	}
	if !profilAnahtarDesen.MatchString(eski) || !profilAnahtarDesen.MatchString(yeni) {
		return nil
	}
	eskiYol := filepath.Join(kok, "profiller", eski)
	if _, err := os.Stat(eskiYol); err != nil {
		return nil
	}
	yeniYol := filepath.Join(kok, "profiller", yeni)
	if _, err := os.Stat(yeniYol); err != nil {
		return os.Rename(eskiYol, yeniYol)
	}
	girdiler, err := os.ReadDir(eskiYol)
	if err != nil {
		return err
	}
	for _, g := range girdiler {
		hedef := filepath.Join(yeniYol, g.Name())
		if _, err := os.Stat(hedef); err == nil {
			continue
		}
		if err := os.Rename(filepath.Join(eskiYol, g.Name()), hedef); err != nil {
			return err
		}
	}
	_ = os.Remove(eskiYol)
	return nil
}

// profilVarMi: profiller klasorunde en az bir profil var mi.
func profilVarMi(kok string) bool {
	girdiler, err := os.ReadDir(filepath.Join(kok, "profiller"))
	return err == nil && len(girdiler) > 0
}

// eskiDosyalariTasi: kok klasordeki tek hesap dosyalarini verilen profile tasir.
func eskiDosyalariTasi(kok, anahtar string) error {
	hedef := filepath.Join(kok, "profiller", anahtar)
	for _, ad := range eskiTekHesapDosyalari {
		kaynak := filepath.Join(kok, ad)
		if _, err := os.Stat(kaynak); err != nil {
			continue
		}
		if err := os.Rename(kaynak, filepath.Join(hedef, ad)); err != nil {
			return fmt.Errorf("%s tasinamadi: %w", ad, err)
		}
	}
	return nil
}

// profilHazirla: verilen profilin klasorunu hazirlar ve etkin hesaplara ekler. Profil hic yoksa (ilk acilis)
// tek hesap donemindeki dosyalar bu profile tasinir. Hicbir hesap "aktif" yapilmaz.
func profilHazirla(anahtar string) error {
	if !profilAnahtarDesen.MatchString(anahtar) {
		return fmt.Errorf("gecersiz profil anahtari")
	}
	kok, err := veriKlasoru()
	if err != nil {
		return err
	}
	if !profilVarMi(kok) {
		if _, err := profilKlasoru(anahtar); err != nil {
			return err
		}
		if err := eskiDosyalariTasi(kok, anahtar); err != nil {
			return err
		}
	}
	if _, err := profilKlasoru(anahtar); err != nil {
		return err
	}
	return etkinHesapEkle(anahtar)
}
