package auth

import (
	"context"
	"strings"

	"apps/backend/internal/module/member/domain"
	"apps/backend/internal/svc"
	"apps/backend/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type OAuthCallbackLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewOAuthCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OAuthCallbackLogic {
	return &OAuthCallbackLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx}
}

func (l *OAuthCallbackLogic) OAuthCallback(req *types.AuthOAuthCallbackReq) (resp *types.AuthSessionData, err error) {
	provider := strings.ToLower(strings.TrimSpace(req.Provider))
	if provider == "" {
		provider = domain.PlatformGoogle
	}

	var subject, email, name string
	switch provider {
	case domain.PlatformGoogle:
		token := strings.TrimSpace(req.IdToken)
		if token == "" {
			return nil, domain.ErrOAuthFailed
		}
		subject, email, name, err = l.svcCtx.Auth.VerifyGoogleIDToken(l.ctx, token)
		if err != nil {
			return nil, err
		}
	case domain.PlatformLine:
		code := req.Code
		if code == "" {
			code = req.AccessToken
		}
		subject, name, email, err = l.svcCtx.Auth.LineCodeToProfile(l.ctx, code, req.RedirectUri)
		if err != nil {
			return nil, err
		}
	default:
		return nil, domain.ErrOAuthFailed
	}

	m, pair, err := l.svcCtx.Auth.LoginOAuth(l.ctx, provider, subject, email, name)
	if err != nil {
		return nil, err
	}
	ids, _ := l.svcCtx.Auth.ListIdentities(l.ctx, m.UID)
	return &types.AuthSessionData{
		Tokens: types.TokenPairFromAuth(pair.AccessToken, pair.RefreshToken, pair.TokenType, pair.ExpiresIn),
		Member: *types.MemberFromModelWithIdentities(m, ids),
	}, nil
}
