package main

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"testing"
)

// eslesmeTestHesap: etkin ve oturumlu bir hesap kurar. Eslesme yazimi oturumlu hesabin
// klasorune yapilir, bu yuzden testlerin once bunu kurmasi gerekir.
func eslesmeTestHesap(t *testing.T) string {
	t.Helper()
	etkinTestKur(t, "ahmet")
	cerez := []*http.Cookie{{Name: "oturum", Value: "test"}}
	if err := oturumYazProfil("ahmet", &oturumKaydi{KullaniciAdi: "ahmet", KullaniciID: "test", Cerezler: cerez}); err != nil {
		t.Fatal(err)
	}
	return "ahmet"
}

// Ayni site tek kayit olmali: tekrar kaydetmede eslesmeler.json sismemeli,
// TokenOzeti guncellenmeli (eski token gecersiz olmali).
// Not: eslesmeKaydetVeyaGuncelle OZET saklar (esleHandler tokenOzeti(token) cagirir);
// eslesmisTokenMi ise HAM token alip ozetler. Bu yuzden kayit tokenOzeti(ham) ile yapilir.
func TestEslesmeKaydetVeyaGuncelleTekKayit(t *testing.T) {
	t.Setenv("APPDATA", t.TempDir())
	eslesmeTestHesap(t)

	if err := eslesmeKaydetVeyaGuncelle(izinliKoken, tokenOzeti("token-a")); err != nil {
		t.Fatal(err)
	}
	if err := eslesmeKaydetVeyaGuncelle(izinliKoken, tokenOzeti("token-b")); err != nil {
		t.Fatal(err)
	}

	liste := eslesmeleriOku()
	if len(liste) != 1 {
		t.Fatalf("tek kayit beklenirdi, %d kayit var", len(liste))
	}
	if liste[0].TokenOzeti != tokenOzeti("token-b") {
		t.Fatalf("TokenOzeti token-b'nin ozeti olmali")
	}
	// Eski token gecersiz, yenisi gecerli.
	if !eslesmisTokenMi("token-b") {
		t.Fatal("yeni token gecerli olmali")
	}
	if eslesmisTokenMi("token-a") {
		t.Fatal("eski token gecersiz olmali")
	}
}

// siteEslesmisMi: kayit varsa true, yoksa false.
func TestSiteEslesmisMi(t *testing.T) {
	t.Setenv("APPDATA", t.TempDir())
	eslesmeTestHesap(t)

	if siteEslesmisMi(izinliKoken) {
		t.Fatal("bos depoda eslesmemis sayilmali")
	}
	if err := eslesmeKaydetVeyaGuncelle(izinliKoken, tokenOzeti("token")); err != nil {
		t.Fatal(err)
	}
	if !siteEslesmisMi(izinliKoken) {
		t.Fatal("kayit sonrasi eslesmis sayilmali")
	}
	if siteEslesmisMi("https://diger.com") {
		t.Fatal("baska site eslesmis sayilmamali")
	}
}

// Eslesme, oturumlu hesabin klasorune yazilmali; eski kok dosya okunmaya devam etmeli.
func TestEslesmeHesapKlasorundeDurur(t *testing.T) {
	t.Setenv("APPDATA", t.TempDir())
	hesap := eslesmeTestHesap(t)

	if err := eslesmeKaydetVeyaGuncelle(izinliKoken, tokenOzeti("token")); err != nil {
		t.Fatal(err)
	}
	if len(eslesmeleriOkuProfil(hesap)) != 1 {
		t.Fatal("eslesme oturumlu hesabin klasorunde olmali")
	}
	if !eslesmisTokenMi("token") {
		t.Fatal("hesap klasorundeki eslesme dogrulanmali")
	}
}

// eslesmeKaldir sonrasi token gecersiz olmali (site yeniden eslesebilir).
func TestEslesmeKaldirSonrasiTokenGecersiz(t *testing.T) {
	t.Setenv("APPDATA", t.TempDir())
	hesap := eslesmeTestHesap(t)

	if err := eslesmeKaydetVeyaGuncelle(izinliKoken, tokenOzeti("token")); err != nil {
		t.Fatal(err)
	}
	if !eslesmisTokenMi("token") {
		t.Fatal("once gecerli olmali")
	}
	// Bos listeye dusur: site artik eslesmemis.
	if err := eslesmeleriYazProfil(hesap, nil); err != nil {
		t.Fatal(err)
	}
	if eslesmisTokenMi("token") {
		t.Fatal("kaldirimdan sonra token gecersiz olmali")
	}
	if siteEslesmisMi(izinliKoken) {
		t.Fatal("kaldirimdan sonra eslesmemis olmali")
	}
}

// eslesmeler.json okunabilir bicimde yazilmali (birden fazla site ayri satir).
func TestEslesmeDosyaBicimi(t *testing.T) {
	t.Setenv("APPDATA", t.TempDir())
	hesap := eslesmeTestHesap(t)

	_ = eslesmeKaydetVeyaGuncelle("https://a.com", tokenOzeti("token-a"))
	_ = eslesmeKaydetVeyaGuncelle("https://b.com", tokenOzeti("token-b"))

	klasor, err := profilKlasorP(hesap)
	if err != nil {
		t.Fatal(err)
	}
	yol := filepath.Join(klasor, "eslesmeler.json")
	veri, err := os.ReadFile(yol)
	if err != nil {
		t.Fatal(err)
	}
	var liste []eslesme
	if json.Unmarshal(veri, &liste) != nil || len(liste) != 2 {
		t.Fatalf("iki ayri site beklenirdi: %s", filepath.Base(yol))
	}
}

// POST /ayarlar/eslesme-kaldir: eslesme dosyasindan duser, site yetkileri silinir,
// o sitenin token'i artik gecersiz olur. CSRF/oturum yoksa handler katmaninda reddedilir.
func TestEslesmeKaldirHandler(t *testing.T) {
	t.Setenv("APPDATA", t.TempDir())
	yetkiBellekSifirla()
	profilTokenKur(t, "ahmet", "token")
	etkinTestKur(t, "ahmet")

	ozet := tokenOzeti("token")
	if err := yetkiVerProfil("ahmet", "everythingAra", ozet, siteYetkiSuresi); err != nil {
		t.Fatal(err)
	}

	govde, _ := json.Marshal(map[string]string{"profil": "ahmet", "ozet": ozet})
	istek := httptest.NewRequest(http.MethodPost, "/ayarlar/eslesme-kaldir", bytes.NewReader(govde))
	kayit := httptest.NewRecorder()
	eslesmeKaldirCekirdek(kayit, istek)
	if kayit.Code != http.StatusOK {
		t.Fatalf("kaldirma basarisiz: %d %s", kayit.Code, kayit.Body.String())
	}
	if len(eslesmeleriOkuProfil("ahmet")) != 0 {
		t.Fatal("kaldirimdan sonra hesapta eslesme kalmamali")
	}
	if eslesmisTokenMi("token") {
		t.Fatal("kaldirimdan sonra token gecersiz olmali")
	}
	if yetkiGecerliMiProfil("ahmet", "everythingAra", ozet) {
		t.Fatal("kaldirimdan sonra site yetkisi dusmeli")
	}
}
