package oauth2

import (
	"errors"
	"strconv"
	"strings"

	oauth_err "github.com/tidbcloud/auth-server/commons/errs"
)

type InnerAuthorizationCodeCheckRequest struct {
	ClientID     string `form:"client_id" json:"client_id"`
	ResponseType string `form:"response_type" json:"response_type"`
	RedirectURI  string `form:"redirect_uri" json:"redirect_uri"`
	Scope        string `form:"scope" json:"scope"`
	State        string `form:"state" json:"state"`

	parsedScopes []string
}

func (r *InnerAuthorizationCodeCheckRequest) Validate() error {
	if r.ClientID == "" {
		return oauth_err.ErrOauth2InvalidClient
	}

	// scope is a space-delimited list of strings.
	r.parsedScopes = strings.Fields(r.Scope)
	return nil
}

func (r *InnerAuthorizationCodeCheckRequest) GetParsedScopes() []string {
	return r.parsedScopes
}

type Application struct {
	Name         string `json:"name"`
	LogoURILight string `json:"logo_uri_light,omitempty"`
	LogoURIDark  string `json:"logo_uri_dark,omitempty"`
	HomePageURI  string `json:"home_page_uri,omitempty"`
}

type InnerAuthorizationCodeResponse struct {
	InnerBasicResponse

	Application  *Application `json:"application,omitempty"`
	NeedRedirect bool         `json:"need_redirect"`
	RedirectTo   string       `json:"redirect_to"`
}

type InnerAuthorizationCodeConfirmationRequest struct {
	ClientID     string `form:"client_id" json:"client_id"`
	ResponseType string `form:"response_type" json:"response_type"`
	RedirectURI  string `form:"redirect_uri" json:"redirect_uri"`
	Scope        string `form:"scope" json:"scope"`
	State        string `form:"state" json:"state"`
	// Accept OrgId & ProjectID as a string to prevent overflow in the frontend.
	OrgID      string   `json:"org_id"`
	ProjectIDs []string `json:"project_ids"`

	parsedOrgID      uint64
	parsedProjectIDs []uint64
	parsedScopes     []string
}

func (r *InnerAuthorizationCodeConfirmationRequest) Validate() error {
	if r.ClientID == "" {
		return oauth_err.ErrOauth2InvalidClient
	}

	if r.OrgID == "" {
		return errors.New("org_id is required")
	}

	//if len(r.ProjectIDs) == 0 {
	//	return errors.New("project_ids can not be empty")
	//}

	parseOrgId, err := strconv.ParseUint(r.OrgID, 10, 64)
	if err != nil {
		return errors.New("org_id is invalid")
	}
	r.parsedOrgID = parseOrgId

	for _, projectID := range r.ProjectIDs {
		parseProjectID, err := strconv.ParseUint(projectID, 10, 64)
		if err != nil {
			return errors.New("project_ids is invalid")
		}
		r.parsedProjectIDs = append(r.parsedProjectIDs, parseProjectID)
	}

	// scope is a space-delimited list of strings.
	r.parsedScopes = strings.Fields(r.Scope)
	return nil
}

func (r *InnerAuthorizationCodeConfirmationRequest) GetParsedOrgID() uint64 {
	return r.parsedOrgID
}

func (r *InnerAuthorizationCodeConfirmationRequest) GetParsedProjectIDs() []uint64 {
	return r.parsedProjectIDs
}

func (r *InnerAuthorizationCodeConfirmationRequest) GetParsedScopes() []string {
	return r.parsedScopes
}
