package auth

import (
	"context"
	"net/url"
	"strings"

	notifDomain "apps/backend/internal/module/notification/domain"
	"apps/backend/internal/svc"
	"apps/backend/internal/types"

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

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

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

// RequestPasswordReset 產生重設碼 → 寄信。信箱不存在回錯誤、不寄。
func (l *RequestPasswordResetLogic) RequestPasswordReset(req *types.AuthRequestResetReq) (resp *types.AuthRequestResetData, err error) {
	email := strings.ToLower(strings.TrimSpace(req.Email))
	code, err := l.svcCtx.Auth.RequestPasswordReset(l.ctx, email)
	if err != nil {
		return nil, err
	}

	relPath := resetPath(email, code)
	absURL := absoluteWebURL(l.svcCtx.Config.PublicWebBase, relPath)

	name := strings.Split(email, "@")[0]
	langRaw := req.Language
	if m, findErr := l.svcCtx.Members.FindByEmail(l.ctx, email); findErr == nil && m != nil {
		if m.DisplayName != "" {
			name = m.DisplayName
		}
		if langRaw == "" && m.PreferredLanguage != "" {
			langRaw = m.PreferredLanguage
		}
	}
	lang := notifDomain.NormalizeLanguage(langRaw)

	subject, html, err := l.svcCtx.Notification.RenderVerify(
		notifDomain.TemplatePasswordReset,
		lang,
		notifDomain.VerifyTemplateVars{
			Username:   name,
			VerifyCode: code,
			ResetURL:   absURL,
		},
	)
	if err != nil {
		l.Errorf("render password reset template: %v", err)
		return nil, err
	}

	if err := l.svcCtx.Notification.SendEmail(l.ctx, notifDomain.EmailRequest{
		RecipientEmail: email,
		SenderEmail:    l.svcCtx.Notification.SenderFrom(),
		Subject:        subject,
		HTMLBody:       html,
	}); err != nil {
		l.Errorf("send password reset to %s: %v", email, err)
		return nil, err
	}

	return &types.AuthRequestResetData{
		Ok:      true,
		Message: "reset code sent",
	}, nil
}

func resetPath(email, code string) string {
	q := url.Values{}
	q.Set("email", email)
	q.Set("token", code)
	return "/reset-password?" + q.Encode()
}

func absoluteWebURL(base, path string) string {
	base = strings.TrimRight(strings.TrimSpace(base), "/")
	if base == "" {
		return path
	}
	if !strings.HasPrefix(path, "/") {
		path = "/" + path
	}
	return base + path
}
