package main

// POST /eklenti/kur (token + oturum). Web yalnizca ISTEK gonderir; kurulum PC'de onaylanir.
// Kurulum mantigi eklentiKurOnayli'de; hem bu HTTP ucu hem soket istegi ayni yolu kullanir.

import (
	"encoding/json"
	"errors"
	"net/http"
)

type eklentiKurIstegi struct {
	Anahtar string `json:"anahtar"`
	Surum   string `json:"surum"`
	Sha256  string `json:"sha256"`
	Imza    string `json:"imza"`
	Bicim   string `json:"bicim"`
	Acilis  bool   `json:"acilis"`
	Url     string `json:"url"`
}

var errKullaniciRed = errors.New("kullanici kurulumu reddetti")

// eklentiKurOnayli: dogrular -> PC'de onay ister -> indirir -> imzayi dogrulayip kurar.
// Donen kod HTTP durum kodudur; 200 basaridir.
func eklentiKurOnayli(profil string, p paketBilgisi, url string) (int, error) {
	if err := paketAlanlariGecerli(p); err != nil {
		return http.StatusBadRequest, err
	}
	if err := izinliIndirmeAdresi(url); err != nil {
		return http.StatusBadRequest, err
	}
	if paketAcikAnahtar == "" {
		return http.StatusServiceUnavailable, errPaketAnahtarYok
	}
	onay, err := onayBekle(
		hesapBaslik(profil, "fikoyt.com "+p.Anahtar+" "+p.Surum+" eklentisini kurmak istiyor"),
		"Eklenti bu bilgisayarda ayrı bir süreç olarak çalışır. Yetkileri yalnızca sizin verdiğiniz kadar kullanır. Dilediğiniz zaman devre dışı bırakabilir veya kaldırabilirsiniz.",
	)
	if errors.Is(err, errMesgul) {
		return http.StatusTooManyRequests, err
	}
	if err != nil {
		return http.StatusInternalServerError, err
	}
	if !onay {
		return http.StatusForbidden, errKullaniciRed
	}
	// Acilis bayragi imzali v2 pakette varsa ayrica onay alinir. Imza kurulumda yine dogrulanir.
	acilistaOnayli := false
	if acilisiIstiyor(p) {
		acilistaOnayli, err = onayBekle(
			hesapBaslik(profil, p.Anahtar+" bilgisayar acildiginda otomatik baslasin mi?"),
			"Bu eklenti Windows açıldığında kendiliğinden çalışır. Dilediğiniz zaman kapatabilirsiniz.",
		)
		if err != nil {
			return http.StatusInternalServerError, err
		}
	}
	veri, err := paketIndir(url)
	if err != nil {
		olayLog("eklenti indirilemedi: %s %s: %v", p.Anahtar, p.Surum, err)
		return http.StatusBadGateway, err
	}
	if err := eklentiKur(profil, p, veri); err != nil {
		olayLog("eklenti kurulamadi: %s %s: %v", p.Anahtar, p.Surum, err)
		return http.StatusBadRequest, err
	}
	if acilistaOnayli {
		if err := kuruluAcilistaAyarlaProfil(profil, p.Anahtar, true); err != nil {
			olayLog("acilis ayari kaydedilemedi: %s: %v", p.Anahtar, err)
		}
	}
	eklentiDurumGonder()
	return http.StatusOK, nil
}

func eklentiKurHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "yalnizca POST", http.StatusMethodNotAllowed)
		return
	}
	var istek eklentiKurIstegi
	if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, 4096)).Decode(&istek); err != nil {
		http.Error(w, "gecersiz istek", http.StatusBadRequest)
		return
	}
	p := paketBilgisi{Anahtar: istek.Anahtar, Surum: istek.Surum, Sha256: istek.Sha256, Imza: istek.Imza, Bicim: istek.Bicim, Acilis: istek.Acilis}
	kod, err := eklentiKurOnayli(profilDe(r), p, istek.Url)
	switch {
	case kod == http.StatusOK:
		yazJSON(w, http.StatusOK, map[string]any{"ok": true})
	case errors.Is(err, errKullaniciRed):
		yazJSON(w, http.StatusForbidden, map[string]any{"hata": "kullanici kurulumu reddetti"})
	case errors.Is(err, errMesgul):
		yazJSON(w, http.StatusTooManyRequests, map[string]any{"hata": "baska bir onay bekleniyor"})
	case kod == http.StatusServiceUnavailable:
		http.Error(w, "eklenti kurulumu bu surumde kapali", kod)
	case kod == http.StatusBadGateway:
		http.Error(w, "indirilemedi", kod)
	case kod == http.StatusInternalServerError:
		http.Error(w, "onay ekrani acilamadi", kod)
	case kod == http.StatusBadRequest:
		http.Error(w, "dogrulama basarisiz: "+err.Error(), kod)
	default:
		http.Error(w, err.Error(), kod)
	}
}
