package pkg

import (
	"context"
	"github.com/pingcap/errcode"
	"strings"

	"github.com/gogo/protobuf/types"
	"github.com/tidbcloud/debug_portal/idl/pbgen/debug_portal"
	sessionManager "github.com/tidbcloud/debug_portal/session"
)

// for debug usage
func (service *debugPortalService) authN(ctx context.Context) error {
	if service.config.DisableAuthN {
		return nil
	}
	_, err := service.sessionManager.GrpcGetDebugSessionUser(ctx)
	return err
}

func (service *debugPortalService) SignOut(context context.Context, req *debug_portal.DebugPortalSignOutReq) (*debug_portal.DebugPortalSignOutResp, error) {
	_, err := service.sessionManager.GrpcGetDebugSessionUser(context)
	if err != nil {
		return nil, err
	}
	if req.SessionKeyAsCookie {
		_ = sessionManager.GrpcClearCookie(context)
	}
	return &debug_portal.DebugPortalSignOutResp{
		OauthSignOutUri: strings.ReplaceAll(service.config.SignOutURL, "{baseURL}", req.RedirectUri),
	}, nil
}

func (service *debugPortalService) GetOAuthConfig(_ context.Context, req *debug_portal.DebugPortalGetOAuthConfigReq) (*debug_portal.DebugPortalGetOAuthConfigResp, error) {
	url, err := service.oAuthClient.WithRedirectURL(req.RedirectUri).GenerateAuthURL()
	if err != nil {
		return nil, err
	}
	return &debug_portal.DebugPortalGetOAuthConfigResp{
		AuthUrl: url,
	}, nil
}

func (service *debugPortalService) ExchangeOAuthToken(context context.Context, req *debug_portal.DebugPortalExchangeOAuthTokenReq) (*debug_portal.DebugPortalExchangeOAuthTokenResp, error) {
	session, err := service.oAuthClient.WithRedirectURL(req.RedirectUri).Exchange(context, req.State, req.Code)
	if err != nil {
		return nil, err
	}
	token, err := service.sessionManager.NewSession(session)
	if err != nil {
		// NewSession failures must be an internal error
		return nil, errcode.NewInternalErr(err)
	}
	if req.SessionKeyAsCookie {
		_ = sessionManager.GrpcSetCookie(context, token)
	}
	return &debug_portal.DebugPortalExchangeOAuthTokenResp{
		SessionKey: token,
	}, nil
}

func (service *debugPortalService) GetBasicSession(context context.Context, _ *types.Empty) (*debug_portal.DebugPortalGetBasicSessionResp, error) {
	session, err := service.sessionManager.GrpcGetDebugSessionUser(context)
	if err != nil {
		return nil, err
	}
	return &debug_portal.DebugPortalGetBasicSessionResp{
		Email:     session.Email,
		Username:  session.Username,
		CsrfToken: session.CSRFToken,
	}, nil
}
