package user

import (
	"context"
	"tyc-server/app/main/model"
	"tyc-server/common/ctxdata"
	"tyc-server/common/xerr"

	"github.com/zeromicro/go-zero/core/mr"

	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/stores/sqlx"

	"tyc-server/app/main/api/internal/svc"

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

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

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

func (l *CancelOutLogic) CancelOut() error {
	userID, getUserIdErr := ctxdata.GetUidFromCtx(l.ctx)
	if getUserIdErr != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %v", getUserIdErr)
	}

	// 1. 先检查用户是否是代理
	agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		return errors.Wrapf(err, "查询代理信息失败, userId: %d", userID)
	}

	// 如果用户是代理，进行额外检查
	if agentModel != nil {
		// 1.1 检查代理等级是否为VIP或SVIP
		if agentModel.LevelName == model.AgentLeveNameVIP || agentModel.LevelName == model.AgentLeveNameSVIP {
			return errors.Wrapf(xerr.NewErrMsg("您是"+agentModel.LevelName+"会员，请联系客服进行注销"), "用户是代理会员，不能注销")
		}

		// 1.2 检查代理钱包是否有余额或冻结金额
		wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agentModel.Id)
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理钱包失败, agentId: %d", agentModel.Id)
		}

		if wallet != nil && (wallet.Balance > 0 || wallet.FrozenBalance > 0) {
			if wallet.Balance > 0 {
				return errors.Wrapf(xerr.NewErrMsg("您的钱包还有余额%.2f元，请先提现后再注销账号"), "用户钱包有余额，不能注销", wallet.Balance)
			}
			if wallet.FrozenBalance > 0 {
				return errors.Wrapf(xerr.NewErrMsg("您的钱包还有冻结金额%.2f元，请等待解冻后再注销账号"), "用户钱包有冻结金额，不能注销", wallet.FrozenBalance)
			}
		}
	}

	// 在事务中处理用户注销相关操作
	err = l.svcCtx.UserModel.Trans(l.ctx, func(tranCtx context.Context, session sqlx.Session) error {
		// 1. 删除用户基本信息
		if err := l.svcCtx.UserModel.Delete(tranCtx, session, userID); err != nil {
			return errors.Wrapf(err, "删除用户基本信息失败, userId: %d", userID)
		}

		// 2. 查询并删除用户授权信息
		UserAuthModelBuilder := l.svcCtx.UserAuthModel.SelectBuilder().Where("user_id = ?", userID)
		userAuths, err := l.svcCtx.UserAuthModel.FindAll(tranCtx, UserAuthModelBuilder, "")
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return errors.Wrapf(err, "查询用户授权信息失败, userId: %d", userID)
		}

		// 并发删除用户授权信息
		if len(userAuths) > 0 {
			funcs := make([]func() error, len(userAuths))
			for i, userAuth := range userAuths {
				authID := userAuth.Id
				funcs[i] = func() error {
					return l.svcCtx.UserAuthModel.Delete(tranCtx, session, authID)
				}
			}

			if err := mr.Finish(funcs...); err != nil {
				return errors.Wrapf(err, "删除用户授权信息失败")
			}
		}

		// 3. 处理代理相关信息
		if agentModel != nil {
			// 3.1 删除代理信息
			if err := l.svcCtx.AgentModel.Delete(tranCtx, session, agentModel.Id); err != nil {
				return errors.Wrapf(err, "删除代理信息失败, agentId: %d", agentModel.Id)
			}

			// 3.2 查询并删除代理会员配置
			configBuilder := l.svcCtx.AgentMembershipUserConfigModel.SelectBuilder().Where("agent_id = ?", agentModel.Id)
			configs, err := l.svcCtx.AgentMembershipUserConfigModel.FindAll(tranCtx, configBuilder, "")
			if err != nil && !errors.Is(err, model.ErrNotFound) {
				return errors.Wrapf(err, "查询代理会员配置失败, agentId: %d", agentModel.Id)
			}

			// 并发删除代理会员配置
			if len(configs) > 0 {
				configFuncs := make([]func() error, len(configs))
				for i, config := range configs {
					configId := config.Id
					configFuncs[i] = func() error {
						return l.svcCtx.AgentMembershipUserConfigModel.Delete(tranCtx, session, configId)
					}
				}

				if err := mr.Finish(configFuncs...); err != nil {
					return errors.Wrapf(err, "删除代理会员配置失败")
				}
			}

			// 3.3 删除代理钱包信息
			wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(tranCtx, agentModel.Id)
			if err != nil && !errors.Is(err, model.ErrNotFound) {
				return errors.Wrapf(err, "查询代理钱包信息失败, agentId: %d", agentModel.Id)
			}

			if wallet != nil {
				if err := l.svcCtx.AgentWalletModel.Delete(tranCtx, session, wallet.Id); err != nil {
					return errors.Wrapf(err, "删除代理钱包信息失败, walletId: %d", wallet.Id)
				}
			}

			// 3.4 删除代理关系信息
			closureBuilder := l.svcCtx.AgentClosureModel.SelectBuilder().Where("ancestor_id = ? AND depth = ?", agentModel.Id, 1)
			closures, err := l.svcCtx.AgentClosureModel.FindAll(tranCtx, closureBuilder, "")
			if err != nil && !errors.Is(err, model.ErrNotFound) {
				return errors.Wrapf(err, "查询代理关系信息失败, agentId: %d", agentModel.Id)
			}

			if len(closures) > 0 {
				closureFuncs := make([]func() error, len(closures))
				for i, closure := range closures {
					closureId := closure.Id
					closureFuncs[i] = func() error {
						return l.svcCtx.AgentClosureModel.Delete(tranCtx, session, closureId)
					}
				}

				if err := mr.Finish(closureFuncs...); err != nil {
					return errors.Wrapf(err, "删除代理关系信息失败")
				}
			}
		}

		// 4. 查询并删除代理审核信息
		auditBuilder := l.svcCtx.AgentAuditModel.SelectBuilder().Where("user_id = ?", userID)
		audits, err := l.svcCtx.AgentAuditModel.FindAll(tranCtx, auditBuilder, "")
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return errors.Wrapf(err, "查询代理审核信息失败, userId: %d", userID)
		}

		// 并发删除代理审核信息
		if len(audits) > 0 {
			auditFuncs := make([]func() error, len(audits))
			for i, audit := range audits {
				auditId := audit.Id
				auditFuncs[i] = func() error {
					return l.svcCtx.AgentAuditModel.Delete(tranCtx, session, auditId)
				}
			}

			if err := mr.Finish(auditFuncs...); err != nil {
				return errors.Wrapf(err, "删除代理审核信息失败")
			}
		}

		// 5. 删除用户查询记录
		queryBuilder := l.svcCtx.QueryModel.SelectBuilder().Where("user_id = ?", userID)
		queries, err := l.svcCtx.QueryModel.FindAll(tranCtx, queryBuilder, "")
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return errors.Wrapf(err, "查询用户查询记录失败, userId: %d", userID)
		}

		if len(queries) > 0 {
			queryFuncs := make([]func() error, len(queries))
			for i, query := range queries {
				queryId := query.Id
				queryFuncs[i] = func() error {
					return l.svcCtx.QueryModel.Delete(tranCtx, session, queryId)
				}
			}

			if err := mr.Finish(queryFuncs...); err != nil {
				return errors.Wrapf(err, "删除用户查询记录失败")
			}
		}

		// 6. 删除用户订单记录
		orderBuilder := l.svcCtx.OrderModel.SelectBuilder().Where("user_id = ?", userID)
		orders, err := l.svcCtx.OrderModel.FindAll(tranCtx, orderBuilder, "")
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return errors.Wrapf(err, "查询用户订单记录失败, userId: %d", userID)
		}

		if len(orders) > 0 {
			orderFuncs := make([]func() error, len(orders))
			for i, order := range orders {
				orderId := order.Id
				orderFuncs[i] = func() error {
					return l.svcCtx.OrderModel.Delete(tranCtx, session, orderId)
				}
			}

			if err := mr.Finish(orderFuncs...); err != nil {
				return errors.Wrapf(err, "删除用户订单记录失败")
			}
		}

		// 7. 删除代理订单信息
		agentOrderBuilder := l.svcCtx.AgentOrderModel.SelectBuilder().Where("agent_id = ?", agentModel.Id)
		agentOrders, err := l.svcCtx.AgentOrderModel.FindAll(tranCtx, agentOrderBuilder, "")
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return errors.Wrapf(err, "查询代理订单信息失败, agentId: %d, err: %v", agentModel.Id, err)
		}

		if len(agentOrders) > 0 {
			agentOrderFuncs := make([]func() error, len(agentOrders))
			for i, agentOrder := range agentOrders {
				agentOrderId := agentOrder.Id
				agentOrderFuncs[i] = func() error {
					return l.svcCtx.AgentOrderModel.Delete(tranCtx, session, agentOrderId)
				}
			}

			if err := mr.Finish(agentOrderFuncs...); err != nil {
				return errors.Wrapf(err, "删除代理订单信息失败")
			}
		}
		return nil
	})

	if err != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "用户注销失败%v", err)
	}

	return nil
}
