package auth

import (
	"context"
	"errors"

	"github.com/gin-gonic/gin"
	"github.com/tidbcloud/account/idl/pbgen/proto/account"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	authsdk "github.com/tidbcloud/tiinf/sdk/auth"
	"go.uber.org/zap"

	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/domain/entity"
)

// get user info with auth0 token
func (a *authServiceImpl) getCurrentUserByAccessToken(
	ctx *gin.Context,
	accessToken *account.GetIdentityByAccessTokenResp,
) (*entity.User, error) {
	if accessToken == nil || accessToken.AccessTokenIdentity == nil {
		tilog.Error(ctx.Request.Context(), "failed to get  accessToken")
		return nil, errors.New("failed to accessToken")
	}

	user := &entity.User{
		User: &account.User{
			Id:    accessToken.AccessTokenIdentity.GetUserId(),
			Email: accessToken.AccessTokenIdentity.GetUserEmail(),
		},
		AccessToken: accessToken.AccessTokenIdentity.RawAccessToken,
		Org: &account.Org{
			Id: accessToken.AccessTokenIdentity.GetOrgId(),
		},
		IdentityType: authsdk.AuthnIdentityTypeAccessToken,
	}

	if !accessToken.AccessTokenIdentity.GrantAllProjects {
		resp, err := a.account.ListProjects(ctx, accessToken.AccessTokenIdentity.ProjectIds)
		if err != nil {
			return nil, err
		}
		user.Projects = resp
	}
	orgId := authsdk.GetOrgIdFromAccessTokenRsp(accessToken)

	prjs, err := a.listProjectsByOrgId(ctx, orgId)
	if err != nil {
		return nil, err
	}
	if len(prjs) == 0 {
		tilog.Error(
			ctx.Request.Context(),
			"no project has permission",
			zap.String("accessToken", accessToken.AccessTokenIdentity.RawAccessToken),
		)
		return nil, errors.New("no project has permission")
	}
	user.Projects = prjs

	return user, nil
}

func (a *authServiceImpl) listProjectsByOrgId(ctx context.Context, orgId uint64) ([]*account.Project, error) {
	in := &account.ListProjectsByOrgsRequest{
		OrgIds: []uint64{orgId},
	}
	resp, err := a.account.GetAccountClient().ListProjectsByOrgs(ctx, in)
	if err != nil {
		return nil, err
	}
	for _, item := range resp.GetProjects() {
		if item.OrgId != orgId {
			continue
		}
		return item.Projects, nil
	}
	return nil, err
}
