package handlers

import (
	"errors"
	"log"
	"net/http"
	"os"
	"strings"
	"strconv"
	
	"hyperia/db"

	"github.com/alexedwards/argon2id"
)

type loginRequest struct {
	Email     string `json:"email"`
	Password string `json:"password"`
}

type user struct {
	ID   int    `json:"id"`
	Email string `json:"email"`
}

func HandleLogin(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Only POST allowed", http.StatusMethodNotAllowed)
		return
	}

	var creds loginRequest
	if err := r.ParseForm(); err != nil {
		http.Error(w, "Unable to parse form", http.StatusBadRequest)
		return
	}

	email := r.FormValue("email")
	password := r.FormValue("password")
	creds.Email = email
	creds.Password = password

	user, err := getUserByCredentials(creds)
	if err != nil || user == nil {
		http.Error(w, "Unauthorized: "+ err.Error(), http.StatusUnauthorized)
		return
	}

	keyInt, err := strconv.Atoi(user["key"].(string))
	if err != nil {
		// This means the string couldn't be parsed as an int — handle it
		log.Println("user['key'] is not a valid int:", err)
		http.Error(w, "internal server error", http.StatusInternalServerError)
		return
	}

	jwtToken, err := GenerateJWT(keyInt)
	if err != nil {
		log.Println("JWT generation error:", err)
		http.Error(w, "Failed to generate auth token", http.StatusInternalServerError)
		return
	}

	cookie := &http.Cookie{
		Name:     "auth_token",
		Value:    jwtToken,
		Path:     "/",
		HttpOnly: true,
		Domain:   "." + os.Getenv("BASE_URL"), 		// or ".localhost" — this allows subdomains
		Secure:   true,             // default to true (production)
		MaxAge:   2 * 60 * 60,
		SameSite: http.SameSiteLaxMode,
	}

	http.SetCookie(w, cookie)
	http.Redirect(w, r, "/", http.StatusSeeOther)
}

func getUserByCredentials(loginCreds loginRequest) (map[string]interface{}, error) {

	email := strings.TrimSpace(strings.ToLower(loginCreds.Email))
	
	user, err := db.Get.UserByEmail(email)
	if err != nil {
		return nil, errors.New("user not found")
	}

	dbPassword, ok := user["password"].(string)
	if !ok {
		return nil, errors.New("password format is invalid")
	}

	log.Println("pass: ", loginCreds, loginCreds.Password, dbPassword)

	match, err := argon2id.ComparePasswordAndHash(loginCreds.Password, dbPassword)
	if err != nil || !match {
		return nil, errors.New("invalid password")
	}

	return user, nil
}