package user

import (
	"context"
	"time"

	"github.com/perfect-panel/server/internal/logic/auth"
	commonLogic "github.com/perfect-panel/server/internal/logic/common"
	"github.com/perfect-panel/server/internal/model/user"
	"github.com/perfect-panel/server/internal/svc"
	"github.com/perfect-panel/server/pkg/logger"
	"github.com/perfect-panel/server/pkg/tool"
	"github.com/perfect-panel/server/pkg/uuidx"
)

func tryGrantTrialOnEmailBind(ctx context.Context, svcCtx *svc.ServiceContext, log logger.Logger, ownerUserId int64, email string) {
	rc := svcCtx.Config.Register
	commonLogic.SubscriptionTraceInfo(log, commonLogic.SubscriptionTraceFlowEmailBind, "trial_grant_evaluating",
		"[SubscriptionFlow] evaluating email bind trial grant",
		logger.Field("owner_user_id", ownerUserId),
		logger.Field("email", email),
		logger.Field("trial_subscribe_id", rc.TrialSubscribe),
	)
	if !auth.ShouldAutoGrantTrialOnPublicEmailFlows(rc) {
		commonLogic.SubscriptionTraceInfo(log, commonLogic.SubscriptionTraceFlowEmailBind, "trial_grant_skipped",
			"[SubscriptionFlow] auto trial on public email flow disabled",
			logger.Field("email", email),
			logger.Field("owner_user_id", ownerUserId),
			logger.Field("skip_reason", "public_email_trial_disabled"),
		)
		return
	}
	if !auth.ShouldGrantTrialForEmail(rc, email) {
		if rc.EnableTrial && rc.EnableTrialEmailWhitelist {
			commonLogic.SubscriptionTraceInfo(log, commonLogic.SubscriptionTraceFlowEmailBind, "trial_grant_skipped",
				"[SubscriptionFlow] email domain not in trial whitelist",
				logger.Field("email", email),
				logger.Field("owner_user_id", ownerUserId),
				logger.Field("skip_reason", "trial_whitelist_rejected"),
			)
		}
		return
	}

	var count int64
	if err := svcCtx.DB.WithContext(ctx).
		Model(&user.Subscribe{}).
		Where("user_id = ? AND subscribe_id = ?", ownerUserId, rc.TrialSubscribe).
		Count(&count).Error; err != nil {
		commonLogic.SubscriptionTraceError(log, commonLogic.SubscriptionTraceFlowEmailBind, "trial_grant_error",
			"[SubscriptionFlow] failed to query existing trial subscription",
			logger.Field("owner_user_id", ownerUserId),
			logger.Field("email", email),
			logger.Field("error", err.Error()),
		)
		return
	}
	if count > 0 {
		commonLogic.SubscriptionTraceInfo(log, commonLogic.SubscriptionTraceFlowEmailBind, "trial_grant_skipped",
			"[SubscriptionFlow] trial already exists for owner",
			logger.Field("owner_user_id", ownerUserId),
			logger.Field("email", email),
			logger.Field("skip_reason", "trial_already_exists"),
		)
		return
	}

	// Cross-user check: prevent the same real inbox (via dot trick / + alias) from
	// getting multiple trials across different accounts.
	if auth.NormalizedEmailHasTrial(ctx, svcCtx.DB, email, rc.TrialSubscribe) {
		commonLogic.SubscriptionTraceInfo(log, commonLogic.SubscriptionTraceFlowEmailBind, "trial_grant_skipped",
			"[SubscriptionFlow] normalized email already received a trial elsewhere",
			logger.Field("email", email),
			logger.Field("owner_user_id", ownerUserId),
			logger.Field("skip_reason", "normalized_email_has_trial"),
		)
		return
	}

	sub, err := svcCtx.SubscribeModel.FindOne(ctx, rc.TrialSubscribe)
	if err != nil {
		commonLogic.SubscriptionTraceError(log, commonLogic.SubscriptionTraceFlowEmailBind, "trial_grant_error",
			"[SubscriptionFlow] failed to load trial subscription template",
			logger.Field("owner_user_id", ownerUserId),
			logger.Field("email", email),
			logger.Field("trial_subscribe_id", rc.TrialSubscribe),
			logger.Field("error", err.Error()),
		)
		return
	}

	userSub := &user.Subscribe{
		UserId:      ownerUserId,
		OrderId:     0,
		SubscribeId: sub.Id,
		StartTime:   time.Now(),
		ExpireTime:  tool.AddTime(rc.TrialTimeUnit, rc.TrialTime, time.Now()),
		Traffic:     sub.Traffic,
		Download:    0,
		Upload:      0,
		Token:       uuidx.NewUUID().String(),
		UUID:        uuidx.NewUUID().String(),
		Status:      1,
	}
	if err = svcCtx.UserModel.InsertSubscribe(ctx, userSub); err != nil {
		commonLogic.SubscriptionTraceError(log, commonLogic.SubscriptionTraceFlowEmailBind, "trial_grant_error",
			"[SubscriptionFlow] failed to create trial subscription for email bind",
			append(commonLogic.UserSubscribeTraceFields(userSub),
				logger.Field("error", err.Error()),
				logger.Field("owner_user_id", ownerUserId),
				logger.Field("email", email),
			)...,
		)
		return
	}

	if svcCtx.NodeModel != nil {
		if err = svcCtx.NodeModel.ClearServerAllCache(ctx); err != nil {
			log.Errorw("ClearServerAllCache error", logger.Field("error", err.Error()))
		}
	}

	commonLogic.SubscriptionTraceInfo(log, commonLogic.SubscriptionTraceFlowEmailBind, "trial_grant_succeeded",
		"[SubscriptionFlow] trial subscription granted after email bind",
		append(commonLogic.UserSubscribeTraceFields(userSub),
			logger.Field("owner_user_id", ownerUserId),
			logger.Field("email", email),
			logger.Field("trial_subscribe_id", sub.Id),
		)...,
	)
}
