package api

import (
	"errors"
	"fmt"
	"net/http"

	"github.com/google/uuid"
	"github.com/lestrrat-go/jwx/jwt"

	"reichard.io/imagini/graph/model"
)

func (api *API) refreshTokens(refreshToken jwt.Token) (string, string, error) {
	// Acquire User & Device
	did, ok := refreshToken.Get("did")
	if !ok {
		return "", "", errors.New("Missing DID")
	}
	uid, ok := refreshToken.Get(jwt.SubjectKey)
	if !ok {
		return "", "", errors.New("Missing UID")
	}
	deviceUUID, err := uuid.Parse(fmt.Sprintf("%v", did))
	if err != nil {
		return "", "", errors.New("Invalid DID")
	}
	userUUID, err := uuid.Parse(fmt.Sprintf("%v", uid))
	if err != nil {
		return "", "", errors.New("Invalid UID")
	}

	// Device & User Skeleton
	user := model.User{ID: userUUID.String()}
	device := model.Device{ID: deviceUUID.String()}

	// Find User
	_, err = api.DB.User(&user)
	if err != nil {
		return "", "", err
	}

	// Update Access Token
	accessToken, err := api.Auth.CreateJWTAccessToken(user, device)
	if err != nil {
		return "", "", err
	}

	return accessToken, "", err
}

func (api *API) validateTokens(w *http.ResponseWriter, r *http.Request) (jwt.Token, error) {
	accessTokenHeader := r.Header.Get("X-Imagini-AccessToken")
	if accessTokenHeader != "" {
		accessToken, err := api.Auth.ValidateJWTAccessToken(accessTokenHeader)
		if err == nil {
			return accessToken, nil
		}
	}

	refreshTokenHeader := r.Header.Get("X-Imagini-RefreshToken")
	if refreshTokenHeader == "" {
		return nil, errors.New("Tokens Invalid")
	}

	// Validate Access Token
	// accessCookie, _ := r.Cookie("AccessToken")
	// if accessCookie != nil {
	// 	accessToken, err := api.Auth.ValidateJWTAccessToken(accessCookie.Value)
	// 	if err == nil {
	// 		return accessToken, nil
	// 	}
	// }

	// Validate Refresh Cookie Exists
	// refreshCookie, _ := r.Cookie("RefreshToken")
	// if refreshCookie == nil {
	// 	return nil, errors.New("Tokens Invalid")
	// }

	// Validate Refresh Token
	// refreshToken, err := api.Auth.ValidateJWTRefreshToken(refreshCookie.Value)
	refreshToken, err := api.Auth.ValidateJWTRefreshToken(refreshTokenHeader)
	if err != nil {
		return nil, errors.New("Tokens Invalid")
	}

	// Refresh Access Token & Generate New Refresh Token
	newAccessToken, newRefreshToken, err := api.refreshTokens(refreshToken)
	if err != nil {
		return nil, err
	}

	// TODO: Actually Refresh Refresh Token
	// newRefreshToken = refreshCookie.Value
	newRefreshToken = refreshTokenHeader

	// Set appropriate cookies (TODO: Only for web!)

	// Update Access & Refresh Cookies
	// http.SetCookie(*w, &http.Cookie{
	// 	Name:  "AccessToken",
	// 	Value: newAccessToken,
	// })
	// http.SetCookie(*w, &http.Cookie{
	// 	Name:  "RefreshToken",
	// 	Value: newRefreshToken,
	// })

	(*w).Header().Set("X-Imagini-AccessToken", newAccessToken)
	(*w).Header().Set("X-Imagini-RefreshToken", newRefreshToken)

	return jwt.ParseBytes([]byte(newAccessToken))
}
