package agent

import (
	"context"
	"database/sql"

	"sim-server/app/main/api/internal/svc"
	"sim-server/app/main/api/internal/types"
	"sim-server/app/main/model"
	"sim-server/common/ctxdata"
	"sim-server/common/xerr"
	"sim-server/pkg/lzkit/crypto"

	"github.com/google/uuid"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

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

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

func (l *CreateWithdrawLogic) CreateWithdraw(req *types.CreateWithdrawReq) (resp *types.CreateWithdrawResp, err error) {
	// 1. 获取当前用户ID（代理ID）
	userId, err := ctxdata.GetUidFromCtx(l.ctx)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败: %v", err)
	}

	// 2. 查询代理信息
	agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userId)
	if err != nil {
		if errors.Is(err, model.ErrNotFound) {
			return nil, errors.Wrap(xerr.NewErrCode(xerr.CUSTOM_ERROR), "您还不是代理，无法申请提现")
		}
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询代理信息失败: %v", err)
	}

	// 3. 查询钱包信息
	wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agent.Id)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询钱包信息失败: %v", err)
	}

	// 4. 验证提现金额
	if req.WithdrawAmount <= 0 {
		return nil, errors.Wrap(xerr.NewErrCode(xerr.REUQEST_PARAM_ERROR), "提现金额必须大于0")
	}

	minWithdraw := 100.00 // 最低提现金额100元
	if req.WithdrawAmount < minWithdraw {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.REUQEST_PARAM_ERROR), "最低提现金额为%.2f元", minWithdraw)
	}

	if wallet.Balance < req.WithdrawAmount {
		return nil, errors.Wrap(xerr.NewErrCode(xerr.CUSTOM_ERROR), "可用余额不足")
	}

	// 5. 加密银行卡号
	encryptedCardNumber, err := crypto.AesEncrypt([]byte(req.BankCardNumber), []byte(l.svcCtx.Config.Encrypt.SecretKey))
	if err != nil {
		logx.Errorf("加密银行卡号失败: %v", err)
		return nil, errors.Wrap(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密银行卡号失败")
	}

	// 6. 生成提现记录ID
	withdrawId := uuid.NewString()

	// 7. 解密代理手机号（用于冗余存储）
	agentMobile, err := crypto.DecryptMobile(agent.Mobile, l.svcCtx.Config.Encrypt.SecretKey)
	if err != nil {
		logx.Errorf("解密代理手机号失败: %v", err)
		agentMobile = ""
	}

	// 8. 开启事务处理
	err = l.svcCtx.AgentWalletModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		// 8.1 冻结提现金额
		wallet.Balance -= req.WithdrawAmount
		wallet.FrozenAmount += req.WithdrawAmount

		// 使用版本号乐观锁更新
		err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet)
		if err != nil {
			return errors.Wrapf(err, "冻结金额失败")
		}

		// 8.2 创建提现记录
		withdrawRecord := &model.AgentWithdraw{
			Id:                      withdrawId,
			AgentId:                 agent.Id,
			WithdrawAmount:          req.WithdrawAmount,
			TaxAmount:               0.00,
			ActualAmount:            0.00,
			FrozenAmount:            req.WithdrawAmount,
			AccountName:             req.AccountName,
			BankCardNumber:          req.BankCardNumber,
			BankCardNumberEncrypted: sql.NullString{String: string(encryptedCardNumber), Valid: true},
			BankBranch:              sql.NullString{String: req.BankBranch, Valid: req.BankBranch != ""},
			Status:                  0,
		}

		// 冗余存储代理手机号和编码
		if agentMobile != "" {
			withdrawRecord.AgentMobile = sql.NullString{String: agentMobile, Valid: true}
		}
		if agent.AgentCode > 0 {
			withdrawRecord.AgentCode = sql.NullInt64{Int64: agent.AgentCode, Valid: true}
		}

		_, err = l.svcCtx.AgentWithdrawModel.Insert(ctx, session, withdrawRecord)
		if err != nil {
			return errors.Wrapf(err, "创建提现记录失败")
		}

		return nil
	})

	if err != nil {
		return nil, errors.Wrap(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), err.Error())
	}

	logx.Infof("代理 %s 申请提现成功，提现金额: %.2f", agent.Id, req.WithdrawAmount)

	return &types.CreateWithdrawResp{
		WithdrawId: withdrawId,
	}, nil
}
