// Copyright (C) 2024 veypi <i@veypi.com>
// 2025-03-04 16:08:06
// Distributed under terms of the MIT license.

package oauth

import (
	"time"

	"github.com/veypi/vbase/cfg"
	"github.com/veypi/vbase/libs/cache"
	"github.com/veypi/vbase/libs/crypto"
	"github.com/veypi/vbase/models"
	"github.com/veypi/vigo"
)

type AuthorizeRequest struct {
	ResponseType string `json:"response_type" src:"query" desc:"授权类型"`
	ClientID     string `json:"client_id" src:"query" desc:"客户端ID"`
	RedirectURI  string `json:"redirect_uri" src:"query" desc:"重定向URI"`
	Scope        string `json:"scope" src:"query" desc:"授权范围"`
	State        string `json:"state" src:"query" desc:"状态值"`
}

type AuthorizeResponse struct {
	Code  string `json:"code"`
	State string `json:"state"`
}

func authorize(x *vigo.X, req *AuthorizeRequest) (*AuthorizeResponse, error) {
	// 验证客户端
	var client models.OAuthClient
	if err := cfg.DB().First(&client, "client_id = ?", req.ClientID).Error; err != nil {
		return nil, vigo.ErrUnauthorized.WithString("invalid client")
	}

	if client.Status != models.OAuthClientStatusActive {
		return nil, vigo.ErrForbidden.WithString("client is disabled")
	}

	// 获取当前用户
	userID := cfg.Auth.UserID(x)
	if userID == "" {
		return nil, vigo.ErrUnauthorized
	}

	// 生成授权码
	code := crypto.GenerateSecret(32)

	// 缓存授权码
	authData := map[string]any{
		"client_id":    req.ClientID,
		"user_id":      userID,
		"redirect_uri": req.RedirectURI,
		"scope":        req.Scope,
	}
	if err := cache.SetObject(cache.OAuthCodeKey(code), authData, time.Minute*10); err != nil {
		return nil, vigo.ErrInternalServer.WithError(err)
	}

	return &AuthorizeResponse{
		Code:  code,
		State: req.State,
	}, nil
}
