package handlers

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"strings"

	"mgit.msbls.de/m/paliad/internal/auth"
	"mgit.msbls.de/m/paliad/internal/branding"
)

func handleLoginPage(w http.ResponseWriter, r *http.Request) {
	if cookie, err := r.Cookie(auth.SessionCookieName); err == nil && cookie.Value != "" {
		if _, err := authClient.VerifyToken(cookie.Value); err == nil {
			http.Redirect(w, r, "/", http.StatusFound)
			return
		}
	}
	http.ServeFile(w, r, "dist/login.html")
}

func handleAPILogin(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Email    string `json:"email"`
		Password string `json:"password"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Ungültige Anfrage."})
		return
	}

	req.Email = strings.TrimSpace(req.Email)
	if req.Email == "" || req.Password == "" {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Bitte E-Mail und Passwort eingeben."})
		return
	}

	if !isAllowedEmailDomain(req.Email) {
		writeJSON(w, http.StatusForbidden, map[string]string{"error": "Zugang nur für autorisierte " + branding.Name + "-E-Mail-Adressen."})
		return
	}

	tokens, err := authClient.SignIn(req.Email, req.Password)
	if err != nil {
		log.Printf("sign in failed for %s: %v", req.Email, err)
		errMsg := "Anmeldung fehlgeschlagen. Bitte versuchen Sie es erneut."
		if strings.Contains(err.Error(), "Invalid login credentials") {
			errMsg = "Ungültige E-Mail-Adresse oder Passwort."
		}
		writeJSON(w, http.StatusUnauthorized, map[string]string{"error": errMsg})
		return
	}

	auth.SetAuthCookies(w, r, tokens)
	writeJSON(w, http.StatusOK, map[string]string{"ok": "true"})
}

func handleAPIRegister(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Email    string `json:"email"`
		Password string `json:"password"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Ungültige Anfrage."})
		return
	}

	req.Email = strings.TrimSpace(req.Email)
	if req.Email == "" || req.Password == "" {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Bitte alle Felder ausfüllen."})
		return
	}

	if len(req.Password) < 8 {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Passwort muss mindestens 8 Zeichen lang sein."})
		return
	}

	if !isAllowedEmailDomain(req.Email) {
		writeJSON(w, http.StatusForbidden, map[string]string{"error": "Registrierung nur für autorisierte " + branding.Name + "-E-Mail-Adressen."})
		return
	}

	tokens, err := authClient.SignUp(req.Email, req.Password)
	if err != nil {
		log.Printf("sign up failed for %s: %v", req.Email, err)
		errMsg := "Registrierung fehlgeschlagen. Bitte versuchen Sie es erneut."
		if strings.Contains(err.Error(), "already registered") || strings.Contains(err.Error(), "already been registered") {
			errMsg = "Ein Account mit dieser E-Mail existiert bereits."
		}
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": errMsg})
		return
	}

	if tokens != nil {
		auth.SetAuthCookies(w, r, tokens)
		writeJSON(w, http.StatusOK, map[string]string{"redirect": "/"})
		return
	}

	writeJSON(w, http.StatusOK, map[string]string{"message": "Account erstellt. Bitte melden Sie sich an."})
}

func handleLogout(w http.ResponseWriter, r *http.Request) {
	if cookie, err := r.Cookie(auth.SessionCookieName); err == nil {
		authClient.SignOut(cookie.Value)
	}
	auth.ClearAuthCookies(w)
	http.Redirect(w, r, "/login", http.StatusFound)
}

// isAllowedEmailDomain gates sign-in/register to the firm's email domains.
// Whitelist is configurable via ALLOWED_EMAIL_DOMAINS (comma-separated),
// defaulting to hoganlovells.com,hlc.com,hlc.de so legacy and post-merger
// addresses keep working until IT finishes the domain consolidation.
// Note: this whitelist intentionally references real DNS domains, not
// branding.Name — the firm's email domains and the firm's display name are
// separate concerns and rotate on different cadences.
func isAllowedEmailDomain(email string) bool {
	parts := strings.SplitN(email, "@", 2)
	if len(parts) != 2 {
		return false
	}
	domain := strings.ToLower(parts[1])
	for _, allowed := range AllowedEmailDomains() {
		if domain == allowed {
			return true
		}
	}
	return false
}

func AllowedEmailDomains() []string {
	raw := os.Getenv("ALLOWED_EMAIL_DOMAINS")
	if strings.TrimSpace(raw) == "" {
		return []string{"hoganlovells.com", "hlc.com", "hlc.de"}
	}
	var out []string
	for _, d := range strings.Split(raw, ",") {
		d = strings.TrimSpace(strings.ToLower(d))
		if d != "" {
			out = append(out, d)
		}
	}
	return out
}
