package main

// Izin istegi gecmisi ve aktif izin yardimcilari.
// Her hesabin gecmisi kendi klasorunde (izin-gecmisi.json) tutulur; en fazla izinGecmisiLimit kayit.

import (
	"encoding/json"
	"os"
	"path/filepath"
	"sync"
	"time"
)

const izinGecmisiLimit = 200

// izinGecmisKaydi: bir izin istegi ya da iptali. Tur: "site" veya "dosya".
// Sonuc: verildi | reddedildi | mesgul | hata | iptal.
type izinGecmisKaydi struct {
	Zaman   time.Time `json:"zaman"`
	Tur     string    `json:"tur"`
	Anahtar string    `json:"anahtar"`
	Site    string    `json:"site"`
	Sonuc   string    `json:"sonuc"`
}

var izinGecmisiMu sync.Mutex

func izinGecmisiYolu(profil string) (string, error) {
	klasor, err := profilKlasorP(profil)
	if err != nil {
		return "", err
	}
	return filepath.Join(klasor, "izin-gecmisi.json"), nil
}

// izinGecmisiEkle: kaydi hesabin gecmisine ekler. Hata olursa yalnizca gunlege yazar; istegi bozmaz.
func izinGecmisiEkle(profil string, k izinGecmisKaydi) {
	if profil == "" {
		return
	}
	izinGecmisiMu.Lock()
	defer izinGecmisiMu.Unlock()
	yol, err := izinGecmisiYolu(profil)
	if err != nil {
		return
	}
	var liste []izinGecmisKaydi
	if veri, err := os.ReadFile(yol); err == nil {
		_ = json.Unmarshal(veri, &liste)
	}
	if k.Zaman.IsZero() {
		k.Zaman = time.Now()
	}
	liste = append(liste, k)
	if len(liste) > izinGecmisiLimit {
		liste = liste[len(liste)-izinGecmisiLimit:]
	}
	veri, err := json.MarshalIndent(liste, "", "  ")
	if err != nil {
		return
	}
	if err := os.WriteFile(yol, veri, 0o600); err != nil {
		olayLog("izin gecmisi yazilamadi: %v", err)
	}
}

// izinGecmisiOku: hesabin gecmisi, en yeni once.
func izinGecmisiOku(profil string) []izinGecmisKaydi {
	izinGecmisiMu.Lock()
	defer izinGecmisiMu.Unlock()
	yol, err := izinGecmisiYolu(profil)
	if err != nil {
		return nil
	}
	veri, err := os.ReadFile(yol)
	if err != nil {
		return nil
	}
	var liste []izinGecmisKaydi
	_ = json.Unmarshal(veri, &liste)
	for i, j := 0, len(liste)-1; i < j; i, j = i+1, j-1 {
		liste[i], liste[j] = liste[j], liste[i]
	}
	return liste
}

// siteAdiOzetten: eslesme tokeninin ozetinden site adini bulur.
func siteAdiOzetten(profil, ozet string) string {
	for _, e := range eslesmeleriOkuProfil(profil) {
		if e.TokenOzeti == ozet {
			return e.Site
		}
	}
	return "Bilinmeyen site"
}

// izinKisaAdi: izin anahtarinin kullanici dostu adi.
func izinKisaAdi(anahtar string) string {
	switch anahtar {
	case "everythingAra":
		return "Dosya arama"
	case "catiaAc":
		return "CATIA açma"
	case "usb":
		return "USB bağlantısı"
	case "dosyaYonetimi":
		return "Dosya yöneticisi"
	}
	return anahtar
}

// aktifSiteIzni: suresi dolmamis bir site yetkisi.
type aktifSiteIzni struct {
	Anahtar string
	Site    string
	Ozet    string
	Bitis   time.Time
}

// aktifSiteIzinleri: profilin suresi dolmamis site yetkileri.
func aktifSiteIzinleri(profil string) []aktifSiteIzni {
	yetkiMu.Lock()
	liste := append([]yetkiKaydi(nil), yetkiListeAlLocked(profil)...)
	yetkiMu.Unlock()
	simdi := time.Now()
	var out []aktifSiteIzni
	for _, k := range liste {
		if k.Bitis.After(simdi) {
			out = append(out, aktifSiteIzni{Anahtar: k.Anahtar, Site: siteAdiOzetten(profil, k.Eslesme), Ozet: k.Eslesme, Bitis: k.Bitis})
		}
	}
	return out
}

// yetkiAnahtarlari: profilde yetkisi kayitli olan tum izin anahtarlari (tekil).
func yetkiAnahtarlari(profil string) []string {
	yetkiMu.Lock()
	defer yetkiMu.Unlock()
	gorulen := map[string]bool{}
	var out []string
	for _, k := range yetkiListeAlLocked(profil) {
		if !gorulen[k.Anahtar] {
			gorulen[k.Anahtar] = true
			out = append(out, k.Anahtar)
		}
	}
	return out
}

// tumIzinleriIptalEt: hesabin tum site yetkilerini, klasor izinlerini ve izin bayraklarini kapatir.
func tumIzinleriIptalEt(profil string) error {
	for _, a := range yetkiAnahtarlari(profil) {
		if err := yetkiGeriAlProfil(profil, a, ""); err != nil {
			return err
		}
	}
	if err := izinleriKaydetProfil(profil, Izinler{}); err != nil {
		return err
	}
	if err := dosyaIzinleriKaydet(profil, DosyaIzinleri{}); err != nil {
		return err
	}
	izinDurumGonderProfil(profil)
	return nil
}
