package main

// Ilk acilis girisi. Mevcut fikoyt.com giris endpoint'i kullanilir (web arayuzu ile ayni):
//   POST /fapiv1/fikoyt.com.FikoYT.sistem.giris.yap
//   multipart/form-data, alan: req_body = {"kullaniciAdi":"...","parola":"..."} (JSON metni)
// Basarili girisde sunucu oturum cerezi (Set-Cookie) doner. Bridge bu cerezleri
// yerel oturum.json dosyasinda saklar. Parola yalnizca bu istek sirasinda HTTPS ile
// fikoyt.com'a gider; diske yazilmaz.

import (
	"bytes"
	"encoding/json"
	"errors"
	"html"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

const girisAdres = "https://fikoyt.com:9000/fapiv1/fikoyt.com.FikoYT.sistem.giris.yap"

type oturumKaydi struct {
	KullaniciAdi string         `json:"kullaniciAdi"`
	Cerezler     []*http.Cookie `json:"cerezler"`
}

func oturumYolu() (string, error) {
	klasor, err := veriKlasoru()
	if err != nil {
		return "", err
	}
	return filepath.Join(klasor, "oturum.json"), nil
}

func oturumOku() (*oturumKaydi, error) {
	yol, err := oturumYolu()
	if err != nil {
		return nil, err
	}
	veri, err := os.ReadFile(yol)
	if err != nil {
		return nil, err
	}
	var k oturumKaydi
	if err := json.Unmarshal(veri, &k); err != nil {
		return nil, err
	}
	if len(k.Cerezler) == 0 {
		return nil, errors.New("oturum cerezi yok")
	}
	return &k, nil
}

func oturumYaz(k *oturumKaydi) error {
	yol, err := oturumYolu()
	if err != nil {
		return err
	}
	veri, err := json.MarshalIndent(k, "", "  ")
	if err != nil {
		return err
	}
	return os.WriteFile(yol, veri, 0o600)
}

func oturumSil() {
	if yol, err := oturumYolu(); err == nil {
		os.Remove(yol)
	}
}

// oturumGerekli: giris yapilmamissa korunan ucu 401 ile kapatir.
func oturumGerekli(h http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if _, err := oturumOku(); err != nil {
			yazJSON(w, http.StatusUnauthorized, map[string]any{"hata": "giris gerekli"})
			return
		}
		h(w, r)
	}
}

// girisHandler: GET formu gosterir, POST kimligi fikoyt.com'a dogrulatir.
func girisHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		w.Header().Set("Cache-Control", "no-store")
		w.Write([]byte(girisSayfasi("")))
	case http.MethodPost:
		if err := r.ParseForm(); err != nil {
			http.Error(w, "gecersiz form", http.StatusBadRequest)
			return
		}
		kullanici := strings.TrimSpace(r.PostFormValue("kullaniciAdi"))
		parola := r.PostFormValue("parola")
		if kullanici == "" || parola == "" {
			w.Header().Set("Content-Type", "text/html; charset=utf-8")
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte(girisSayfasi("Kullanıcı adı ve parola zorunlu.")))
			return
		}
		kayit, err := fikoytGirisYap(kullanici, parola)
		if err != nil {
			olayLog("giriş denemesi başarısız (%s): %v", kullanici, err)
			w.Header().Set("Content-Type", "text/html; charset=utf-8")
			w.WriteHeader(http.StatusUnauthorized)
			w.Write([]byte(girisSayfasi("Giriş başarısız: " + err.Error())))
			return
		}
		olayLog("giriş yapıldı: %s", kayit.KullaniciAdi)
		if err := oturumYaz(kayit); err != nil {
			http.Error(w, "oturum kaydedilemedi", http.StatusInternalServerError)
			return
		}
		http.Redirect(w, r, "/", http.StatusSeeOther)
	default:
		http.Error(w, "yalnizca GET/POST", http.StatusMethodNotAllowed)
	}
}

// oturumKapatHandler: yerel oturumu siler.
func oturumKapatHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "yalnizca POST", http.StatusMethodNotAllowed)
		return
	}
	oturumSil()
	yazJSON(w, http.StatusOK, map[string]any{"ok": true})
}

