package Auth

import (
	"database/sql/driver"
	"encoding/json"
	"net/http"
	"time"

	"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
	"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)

type credentials struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type loginResponse struct {
	UserID               string `json:"user_id"`
	Username             string `json:"username"`
	AsymmetricPublicKey  string `json:"asymmetric_public_key"`
	AsymmetricPrivateKey string `json:"asymmetric_private_key"`
	SymmetricKey         string `json:"symmetric_key"`
	MessageExpiryDefault string `json:"message_expiry_default"`
	ImageLink            string `json:"image_link"`
}

// Login logs the user into the system
func Login(w http.ResponseWriter, r *http.Request) {
	var (
		creds            credentials
		user             Models.User
		session          Models.Session
		expiresAt        time.Time
		messageExpiryRaw driver.Value
		messageExpiry    string
		imageLink        string
		returnJSON       []byte
		err              error
	)

	err = json.NewDecoder(r.Body).Decode(&creds)
	if err != nil {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	user, err = Database.GetUserByUsername(creds.Username)
	if err != nil {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	if !CheckPasswordHash(creds.Password, user.Password) {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	// TODO: Revisit before production
	expiresAt = time.Now().Add(12 * time.Hour)

	session = Models.Session{
		UserID: user.ID,
		Expiry: expiresAt,
	}

	err = Database.CreateSession(&session)
	if err != nil {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	http.SetCookie(w, &http.Cookie{
		Name:    "session_token",
		Value:   session.ID.String(),
		Expires: expiresAt,
	})

	if user.AttachmentID != nil {
		imageLink = user.Attachment.FilePath
	}

	messageExpiryRaw, _ = user.MessageExpiryDefault.Value()
	messageExpiry, _ = messageExpiryRaw.(string)

	returnJSON, err = json.MarshalIndent(loginResponse{
		UserID:               user.ID.String(),
		Username:             user.Username,
		AsymmetricPublicKey:  user.AsymmetricPublicKey,
		AsymmetricPrivateKey: user.AsymmetricPrivateKey,
		SymmetricKey:         user.SymmetricKey,
		MessageExpiryDefault: messageExpiry,
		ImageLink:            imageLink,
	}, "", "  ")

	if err != nil {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	// Return updated json
	w.WriteHeader(http.StatusOK)
	w.Write(returnJSON)
}
