package auth

import (
	"context"
	"strings"
	"time"

	domauth "gateway/internal/model/auth/domain/usecase"
	"gateway/internal/svc"
	"gateway/internal/types"

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

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

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

func (l *RegisterSocialStartLogic) RegisterSocialStart(req *types.RegisterSocialStartReq) (*types.RegisterSocialStartData, error) {
	if l.svcCtx.Zitadel == nil {
		return nil, errb.SysNotImplemented("zitadel not configured")
	}
	if l.svcCtx.AuthRegistrationSession == nil {
		return nil, errb.SysNotImplemented("registration session not configured")
	}

	tenant, err := resolveTenant(l.ctx, l.svcCtx, req.TenantSlug)
	if err != nil {
		return nil, err
	}

	regCfg := l.svcCtx.Config.Member.Defaults().Registration
	inviteNewUsersOnly := true
	if regCfg.RequireInviteCode {
		if l.svcCtx.AuthInvite == nil {
			return nil, errb.SysNotImplemented("invite validation not configured")
		}
		view, err := l.svcCtx.AuthInvite.Validate(l.ctx, &domauth.ValidateInviteRequest{
			TenantID: tenant.TenantID,
			Code:     req.InviteCode,
		})
		if err != nil {
			return nil, err
		}
		inviteNewUsersOnly = view.NewUsersOnly
	}

	meta := RequestMetaFromContext(l.ctx)
	ttl := time.Duration(l.svcCtx.Config.Auth.Defaults().RegistrationSessionTTLSeconds) * time.Second
	session, err := l.svcCtx.AuthRegistrationSession.Create(l.ctx, &domauth.CreateRegistrationSessionRequest{
		TenantID:           tenant.TenantID,
		TenantSlug:         tenant.Slug,
		InviteCode:         req.InviteCode,
		InviteNewUsersOnly: inviteNewUsersOnly,
		AcceptTermsVersion: req.AcceptTermsVersion,
		MarketingOptIn:     req.MarketingOptIn,
		Language:           strings.TrimSpace(req.Language),
		Provider:           strings.ToLower(strings.TrimSpace(req.Provider)),
		RedirectURI:        strings.TrimSpace(req.RedirectURI),
		ClientIP:           meta.ClientIP,
		UserAgent:          meta.UserAgent,
		TTL:                ttl,
	})
	if err != nil {
		return nil, err
	}

	oauthURL, err := l.svcCtx.Zitadel.AuthorizeURL(req.RedirectURI, registerOAuthState(session.SessionID), req.Provider)
	if err != nil {
		return nil, wrapZitadelErr(err)
	}

	return &types.RegisterSocialStartData{
		OauthURL:  oauthURL,
		SessionID: session.SessionID,
		ExpiresIn: session.ExpiresIn,
	}, nil
}