func fikoytGirisYap(kullanici, parola string) (*oturumKaydi, error) {
	reqBody, _ := json.Marshal(map[string]string{"kullaniciAdi": kullanici, "parola": parola})

	var govde bytes.Buffer
	mw := multipart.NewWriter(&govde)
	if err := mw.WriteField("req_body", string(reqBody)); err != nil {
		return nil, err
	}
	mw.Close()

	istemci := &http.Client{
		Timeout: 15 * time.Second,
		CheckRedirect: func(*http.Request, []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	istek, err := http.NewRequest(http.MethodPost, girisAdres, &govde)
	if err != nil {
		return nil, err
	}
	istek.Header.Set("Content-Type", mw.FormDataContentType())
	istek.Header.Set("Accept", "application/json")

	yanit, err := istemci.Do(istek)
	if err != nil {
		return nil, errors.New("sunucuya ulasilamadi")
	}
	defer yanit.Body.Close()
	icerik, _ := io.ReadAll(io.LimitReader(yanit.Body, 1<<20))

	// Sunucu hata durumunda {"sonuc":{"body":{"durum":{"hata":true,"hatalar":[{"mesaj":...}]}}}}
	// ya da dogrudan {"durum":{...}} donebilir; ikisini de dene.
	var cevap map[string]any
	mesajlar := []string{}
	if json.Unmarshal(icerik, &cevap) == nil {
		durum, _ := cevap["durum"].(map[string]any)
		if durum == nil {
			if sonuc, ok := cevap["sonuc"].(map[string]any); ok {
				if b, ok := sonuc["body"].(map[string]any); ok {
					durum, _ = b["durum"].(map[string]any)
				}
			}
		}
		if durum != nil {
			if hata, _ := durum["hata"].(bool); hata {
				if hs, ok := durum["hatalar"].([]any); ok {
					for _, h := range hs {
						if hm, ok := h.(map[string]any); ok {
							if m, ok := hm["mesaj"].(string); ok && m != "" {
								mesajlar = append(mesajlar, m)
							}
						}
					}
				}
				if len(mesajlar) == 0 {
					mesajlar = append(mesajlar, "sunucu hata dondu (HTTP "+http.StatusText(yanit.StatusCode)+")")
				}
				return nil, errors.New(strings.Join(mesajlar, " "))
			}
		}
	}
	if yanit.StatusCode != http.StatusOK {
		return nil, errors.New("sunucu HTTP " + http.StatusText(yanit.StatusCode) + " dondu")
	}
	cerezler := yanit.Cookies()
	if len(cerezler) == 0 {
		return nil, errors.New("sunucu oturum cerezi vermedi")
	}
	return &oturumKaydi{KullaniciAdi: kullanici, Cerezler: cerezler}, nil
}

// fikoytIstekCerezleri: sonraki fikoyt.com isteklerine kayitli oturum cerezlerini ekler.
func fikoytIstekCerezleri(istek *http.Request) error {
	k, err := oturumOku()
	if err != nil {
		return err
	}
	for _, c := range k.Cerezler {
		istek.AddCookie(c)
	}
	return nil
}

func girisSayfasi(hata string) string {
	mesaj := ""
	if hata != "" {
		mesaj = `<p class="hata">` + html.EscapeString(hata) + `</p>`
	}
	return `<!doctype html><html lang="tr"><head><meta charset="utf-8">
<title>FikoYT Yerel Köprü - Giriş</title>
<style>
body{font-family:system-ui,sans-serif;background:#111;color:#eee;display:flex;min-height:100vh;align-items:center;justify-content:center;margin:0}
form{background:#1b1b1b;padding:24px;border-radius:8px;width:300px}
input{width:100%;padding:8px;margin:6px 0 12px;box-sizing:border-box;background:#222;color:#eee;border:1px solid #333;border-radius:4px}
button{width:100%;padding:10px;background:#2b6cb0;color:#fff;border:0;border-radius:4px;cursor:pointer}
.hata{color:#f88}
</style></head><body>
<form method="post" action="/giris">
<h3>FikoYT Yerel Köprü</h3>
<p>Devam etmek için fikoyt.com hesabınızla giriş yapın.</p>
` + mesaj + `
<label>Kullanıcı adı</label><input name="kullaniciAdi" autocomplete="username" required>
<label>Parola</label><input name="parola" type="password" autocomplete="current-password" required>
<button type="submit">Giriş yap</button>
</form></body></html>`
}
