package main

import (
	"encoding/base64"
	"os"
	"path/filepath"
	"testing"
)

func b64(s string) string { return base64.StdEncoding.EncodeToString([]byte(s)) }

func TestListele(t *testing.T) {
	klasor := t.TempDir()
	os.WriteFile(filepath.Join(klasor, "b.txt"), []byte("merhaba"), 0o644)
	os.Mkdir(filepath.Join(klasor, "alt"), 0o755)
	c := listele(klasor)
	if !c.Tamam {
		t.Fatalf("listele basarisiz: %s", c.Hata)
	}
	kayitlar := c.Veri.(map[string]any)["kayitlar"].([]kayit)
	if len(kayitlar) != 2 || kayitlar[0].Tip != "klasor" || kayitlar[1].Ad != "b.txt" {
		t.Fatalf("beklenmeyen liste: %+v", kayitlar)
	}
}

func TestOkuParca(t *testing.T) {
	yol := filepath.Join(t.TempDir(), "x.nc")
	os.WriteFile(yol, []byte("0123456789"), 0o644)
	c := oku(veriIslem{Yol: yol, Ofset: 0, Uzunluk: 4})
	v := c.Veri.(map[string]any)
	icerik, _ := base64.StdEncoding.DecodeString(v["icerik"].(string))
	if string(icerik) != "0123" || v["bitti"].(bool) {
		t.Fatalf("ilk parca yanlis: %q", icerik)
	}
	c = oku(veriIslem{Yol: yol, Ofset: 8, Uzunluk: 4})
	v = c.Veri.(map[string]any)
	icerik, _ = base64.StdEncoding.DecodeString(v["icerik"].(string))
	if string(icerik) != "89" || !v["bitti"].(bool) {
		t.Fatalf("son parca yanlis: %q", icerik)
	}
}

func TestYazParcali(t *testing.T) {
	yol := filepath.Join(t.TempDir(), "yeni.nc")
	if c := yaz2(veriIslem{Yol: yol, Icerik: b64("abc"), Ilk: true, Bitti: false}); !c.Tamam {
		t.Fatalf("ilk parca: %s", c.Hata)
	}
	if c := yaz2(veriIslem{Yol: yol, Icerik: b64("def"), Bitti: true}); !c.Tamam {
		t.Fatalf("son parca: %s", c.Hata)
	}
	icerik, _ := os.ReadFile(yol)
	if string(icerik) != "abcdef" {
		t.Fatalf("birlesik icerik yanlis: %q", icerik)
	}
	if _, err := os.Stat(yol + geciciEk); err == nil {
		t.Fatal("gecici dosya kaldi")
	}
}

func TestYazVarOlanReddedilir(t *testing.T) {
	yol := filepath.Join(t.TempDir(), "var.txt")
	os.WriteFile(yol, []byte("eski"), 0o644)
	if c := yaz2(veriIslem{Yol: yol, Icerik: b64("yeni"), Ilk: true, Bitti: true}); c.Tamam {
		t.Fatal("var olan dosyanin uzerine yazildi")
	}
	if c := yaz2(veriIslem{Yol: yol, Icerik: b64("yeni"), Ilk: true, Bitti: true, UzerineYaz: true}); !c.Tamam {
		t.Fatalf("uzerine yazma basarisiz: %s", c.Hata)
	}
	icerik, _ := os.ReadFile(yol)
	if string(icerik) != "yeni" {
		t.Fatalf("uzerine yazma icerigi yanlis: %q", icerik)
	}
}

func TestKopyala(t *testing.T) {
	klasor := t.TempDir()
	kaynak := filepath.Join(klasor, "a.txt")
	hedef := filepath.Join(klasor, "b.txt")
	os.WriteFile(kaynak, []byte("veri"), 0o644)
	if c := kopyala(veriIslem{Kaynak: kaynak, Hedef: hedef}); !c.Tamam {
		t.Fatalf("kopyalama: %s", c.Hata)
	}
	icerik, _ := os.ReadFile(hedef)
	if string(icerik) != "veri" {
		t.Fatalf("kopya yanlis: %q", icerik)
	}
	if c := kopyala(veriIslem{Kaynak: kaynak, Hedef: hedef}); c.Tamam {
		t.Fatal("var olan hedefin uzerine kopyalandi")
	}
}

func TestSilDosyaVeKlasor(t *testing.T) {
	klasor := t.TempDir()
	yol := filepath.Join(klasor, "s.txt")
	os.WriteFile(yol, []byte("x"), 0o644)
	if c := sil(veriIslem{Yol: yol}); !c.Tamam {
		t.Fatalf("silme: %s", c.Hata)
	}
	if _, err := os.Stat(yol); err == nil {
		t.Fatal("dosya silinmedi")
	}
	// Klasor (icerigiyle birlikte) silinebilmeli.
	alt := filepath.Join(klasor, "alt")
	os.MkdirAll(filepath.Join(alt, "ic"), 0o755)
	os.WriteFile(filepath.Join(alt, "ic", "d.txt"), []byte("y"), 0o644)
	if c := sil(veriIslem{Yol: alt}); !c.Tamam {
		t.Fatalf("klasor silme: %s", c.Hata)
	}
	if _, err := os.Stat(alt); err == nil {
		t.Fatal("klasor silinmedi")
	}
	// Surucu koku silinmemeli.
	kok := filepath.VolumeName(klasor) + string(filepath.Separator)
	if c := sil(veriIslem{Yol: kok}); c.Tamam {
		t.Fatal("surucu koku silindi")
	}
}

func TestGoreliYolReddedilir(t *testing.T) {
	if c := listele("relatif\\yol"); c.Tamam {
		t.Fatal("goreli yol kabul edildi")
	}
	if c := sil(veriIslem{Yol: ""}); c.Tamam {
		t.Fatal("bos yol kabul edildi")
	}
}
