package repoimpl

import (
	"context"
	"gorm.io/gorm"
	"time"
	"unicode/utf8"
	"voucher/internal/biz/bo"
	"voucher/internal/biz/repo"
	"voucher/internal/biz/vo"
	"voucher/internal/data"
	"voucher/internal/data/model"
)

// OrderWechatRepoImpl .
type OrderWechatRepoImpl struct {
	Base[model.OrderWechat, bo.OrderWechatBo]
	db *data.Db
}

// NewOrderWechatRepoImpl .
func NewOrderWechatRepoImpl() repo.OrderWechatRepo {
	return &OrderWechatRepoImpl{}
}

func (p *OrderWechatRepoImpl) DB(ctx context.Context) *gorm.DB {
	return p.db.DB(ctx).Model(model.OrderWechat{})
}

func (p *OrderWechatRepoImpl) Create(ctx context.Context, req *bo.OrderWechatBo) (*bo.OrderWechatBo, error) {
	now := time.Now()

	info := &model.OrderWechat{
		OrderNo:           req.OrderNo,
		OutRequestNo:      req.OutRequestNo,
		AppID:             req.AppID,
		StockCreatorMchid: req.StockCreatorMchid,
		OpenID:            req.OpenID,
		StockID:           req.StockID,
		Status:            vo.OrderWechatStatusWait.GetValue(),
		CreateTime:        &now,
		UpdateTime:        &now,
	}

	if err := p.db.DB(ctx).Create(info).Error; err != nil {
		return nil, err
	}

	return p.ToBo(info), nil
}

func (p *OrderWechatRepoImpl) GetByOutRequestNo(ctx context.Context, outRequestNo string) (*bo.OrderWechatBo, error) {
	info := &model.OrderWechat{}

	tx := p.DB(ctx).Where(model.OrderWechat{OutRequestNo: outRequestNo}).Find(&info)

	if tx.Error != nil {
		return nil, tx.Error
	}

	if tx.RowsAffected == 0 {
		return nil, gorm.ErrRecordNotFound
	}

	return p.ToBo(info), nil
}

func (p *OrderWechatRepoImpl) Success(ctx context.Context, id uint64, couponId string) error {
	now := time.Now()

	res := p.db.DB(ctx).
		Where(model.OrderWechat{
			ID:     id,
			Status: vo.OrderStatusWait.GetValue(),
		}).
		Updates(model.OrderWechat{
			Status:     vo.OrderWechatStatusSuccess.GetValue(),
			CouponID:   couponId,
			UpdateTime: &now,
		})

	if res.Error != nil {
		return res.Error
	}

	return nil
}

func (p *OrderWechatRepoImpl) Fail(ctx context.Context, id uint64, remark string) error {
	now := time.Now()

	if utf8.RuneCountInString(remark) > 100 {
		runes := []rune(remark)
		if len(runes) > 100 {
			remark = string(runes[:100])
		}
	}

	res := p.db.DB(ctx).
		Where(model.OrderWechat{
			ID:     id,
			Status: vo.OrderStatusWait.GetValue(),
		}).
		Updates(model.OrderWechat{
			Status:     vo.OrderWechatStatusFail.GetValue(),
			Remark:     remark,
			UpdateTime: &now,
		})

	if res.Error != nil {
		return res.Error
	}

	return nil
}
