package models

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/rs/zerolog/log"
	"github.com/xuri/excelize/v2"
	"go-admin/app/admin/apis/pay"
	utils "go-admin/app/admin/models/tools"
	orm "go-admin/common/global"
	"go-admin/logger"
	"go-admin/tools"
	"go-admin/tools/config"
	"gorm.io/gorm"
	"math/rand"
	"sort"
	"strconv"
	"strings"
	"time"
)

const (
	SaleStatusUnknown = iota
	SaleStatusYes
	SaleStatusNo
)

const (
	PayTypeUnknown = iota
	PayTypeRm      // 人民币
	PayTypeVm      // 积分
)

const (
	PayStatusUnknown = iota
	PayStatusInit
	PayStatusOK
	PayStatusFail
)

// 商品
// gen:qs
//
//go:generate goqueryset -in mall.go
type Goods struct {
	Model

	GoodsId   uint32 `json:"goods_id" gorm:"unique_index"`
	SerialNo  string `json:"serial_no" gorm:"unique_index"` // 序列号
	CatId     uint32 `json:"cat_id" gorm:"index"`           // 分类
	Name      string `json:"name"`                          // 名称
	Title     string `json:"title"`                         // 标题
	MainImage string `json:"main_image"`                    // 主图
	Images    string `json:"images"`                        // 图片列表，用,隔开
	Detail    string `json:"detail" gorm:"type:text;"`      // 详情, 富文本

	SoldCount  uint32 `json:"sold_count"`  // 已销售数量
	SaleStatus uint32 `json:"sale_status"` // 在售状态 1-在售 2-下架
	CatSort    uint32 `json:"cat_sort"`    // 分类排序
	Sort       uint32 `json:"sort"`        // 商品排序

	SpecList     string `json:"spec_list" gorm:"type:text;"`     // 属性json数据
	DiscountList string `json:"discount_list" gorm:"type:text;"` // 折扣
	SpecIndex    string `json:"spec_index" gorm:"index"`         // 1,3

	PriceOriginal uint32 `json:"price_original"` // 市场价
	DeliveryFee   uint32 `json:"delivery_fee"`   // 邮费
	DealType      uint32 `json:"deal_type"`      // 1-积分兑换  2-购买  3-抵扣
	VersionId     uint64 `json:"version_id"`     // 乐观锁

	PriceVm uint32 `json:"price_vm"` // 积分价格
	PriceRm uint32 `json:"price_rm"` // 人民币价格
	//Stock         uint32 `json:"stock"`          // 库存
	ShowDiscount    int8   `json:"show_discount"`     // 是否展示折扣价
	GoodsAccountNum uint32 `json:"goods_account_num"` // 收款账户编号 1 明慧；2 迪为

	GoodsCat      *GoodsCat            `json:"goods_cat" gorm:"-"`
	GoodsDiscount *GoodsDiscount       `json:"goods_discount" gorm:"-"`
	Attributes    []GoodsAttribute     `json:"attributes" gorm:"-"`
	Combo         *GoodsAttributeCombo `json:"combo" gorm:"-"`
}

func (*Goods) TableName() string {
	return "goods"
}

type GoodsDiscount struct {
	Gold      uint32 `json:"gold"`       // 黄金折扣
	Platinum  uint32 `json:"platinum"`   // 白金折扣
	BlackGold uint32 `json:"black_gold"` // 黑金折扣
}

type GoodsSpec struct {
	Spec   Spec        `json:"spec"`
	Values []SpecValue `json:"values"`
}

//// gen:qs
//type GoodsCat struct {
//	Model
//	Color string `json:"color"`
//}

// gen:qs
type GoodsCat struct {
	Model

	Name     string     `json:"name"`     // 名称
	Priority string     `json:"priority"` // 分类
	State    uint32     `json:"state"`    // 1-未使用 2-使用
	Level    uint32     `json:"level"`    // 分类层级
	Pid      uint32     `json:"pid" gorm:"index"`
	Sort     uint32     `json:"sort"`
	SubCats  []GoodsCat `json:"sub_cats" gorm:"-"` // 子列表
	// goods_cat
}

type GoodsAttribute struct {
	Model

	GoodsId   uint32 `json:"goods_id" gorm:"index"`
	SerialNo  string `json:"serial_no" gorm:"index"` // 序列号
	CatId     uint32 `json:"cat_id" gorm:"index"`    // 分类
	Name      string `json:"name"`                   // 名称
	Title     string `json:"title"`                  // 标题
	MainImage string `json:"main_image"`             // 主图

	Stock     uint32 `json:"stock"`      // 库存
	SoldCount uint32 `json:"sold_count"` // 已销售数量
	Sort      int    `json:"sort"`       //排序

	//PriceRm        uint32 `json:"price_rm"`                          // 人民币价格
	PriceOriginal  uint32                `json:"price_original"`                    // 市场价
	SpecValueList  string                `json:"spec_value_list" gorm:"type:text;"` // 属性json数据
	SpecValueIndex string                `json:"spec_value_index" gorm:"index"`     // 1,3,5
	DealType       uint32                `json:"deal_type"`                         // 1-积分兑换  2-购买  3-抵扣
	SpecValues     []SpecValue           `json:"spec_values" gorm:"-"`
	Combos         []GoodsAttributeCombo `json:"combos" gorm:"-"`
	Combo          *GoodsAttributeCombo  `json:"combo" gorm:"-"`
	// goods_attribute
}

type GoodsAttributeCombo struct {
	Model

	GoodsAttributeId uint32 `json:"goods_attribute_id" gorm:"index"`
	GoodsId          uint32 `json:"goods_id" gorm:"index"`
	SerialNo         string `json:"serial_no" gorm:"index"` // 序列号
	CatId            uint32 `json:"cat_id" gorm:"index"`    // 分类
	Name             string `json:"name"`                   // 名称
	Title            string `json:"title"`                  // 标题
	MainImage        string `json:"main_image"`             // 主图
	ComboName        string `json:"combo_name"`             // 名称
	PriceVm          uint32 `json:"price_vm"`               // 积分价格
	PriceRm          uint32 `json:"price_rm"`               // 人民币价格
	// goods_attribute_combo
}

//type GoodsSpec struct {
//	Model
//}

type Spec struct {
	Model
	DisplayName string      `json:"display_name"`
	Name        string      `json:"name"`
	State       uint32      `json:"state"` // 1-未使用 2-使用
	Sort        uint32      `json:"sort"`
	Values      []SpecValue `json:"values" gorm:"-"`
}

type SpecValue struct {
	Model
	SpecId          uint32 `json:"spec_id"`
	SpecDisplayName string `json:"spec_display_name"`
	SpecName        string `json:"spec_name"`
	DisplayValue    string `json:"display_value"`
	State           uint32 `json:"state"` // 1-未使用 2-使用
	Value           string `json:"value"`
	SpecSort        uint32 `json:"spec_sort"`
	Sort            uint32 `json:"sort"`
	// spec_value
}

func CreateGoodsSerialNo() string {
	for {
		serialNo := utils.GenSerialNo()
		var count int64
		err := orm.Eloquent.Table("goods").Where("serial_no=?", serialNo).Count(&count).Error
		if err != nil {
			logger.Errorf("err:", err)
			return ""
		}
		if count > 0 {
			continue
		}
		//if count, err := NewGoodsQuerySet(DB).SerialNoEq(serialNo).Total(); err == nil && count > 0 {
		//	continue
		//}
		return serialNo
	}
}

func CreateGoodsId() uint32 {
	for {
		orderId := utils.GenUid()
		var count int64
		err := orm.Eloquent.Table("goods").Where("goods_id=?", orderId).Count(&count).Error
		if err != nil {
			logger.Errorf("err:", err)
			return 0
		}
		if count > 0 {
			continue
		}
		//if count, err := NewGoodsQuerySet(DB).GoodsIdEq(orderId).Total(); err == nil && count > 0 {
		//	continue
		//}
		return orderId
	}
}

type GoodsListReq struct {
	PageIdx    int    `json:"pageIndex"`
	PageSize   int    `json:"pageSize"`
	Name       string `json:"name"`
	SaleStatus uint32 `json:"sale_status"` // 在售状态 1-在售 2-下架
}

func (m *GoodsListReq) GoodsList() ([]Goods, int64, error) {
	page := m.PageIdx - 1
	if page < 0 {
		page = 0
	}
	if m.PageSize == 0 {
		m.PageSize = 10
	}
	var goodsList []Goods
	qs := orm.Eloquent.Table("goods")
	//qs := NewGoodsQuerySet(DB)
	if m.Name != "" {
		qs = qs.Where("name LIKE ?", "%"+m.Name+"%")
	}
	if m.SaleStatus != 0 {
		qs = qs.Where("sale_status = ?", m.SaleStatus)
	}
	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, 0, err
	}
	//totalPage := int(count)/m.PageSize + 1

	//err = qs.Order("cat_sort DESC,sort DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&goodsList).Error
	err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&goodsList).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, 0, err
	}
	GoodsListSetGoodsCat(goodsList)

	return goodsList, count, nil
}

type GoodsDetailReq struct {
	GoodsId uint32 `json:"goods_id"`
}

func (m *GoodsDetailReq) GoodsDetail() (*Goods, error) {
	var goods Goods
	//err := NewGoodsQuerySet(DB).GoodsIdEq(m.GoodsId).One(&goods).GoodsIdEq(m.GoodsId).One(&goods)
	err := orm.Eloquent.Table("goods").Where("goods_id=?", m.GoodsId).Find(&goods).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, err
	}
	return &goods, nil
}

// 商品分类
// gen:qs
type GoodsCategory struct {
	Model

	CatId       uint32 `json:"cat_id"`
	ParentCatId uint32 `json:"parent_cat_id"`
	Name        string `json:"name"`
	Sort        uint32 `json:"sort"` // 排序
	Level       uint32 `json:"level"`
	State       uint32 `json:"state"`
}

const (
	GoodsOrderStateUnPay          = "un_pay"          // 待付款
	GoodsOrderStateOnDeliver      = "on_deliver"      // 待发货
	GoodsOrderStateDelivered      = "delivered"       // 已发货
	GoodsOrderStateReceived       = "received"        // 已收货
	GoodsOrderStateCancel         = "cancel"          // 已取消
	GoodsOrderStateOnRefund       = "on_refund"       // 退货中
	GoodsOrderStateRefunded       = "refunded"        // 已退货
	GoodsOrderStateRefundedCancel = "refunded_cancel" // 退货取消
)

// 商品订单
// gen:qs
type GoodsOrder struct {
	Model

	OrderId  uint32 `json:"order_id" gorm:"unique_index"`  // 订单 id
	SerialNo string `json:"serial_no" gorm:"unique_index"` // 序列号

	Uid      uint32 `json:"uid" gorm:"index"`
	GoodsId  uint32 `json:"goods_id" gorm:"index"` // 商品id
	Amount   uint32 `json:"amount"`                // 订单金额
	Quantity uint32 `json:"quantity"`              // 购买商品的数量

	PayType               uint32    `json:"pay_type"`                 // 支付方式 1-rm 2-vm
	PayTime               time.Time `json:"pay_time"`                 // 支付时间
	PayStatus             uint32    `json:"pay_status"`               // 支付状态 1-待支付 2-已支付 3-失败
	State                 string    `json:"state"`                    //
	AddressId             uint32    `json:"address_id"`               // 收货地址
	DeliveryExtraInfo     string    `json:"delivery_extra_info"`      // 物流备注
	DeliveryFee           uint32    `json:"delivery_fee"`             // 物流费用
	DeliveryTrackingNo    string    `json:"delivery_tracking_no"`     // 物流单号
	DeliveryCompany       string    `json:"delivery_company"`         // 物流公司
	DeliveryCompanyNo     string    `json:"delivery_company_no"`      // 物流公司编号
	DeliveryStatus        uint32    `json:"delivery_status"`          // 物流状态 1-待发货 2-已发货 3-已收货
	Rm                    uint32    `json:"rm"`                       //
	Vm                    uint32    `json:"vm"`                       // 积分
	Discount              uint32    `json:"discount"`                 // 折扣
	GoodsAttributeId      uint32    `json:"goods_attribute_id"`       //
	GoodsAttributeComboId uint32    `json:"goods_attribute_combo_id"` //

	DeliverStoreId uint32    `json:"deliver_store_id"` // 发货门店
	DeliverTime    time.Time `json:"deliver_time"`     // 发货时间

	RefundExpressCompany   string    `json:"refund_express_company"`    // 退货物流公司
	RefundExpressCompanyNo string    `json:"refund_express_company_no"` // 退货物流公司编号
	RefundExpressNo        string    `json:"refund_express_no"`         // 退货物流单号
	RefundReason           string    `json:"refund_reason" gorm:"type:text;"`
	ReceivedTime           time.Time `json:"received_time"`         // 签收时间
	RefundTime             time.Time `json:"refund_time"  gorm:"-"` // 退货时间

	VersionId uint64 `json:"version_id"` // 乐观锁

	Goods        *Goods       `json:"goods" gorm:"-"`
	UserAddress  *UserAddress `json:"user_address"  gorm:"-"`
	DeliverStore *Store       `json:"deliver_store"  gorm:"-"`
}

func (*GoodsOrder) TableName() string {
	return "goods_order"
}

func CreateGoodsOrderSerialNo() string {
	for {
		serialNo := utils.GenSerialNo()
		//if count, err := NewGoodsOrderQuerySet(DB).SerialNoEq(serialNo).Total(); err == nil && count > 0 {
		//	continue
		//}
		return serialNo
	}
}

func CreateGoodsOrderId() uint32 {
	for {
		orderId := utils.GenUid()
		//if count, err := NewGoodsOrderQuerySet(DB).OrderIdEq(orderId).Total(); err == nil && count > 0 {
		//	continue
		//}
		return orderId
	}
}

type GoodsOrderListReq struct {
	PageIdx         int    `json:"pageIndex"`
	PageSize        int    `json:"pageSize"`
	Uid             uint32 `json:"uid"`
	State           string `json:"state"`
	OrderId         uint32 `json:"order_id"`
	GoodsId         uint32 `json:"goods_id"`          // 商品id
	RefundExpressNo string `json:"refund_express_no"` // 退货物流单号
	StartTime       string `json:"start_time"`        // 开始时间
	EndTime         string `json:"end_time"`          // 结束时间
	IsExport        uint32 `json:"is_export"`         // 1-导出
	//DeliveryStatus uint32 `json:"delivery_status"`
}

func (m *GoodsOrderListReq) OrderList() ([]GoodsOrder, string, int64, error) {
	page := m.PageIdx - 1
	if page < 0 {
		page = 0
	}
	if m.PageSize == 0 {
		m.PageSize = 10
	}

	var list []GoodsOrder
	qs := orm.Eloquent.Table("goods_order") // NewGoodsOrderQuerySet(DB)

	if m.Uid != 0 {
		qs = qs.Where("uid=?", m.Uid)
	}
	if m.State != "" {
		qs = qs.Where("state=?", m.State)
	} else {
		qs = qs.Where("state!=?", GoodsOrderStateUnPay)
	}
	if m.RefundExpressNo != "" {
		qs = qs.Where("refund_express_no=?", m.RefundExpressNo)
	}
	if m.OrderId != 0 {
		qs = qs.Where("order_id=?", m.OrderId)
	}
	if m.GoodsId != 0 {
		qs = qs.Where("goods_id=?", m.GoodsId)
	}
	if m.StartTime != "" {
		parse, err := time.Parse(QueryTimeFormat, m.StartTime)
		if err != nil {
			logger.Errorf("err:", err)
		}
		qs = qs.Where("created_at > ?", parse)
	}
	if m.EndTime != "" {
		parse, err := time.Parse(QueryTimeFormat, m.EndTime)
		if err != nil {
			logger.Errorf("err:", err)
		}
		qs = qs.Where("created_at < ?", parse)
	}
	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, "", 0, err
	}
	//totalPage := int(count)/m.PageSize + 1

	var exportUrl string
	if m.IsExport == 1 { // 导出excel
		err = qs.Order("id DESC").Find(&list).Error
		if err != nil {
			logger.Errorf("err:", err)
			return nil, "", 0, err
		}
		GoodsOrderListSetGoods(list)
		exportUrl, err = mallOrderListExport(list)
		if err != nil {
			logger.Errorf("err:", err)
			return nil, "", 0, err
		}
		list = nil
	} else {
		err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&list).Error
		if err != nil {
			logger.Errorf("err:", err)
			return nil, "", 0, err
		}
		GoodsOrderListSetGoods(list)
	}

	return list, exportUrl, count, nil
}

// mallOrderListExport 导出小程序商城订单数据
func mallOrderListExport(list []GoodsOrder) (string, error) {
	file := excelize.NewFile()
	fSheet := "Sheet1"

	url := config.ExportConfig.Url
	fileName := time.Now().Format(TimeFormat) + "商城订单" + ".xlsx"
	fmt.Println("url fileName:", url+fileName)

	// 组合标题栏数据
	title := []interface{}{"订单ID", "用户ID", "商品", "商品数量", "消耗积分", "实付款", "会员折扣", "下单时间", "状态"}
	for i, _ := range title {
		cell, _ := excelize.CoordinatesToCellName(1+i, 1)
		err := file.SetCellValue(fSheet, cell, title[i])
		if err != nil {
			logger.Error("file set value err:", logger.Field("err", err))
		}
	}

	var row1 []interface{}
	nExcelStartRow := 0
	for _, reportData := range list {
		var allotState string
		switch reportData.State {
		case GoodsOrderStateUnPay: // 待付款
			allotState = "待付款"
		case GoodsOrderStateOnDeliver: // 待发货
			allotState = "待发货"
		case GoodsOrderStateDelivered: // 已发货
			allotState = "已发货"
		case GoodsOrderStateReceived: // 已收货
			allotState = "已收货"
		case GoodsOrderStateCancel: // 已取消
			allotState = "已取消"
		case GoodsOrderStateOnRefund: // 退货中
			allotState = "退货中"
		case GoodsOrderStateRefunded: // 已退货
			allotState = "已退货"
		case GoodsOrderStateRefundedCancel: // 退货取消
			allotState = "退货取消"
		}

		var discount string
		if reportData.Discount != 100 {
			discount = strconv.FormatFloat(float64(reportData.Discount/10), 'f', 1, 64)
		}
		var payRm string
		if reportData.Rm != 0 {
			payRm = strconv.FormatFloat(float64(reportData.Rm)/100, 'f', 2, 64)
		}
		var createdTime string
		createdTime = reportData.CreatedAt.Format(TimeFormat)

		var goodsName string
		if reportData.Goods != nil {
			goodsName = reportData.Goods.Name
		}
		row1 = []interface{}{
			reportData.OrderId,  // 订单ID
			reportData.Uid,      // 用户ID
			goodsName,           // 商品名称
			reportData.Quantity, // 商品数量
			reportData.Vm,       // 消耗积分
			payRm,               // 实付款
			discount,            // 会员折扣
			createdTime,         // 下单时间
			allotState,          // 状态
		}

		for j, _ := range row1 {
			cell, err := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2)
			if err != nil {
				logger.Error("invalid cell coordinates", logger.Field("err", err))
				continue
			}
			err = file.SetCellValue(fSheet, cell, row1[j])
			if err != nil {
				logger.Error("file set value err:", logger.Field("err", err))
			}
		}
		nExcelStartRow++
	}

	// 设置所有单元格的样式: 居中、加边框
	style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},
	"border":[{"type":"left","color":"000000","style":1},
	{"type":"top","color":"000000","style":1},
	{"type":"right","color":"000000","style":1},
	{"type":"bottom","color":"000000","style":1}]}`)

	//设置单元格高度
	file.SetRowHeight("Sheet1", 1, 20)

	// 设置单元格大小
	file.SetColWidth("Sheet1", "A", "A", 15)
	file.SetColWidth("Sheet1", "B", "B", 15)
	file.SetColWidth("Sheet1", "C", "C", 23)
	file.SetColWidth("Sheet1", "H", "H", 23)

	endRow := fmt.Sprintf("I"+"%d", nExcelStartRow+1)
	// 应用样式到整个表格
	_ = file.SetCellStyle("Sheet1", "A1", endRow, style)

	fmt.Println("save fileName:", config.ExportConfig.Path+fileName)
	if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
		fmt.Println(err)
	}
	return url + fileName, nil
}

type GoodsOrderDetailReq struct {
	OrderId uint32 `json:"order_id"`
}

func (m *GoodsOrderDetailReq) OrderDetail() (*GoodsOrder, error) {
	var order GoodsOrder
	qs := orm.Eloquent.Table("goods_order").Where("order_id=?", m.OrderId)
	// NewGoodsOrderQuerySet(DB).OrderIdEq(m.OrderId)
	//if uid != 0 {
	//	//qs = qs.UidEq(uid)
	//	qs = qs.Where("uid=?", uid)
	//}

	err := qs.Find(&order).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, err
	}
	//orders := GoodsOrderListSetGoods([]GoodsOrder{order})
	//if len(orders) > 0 {
	//	order.Goods = orders[0].Goods
	//}
	//var goods Goods
	goods, err := GetGoods(order.GoodsId)
	if err != nil {
		logger.Errorf("err:", err)
		return nil, err
	}
	var goodsAttribute GoodsAttribute
	err = orm.Eloquent.Table("goods_attribute").Where("id=?", order.GoodsAttributeId).
		Find(&goodsAttribute).Error
	if err != nil {
		log.Error().Msgf("goods attribute err:%#v", err)
		return nil, err
	}
	if goods.DiscountList != "" {
		discount := new(GoodsDiscount)
		err = json.Unmarshal([]byte(goods.DiscountList), discount)
		if err != nil {
			log.Error().Msgf("goods discount err:%#v", err)
			return nil, err
		}
		goods.GoodsDiscount = discount
	}
	//cat, err := GetGoodsCat(goods.CatId)
	//if err != nil {
	//	log.Error().Msgf("goods cat err:%#v", err)
	//}
	//goods.GoodsCat = cat
	attributes := []GoodsAttribute{goodsAttribute}
	GoodsAttributeListSetSpecValues(attributes)
	//GoodsAttributeListSetCombos(attributes)
	combo, err := GetCombo(order.GoodsAttributeComboId)
	if err != nil {
		log.Error().Msgf("get combo:%#v", err)
		return nil, err
	}
	if len(attributes) > 0 {
		attributes[0].Combo = combo
	}
	goods.Attributes = attributes
	order.Goods = &goods
	if order.State == GoodsOrderStateRefunded { // 已退货状态
		order.RefundTime = order.UpdatedAt
	}

	var userAddress UserAddress
	err = orm.Eloquent.Table("user_address").Where("id=?", order.AddressId).Find(&userAddress).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, err
	}
	order.UserAddress = &userAddress
	err = order.SetDeliverStore()
	if err != nil {
		logger.Errorf(" err:", err)
	}
	return &order, nil
}

func (m *Goods) GoodsCreate() error {
	m.SerialNo = CreateGoodsSerialNo()
	m.GoodsId = CreateGoodsId()
	err := orm.Eloquent.Create(m).Error
	if err != nil {
		logger.Errorf("err:", err.Error())
		return err
	}
	return nil
}

func (m *Goods) Edit() error {
	err := orm.Eloquent.Save(m).Error
	if err != nil {
		logger.Errorf("err:", err.Error())
		return err
	}
	return nil
}

func (m *Goods) GetDetail() error {
	err := orm.Eloquent.Table("goods").Where("goods_id=?", m.GoodsId).Find(m).Error
	if err != nil {
		logger.Errorf("err:", err.Error())
		return err
	}
	var goodsAttributes []GoodsAttribute
	err = orm.Eloquent.Table("goods_attribute").
		Where("goods_id=?", m.GoodsId).
		Order("sort desc").
		Find(&goodsAttributes).Error
	if err != nil {
		log.Error().Msgf("goods attribute err:%#v", err)
		return err
	}
	if m.DiscountList != "" {
		discount := new(GoodsDiscount)
		err = json.Unmarshal([]byte(m.DiscountList), discount)
		if err != nil {
			log.Error().Msgf("goods discount err:%#v", err)
			return err
		}
		m.GoodsDiscount = discount
	}
	cat, err := GetGoodsCat(m.CatId)
	if err != nil {
		log.Error().Msgf("goods cat err:%#v", err)
	}
	m.GoodsCat = cat
	GoodsAttributeListSetSpecValues(goodsAttributes)
	GoodsAttributeListSetCombos(goodsAttributes)

	m.Attributes = goodsAttributes
	return nil
}

func GetGoodsMapByIds(ids []uint32) map[uint32]Goods {
	goodsMap := make(map[uint32]Goods, 0)
	if len(ids) == 0 {
		return goodsMap
	}
	var goodsList []Goods
	err := orm.Eloquent.Table("goods").Where("goods_id IN (?)", ids).Find(&goodsList).Error
	//err := NewGoodsQuerySet(DB).GoodsIdIn(ids...).All(&goodsList)
	if err != nil {
		logger.Errorf("err:", err)
		return goodsMap
	}
	for i, _ := range goodsList {
		goodsMap[goodsList[i].GoodsId] = goodsList[i]
	}

	return goodsMap
}

func GoodsOrderListSetGoods(orders []GoodsOrder) {
	if len(orders) == 0 {
		return
	}
	ids := make([]uint32, 0, len(orders))
	for i, _ := range orders {
		ids = append(ids, orders[i].GoodsId)
		if orders[i].State == GoodsOrderStateRefunded { // 已退货状态
			orders[i].RefundTime = orders[i].UpdatedAt
		}
	}
	goodsMap := GetGoodsMapByIds(ids)
	for i, _ := range orders {
		v, ok := goodsMap[orders[i].GoodsId]
		if ok {
			orders[i].Goods = &v
		}
	}
	return
}

type GoodsOrderDeliverReq struct {
	OrderId            uint32 `json:"order_id"`
	DeliveryTrackingNo string `json:"delivery_tracking_no"` // 物流单号
	DeliveryCompanyNo  string `json:"delivery_company_no"`  // 物流公司编号
	DeliveryCompany    string `json:"delivery_company"`     // 物流公司
	DeliverStoreId     uint32 `json:"deliver_store_id"`     // 发货门店
}

func (m *GoodsOrderDeliverReq) OrderDeliver() (*GoodsOrder, error) {
	var order GoodsOrder
	err := orm.Eloquent.Table("goods_order").Where("order_id=?", m.OrderId).Find(&order).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, err
	}
	if order.State != GoodsOrderStateOnDeliver {
		log.Error().Msg("state err")
		return nil, errors.New("state err")
	}

	err = orm.Eloquent.Table("goods_order").Where("order_id=?", m.OrderId).Updates(map[string]interface{}{
		"delivery_tracking_no": m.DeliveryTrackingNo,
		"delivery_company":     m.DeliveryCompany,
		//"refund_express_company_no": m.DeliveryCompanyNo,
		"delivery_company_no": m.DeliveryCompanyNo,
		"state":               GoodsOrderStateDelivered,
		"deliver_time":        Now(),
		"deliver_store_id":    m.DeliverStoreId,
		//"delivery_status":           2,
	}).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, err
	}
	order.DeliveryTrackingNo = m.DeliveryTrackingNo
	order.DeliveryCompany = m.DeliveryCompany
	order.DeliveryCompanyNo = m.DeliveryCompanyNo
	order.State = GoodsOrderStateDelivered
	order.DeliverTime = Now()
	order.DeliverStoreId = m.DeliverStoreId

	//orders := []GoodsOrder{order}
	//GoodsOrderListSetGoods(orders)
	//if len(orders) > 0 {
	//	order.Goods = orders[0].Goods
	//}

	goods, err := GetGoods(order.GoodsId)
	if err != nil {
		logger.Errorf("err:", err)
		return nil, err
	}
	var goodsAttribute GoodsAttribute
	err = orm.Eloquent.Table("goods_attribute").Where("id=?", order.GoodsAttributeId).
		Find(&goodsAttribute).Error
	if err != nil {
		log.Error().Msgf("goods attribute err:%#v", err)
		return nil, err
	}
	if goods.DiscountList != "" {
		discount := new(GoodsDiscount)
		err = json.Unmarshal([]byte(goods.DiscountList), discount)
		if err != nil {
			log.Error().Msgf("goods discount err:%#v", err)
			return nil, err
		}
		goods.GoodsDiscount = discount
	}
	attributes := []GoodsAttribute{goodsAttribute}
	GoodsAttributeListSetSpecValues(attributes)
	combo, err := GetCombo(order.GoodsAttributeComboId)
	if err != nil {
		log.Error().Msgf("get combo:%#v", err)
		return nil, err
	}
	if len(attributes) > 0 {
		attributes[0].Combo = combo
	}
	goods.Attributes = attributes
	order.Goods = &goods

	var userAddress UserAddress
	err = orm.Eloquent.Table("user_address").Where("id=?", order.AddressId).Find(&userAddress).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, err
	}
	order.UserAddress = &userAddress

	UpdateDeliverTaskSubState(order.OrderId)

	return &order, nil
}

type MallUserVmRecordReq struct {
	PageIdx   int    `json:"pageIndex"`
	PageSize  int    `json:"pageSize"`
	Uid       uint32 `json:"uid"`        // 用户ID
	Tel       string `json:"tel"`        // 用户手机号
	StartTime string `json:"start_time"` // 开始时间，示例：2006-01-02T15:04:05+08:00
	EndTime   string `json:"end_time"`   // 结束时间，示例：2006-01-02T15:04:05+08:00
	VmType    uint32 `json:"vm_type"`    // 默认0-正常查询，1-查询7天内即将过期积分
}

type MallUserVmRecordResp struct {
	Count     int64                  `json:"total"`
	List      []MallUserVmRecordData `json:"list"`
	PageIndex int                    `json:"page_index"`
	PageSize  int                    `json:"page_size"`
}

type MallUserVmRecordData struct {
	UserVmRecord
	Tel string `json:"tel"` // 用户手机号
}

func (m *MallUserVmRecordReq) MallUserVmRecordList() ([]MallUserVmRecordData, int64, error) {
	page := m.PageIdx - 1
	if page < 0 {
		page = 0
	}
	if m.PageSize == 0 {
		m.PageSize = 10
	}

	var list []MallUserVmRecordData
	qs := orm.Eloquent.Table("user_vm_record")
	countQuery := orm.Eloquent.Table("user_vm_record").
		Joins("LEFT JOIN user ON user_vm_record.uid = user.uid")

	if m.Uid != 0 {
		qs = qs.Where("user_vm_record.uid=?", m.Uid)
		countQuery = countQuery.Where("user_vm_record.uid=?", m.Uid)
	}
	if m.Tel != "" {
		qs = qs.Where("user.tel=?", m.Tel)
		countQuery = countQuery.Where("user.tel=?", m.Tel)
	}
	if m.VmType != 0 {
		now := time.Now()
		year, month, day := now.Date()
		startTime := time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
		endTime := time.Date(year, month, day, 23, 59, 59, 0, time.UTC).AddDate(0, 0, 7)

		qs = qs.Where("user_vm_record.expiry_date BETWEEN ? AND ?", startTime, endTime).
			Where("user_vm_record.alter > 0 and user_vm_record.alter != user_vm_record.used_vm")

		countQuery = countQuery.Where("user_vm_record.expiry_date BETWEEN ? AND ?", startTime, endTime).
			Where("user_vm_record.alter > 0 and user_vm_record.alter != user_vm_record.used_vm")
	} else {
		if m.StartTime != "" {
			startTime, err := time.Parse(QueryTimeFormat, m.StartTime)
			if err == nil {
				qs = qs.Where("user_vm_record.created_at>?", startTime)
				countQuery = countQuery.Where("user_vm_record.created_at>?", startTime)
			} else {
				logger.Errorf("MallUserVmRecordList time start parse err:", err.Error())
			}
		}
		if m.EndTime != "" {
			endTime, err := time.Parse(QueryTimeFormat, m.EndTime)
			if err == nil {
				qs = qs.Where("user_vm_record.created_at<?", endTime)
				countQuery = countQuery.Where("user_vm_record.created_at<?", endTime)
			} else {
				logger.Errorf("MallUserVmRecordList time end parse err:", err.Error())
			}
		}
	}

	qs = qs.Select("user_vm_record.*, user.tel").
		Joins("Left JOIN user ON user_vm_record.uid = user.uid")
	err := qs.Offset(page * m.PageSize).Limit(m.PageSize).Order("created_at desc").Find(&list).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, 0, err
	}

	// 计算count
	var count int64
	err = countQuery.Count(&count).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, 0, err
	}

	for i, _ := range list {
		list[i].ExpiryVm = list[i].Alter - list[i].UsedVm
	}

	return list, count, nil
}

func MallUserVmRecordListSetUser(list []UserVmRecord) []UserVmRecord {
	ids := make([]uint32, 0, len(list))
	for i, _ := range list {
		ids = append(ids, list[i].Uid)
	}
	if len(ids) == 0 {
		return list
	}

	infoMap, err := GetUserInfoMap(ids)
	if err != nil {
		logger.Errorf("user info map err:", logger.Field("err", err))
		return list
	}

	for i, _ := range list {
		v, ok := infoMap[list[i].Uid]
		if ok {
			list[i].User = &v
		}
		fmt.Println("UserInfo:", v)
	}

	return list
}

//func (c *GoodsCat) Add() error {
//	err := orm.Eloquent.Create(c).Error
//}

func SpecListSetValue(list []Spec) []Spec {
	sids := make([]uint32, 0, len(list))
	for i, _ := range list {
		sids = append(sids, list[i].ID)
	}
	specValueMap, err := GetSpecValueMap(sids)
	if err != nil {
		logger.Errorf("get spec value map err:", err)
		return list
	}
	for i, _ := range list {
		v, ok := specValueMap[list[i].ID]
		if ok {
			list[i].Values = v
		}
	}

	return list
}

func GetSpecValueMap(ids []uint32) (map[uint32][]SpecValue, error) {
	specValueMap := make(map[uint32][]SpecValue, 0)
	if len(ids) == 0 {
		return specValueMap, nil
	}
	var specValues []SpecValue
	err := orm.Eloquent.Table("spec_value").Where("spec_id in (?)", ids).
		Order("spec_id DESC,sort DESC").Find(&specValues).Error
	if err != nil {
		logger.Errorf("create spec value list err:", err)
		return specValueMap, err
	}
	for i, _ := range specValues {
		specValueMap[specValues[i].SpecId] = append(specValueMap[specValues[i].SpecId], specValues[i])
	}

	return specValueMap, nil
}

func (a *GoodsAttribute) SetSpecValues() {
	if a.SpecValueIndex == "" {
		return
	}

	err := orm.Eloquent.Table("spec_value").Where(fmt.Sprintf("id in (%s)", a.SpecValueIndex)).
		Find(&a.SpecValues).Error
	if err != nil {
		logger.Errorf("set spec value list err:", err)
		return
	}
}

func GetGoods(id uint32) (Goods, error) {
	var goods Goods
	err := orm.Eloquent.Table("goods").Where("goods_id=?", id).Find(&goods).Error
	if err != nil {
		logger.Errorf("goods err:", err)
		return goods, err
	}
	return goods, nil
}

func IndexSortString(n string) (string, error) {
	numStrings := strings.Split(n, ",")
	nums := make([]int, 0, len(numStrings))
	for i, _ := range numStrings {
		num, err := strconv.Atoi(numStrings[i])
		if err != nil {
			logger.Errorf("num err:", err)
			return "", err
		}
		nums = append(nums, num)
	}
	ns := ""
	sort.Ints(nums)
	for i, _ := range nums {
		ns += fmt.Sprintf("%d,", nums[i])
	}

	return ns[:len(ns)-1], nil
}

func (g *Goods) UpdateSpecList() {
	//fmt.Println("更新goods id", g.GoodsId)
	var attributeList []GoodsAttribute
	err := orm.Eloquent.Table("goods_attribute").Where("goods_id=?", g.GoodsId).Find(&attributeList).Error
	if err != nil && err != RecordNotFound {
		log.Error().Msgf(" attribute list err:%#v", err)
		return
	}
	var goods Goods
	err = orm.Eloquent.Table("goods").Where("goods_id=?", g.GoodsId).Find(&goods).Error
	if err != nil && err != RecordNotFound {
		log.Error().Msgf(" attribute list err:%#v", err)
		return
	}
	var combo GoodsAttributeCombo
	err = orm.Eloquent.Table("goods_attribute_combo").Where("goods_id=?", g.GoodsId).
		Order("price_rm ASC").Limit(1).Find(&combo).Error
	if err != nil && err != RecordNotFound {
		log.Error().Msgf(" attribute list err:%#v", err)
		return
	}
	//priceRm := uint32(0)
	//if g.PriceRm == 1000000 {
	//	priceRm = goods.PriceRm
	//	if goods.PriceRm > combo.PriceRm {
	//		priceRm = combo.PriceRm
	//	}
	//} else {
	//	priceRm = g.PriceRm
	//	if g.PriceRm > combo.PriceRm {
	//		priceRm = combo.PriceRm
	//	}
	//}
	if len(attributeList) == 0 {
		err = orm.Eloquent.Table("goods").Where("goods_id=?", g.GoodsId).Updates(map[string]interface{}{
			"spec_list":  "",
			"spec_index": "",
			//"price_rm":   priceRm,
		}).Error
		if err != nil {
			log.Error().Msgf("update goods spec list err:%#v", err)
		}
		return
	}
	ids := make([]string, 0)
	idMap := make(map[string]int, 0)
	for i, _ := range attributeList {
		idxList := strings.Split(attributeList[i].SpecValueIndex, ",")
		for _, idx := range idxList {
			_, ok := idMap[idx]
			if !ok {
				idMap[idx] = i
				ids = append(ids, idx)
			}
		}
	}
	//fmt.Println("更新goods id------------1", g.GoodsId)
	var val []SpecValue
	err = orm.Eloquent.Table("spec_value").Where("id in (?)", ids).
		Order("spec_sort DESC,sort DESC").Find(&val).Error
	if err != nil {
		log.Error().Msgf("spec value err:%#v", err)
		return
	}
	specIds := ""
	specList := make([]GoodsSpec, 0)
	valMap := make(map[uint32][]SpecValue, 0)
	for i, _ := range val {
		_, ok := valMap[val[i].SpecId]
		if ok {
			valMap[val[i].SpecId] = append(valMap[val[i].SpecId], val[i])
		} else {
			spec := Spec{
				DisplayName: val[i].SpecDisplayName,
				Sort:        val[i].SpecSort,
			}
			spec.ID = val[i].SpecId
			specList = append(specList, GoodsSpec{Spec: spec})
			specIds += fmt.Sprintf("%d,", spec.ID)
			valMap[val[i].SpecId] = []SpecValue{val[i]}
		}
	}
	//fmt.Println("更新goods id------------2", g.GoodsId)
	for i, _ := range specList {
		v, ok := valMap[specList[i].Spec.ID]
		if ok {
			specList[i].Values = v
		}
	}
	sortString, err := IndexSortString(specIds[:len(specIds)-1])
	if err != nil {
		log.Error().Msgf("index sort err:%#v", err)
		return
	}
	specString, err := json.Marshal(specList)
	if err != nil {
		log.Error().Msgf("marshal spec list err:%#v", err)
		return
	}

	err = orm.Eloquent.Table("goods").Where("goods_id=?", g.GoodsId).Updates(map[string]interface{}{
		"spec_list":  specString,
		"spec_index": sortString,
		//"price_rm":   priceRm,
	}).Error
	if err != nil {
		log.Error().Msgf("update goods spec list err:%#v", err)
		return
	}
	//fmt.Println("更新goods id------------3", g.GoodsId)
	return
}

func UpdateSpecList(goodsId, miniRm uint32) {
	goods := &Goods{}
	goods.GoodsId = goodsId
	goods.PriceRm = miniRm
	goods.UpdateSpecList()
}

func IndexToString(ids []int) string {
	sort.Ints(ids)
	idString := ""
	for i, _ := range ids {
		idString += fmt.Sprintf("%d,", ids[i])
	}
	return idString[:len(idString)-1]
}

func GetGoodsAttribute(id uint32) (*GoodsAttribute, error) {
	var attribute GoodsAttribute
	err := orm.Eloquent.Table("goods_attribute").Where("id=?", id).Find(&attribute).Error
	if err != nil {
		log.Error().Msgf("attribute err:%#v", err)
		return &attribute, err
	}
	return &attribute, nil
}

func GoodsListSetGoodsCat(list []Goods) {
	ids := make([]uint32, 0, len(list))
	for i, _ := range list {
		ids = append(ids, list[i].CatId)
	}
	if len(ids) == 0 {
		return
	}
	catMap, err := GetGoodsCatMap(ids)
	if err != nil {
		log.Error().Msgf("goods cat err:%#v", err)
		return
	}

	for i, _ := range list {
		v, ok := catMap[list[i].CatId]
		if ok {
			list[i].GoodsCat = v
		}
	}
}

func GetGoodsCatMap(ids []uint32) (map[uint32]*GoodsCat, error) {
	catMap := make(map[uint32]*GoodsCat, 0)
	if len(ids) == 0 {
		return catMap, nil
	}
	var cats []GoodsCat
	err := orm.Eloquent.Table("goods_cat").Where("id in (?)", ids).Find(&cats).Error
	if err != nil {
		log.Error().Msgf("goods cat err:%#v", err)
		return catMap, err
	}
	for i, _ := range cats {
		catMap[cats[i].ID] = &cats[i]
	}

	return catMap, nil
}

func GetGoodsCat(id uint32) (*GoodsCat, error) {
	var cat GoodsCat
	err := orm.Eloquent.Table("goods_cat").Where("id=?", id).Find(&cat).Error
	if err != nil {
		log.Error().Msgf("goods cat err:%#v", err)
		return &cat, err
	}
	if cat.Pid != 0 {
		var pCat GoodsCat
		err := orm.Eloquent.Table("goods_cat").Where("id=?", cat.Pid).Find(&pCat).Error
		if err != nil {
			log.Error().Msgf("goods cat err:%#v", err)
			return &cat, err
		}
		pCat.SubCats = []GoodsCat{cat}
		return &pCat, nil
	}

	return &cat, nil
}

func GoodsAttributeListSetSpecValues(attributes []GoodsAttribute) {
	for i, _ := range attributes {
		err := json.Unmarshal([]byte(attributes[i].SpecValueList), &attributes[i].SpecValues)
		if err != nil {
			log.Error().Msgf("spec value err:%#v", err)
			continue
		}
	}
	//GoodsAttribute{}
}

func GoodsAttributeListSetCombos(attributes []GoodsAttribute) {
	ids := make([]uint32, 0)
	for i, _ := range attributes {
		ids = append(ids, attributes[i].ID)
	}
	comboMap := GetGoodsAttributeComboMap(ids)
	for i, _ := range attributes {
		v, ok := comboMap[attributes[i].ID]
		if ok {
			attributes[i].Combos = v
		}
	}
}

func GetGoodsAttributeComboMap(attributeIds []uint32) map[uint32][]GoodsAttributeCombo {
	attributeMap := make(map[uint32][]GoodsAttributeCombo, 0)
	if len(attributeIds) == 0 {
		return attributeMap
	}
	var combos []GoodsAttributeCombo
	err := orm.Eloquent.Table("goods_attribute_combo").Where("goods_attribute_id in (?)", attributeIds).
		Find(&combos).Error
	if err != nil {
		log.Error().Msgf("goods attribute combo err:%#v", err)
		return attributeMap
	}
	for i, _ := range combos {
		attributeMap[combos[i].GoodsAttributeId] =
			append(attributeMap[combos[i].GoodsAttributeId], combos[i])
	}

	return attributeMap
}

func GetCombo(id uint32) (*GoodsAttributeCombo, error) {
	var combo GoodsAttributeCombo
	err := orm.Eloquent.Table("goods_attribute_combo").Where("id=?", id).Find(&combo).Error
	if err != nil {
		log.Error().Msgf("goods attribute combo err:%#v", err)
		return nil, err
	}

	return &combo, nil
}

type GoodsOrderRefundSendReceiveReq struct {
	OrderId uint32  `json:"order_id"`
	SysUser SysUser `json:"sys_user"`
}

func (r *GoodsOrderRefundSendReceiveReq) Receive() error {
	var goodsOrder GoodsOrder
	err := orm.Eloquent.Table("goods_order").Where("order_id=?", r.OrderId).Find(&goodsOrder).Error
	if err != nil {
		log.Error().Msgf("goods order err:%#v", err)
		return err
	}

	switch goodsOrder.State {
	case GoodsOrderStateUnPay: //待付款
		logger.Errorf("退货失败：订单未付款")
		return errors.New("订单未付款")
	case GoodsOrderStateDelivered: //已发货
		logger.Errorf("退货失败：订单已发货，需用户接收后发起退货")
		return errors.New("订单已发货，需用户接收后发起退货")
	case GoodsOrderStateRefundedCancel: // 已取消
		logger.Errorf("退货失败：订单已取消")
		return errors.New("订单已取消")
	case GoodsOrderStateRefunded: // 已退货
		logger.Errorf("退货失败：订单已退货，请勿重复操作")
		return errors.New("订单已退货，请勿重复操作")
	}

	begin := orm.Eloquent.Begin()
	if goodsOrder.Vm != 0 {
		err = UserVmUpdate(begin, "", goodsOrder.Uid, int(goodsOrder.Vm), VmEventBuyGoods, "购买商品积分抵扣取消")
		if err != nil {
			logger.Errorf("update  user vm err:", err)
			return err
		}
	}

	var goodsAttribute GoodsAttribute
	err = orm.Eloquent.Table("goods_attribute").Where("id=?", goodsOrder.GoodsAttributeId).Find(&goodsAttribute).Error
	if err != nil {
		log.Error().Msgf("get goods attribute err:%#v", err)
		return err
	}

	outTradeNo, err := GetWxPayExpressFeeRefundRecord(goodsOrder.OrderId)
	if err != nil {
		log.Error().Msgf("express fee refund record err:%#v", err)
		return err
	}
	if outTradeNo == "" {
		log.Error().Msgf("未查询到商户订单号")
		return errors.New("未查询到商户订单号")
	}

	memberRecord := &UserOpenMemberRecord{OpenNo: GetOrderSn(), OrderType: 8, GoodsOrder: &goodsOrder}

	// 判断收款帐户goods.GoodsAccountNum：1 明慧 2迪为
	var goods Goods
	err = orm.Eloquent.Table("goods").Where("goods_id=?", goodsOrder.GoodsId).Find(&goods).Error
	if err != nil || goods.ID == 0 {
		log.Error().Msgf("get goods err:%#v", err)
		return errors.New("未查询到商品信息")
	}

	if goodsOrder.Rm != 0 { // 如果有支付，则走退款流程
		if goods.GoodsAccountNum == 1 { // 明慧，默认使用杉德河马付
			// 记录UserOpenMemberRecord
			memberRecord.Uid = goodsOrder.Uid
			memberRecord.OrderId = goodsOrder.ID
			err = orm.Eloquent.Create(memberRecord).Error
			if err != nil {
				logger.Error("insert user open member record err:", logger.Field("err", err))
				return err
			}

			// 查询付款信息
			var fundRecord FundRecord
			err = orm.Eloquent.Table("fund_record").Where("out_trade_no=?", outTradeNo).Find(&fundRecord).Error
			if err != nil || fundRecord.ID == 0 {
				log.Error().Msgf("get fund_record err:%#v", err)
				return errors.New("未查询到付款信息")
			}

			refundReq := pay.HmPayTradeRefundContent{
				OutOrderNo:      outTradeNo,
				BankOrderNo:     fundRecord.TransactionId,
				RefundAmount:    float64(fundRecord.Amount) / 100.0,
				RefundRequestNo: GenerateRefundOrderNo(),
			}
			resp, err := pay.HmRefundOrder(refundReq, 100001)
			if err != nil {
				log.Error().Msgf("order refund err:%#v", err)
				return err
			}
			if resp.SubCode != "REFUND_SUCCESS" {
				log.Error().Msg("河马付退款失败")
				return errors.New(resp.SubMsg)
			} else { // 退款成功，记录订单信息
				refundRecord := &FundRecord{
					Uid:           fundRecord.Uid,
					FundType:      "buy_goods_refund",
					Amount:        int64(resp.RefundAmount*100) * (-1),
					TransactionId: resp.BankOrderNo,
					OutTradeNo:    resp.OutOrderNo,
					RefundId:      resp.RefundBankTrxNo,
					Status:        2,
					Remark:        "商城购买退货",
				}
				err = orm.Eloquent.Create(refundRecord).Error
				if err != nil {
					logger.Errorf("create fund record err:", err.Error())
					return err
				}
			}
		} else {
			err = memberRecord.MallGoodsOrderRefund(outTradeNo, goods.GoodsAccountNum)
			if err != nil {
				log.Error().Msgf("order refund err:%#v", err)
				return err
			}
		}
	}

	// 更新订单为"已退货"状态
	err = begin.Table("goods_order").Where("order_id=?", r.OrderId).Update("state", GoodsOrderStateRefunded).Error
	if err != nil {
		begin.Rollback()
		log.Error().Msgf("update state err:%#v", err)
		return err
	}
	// 更新库存
	err = OrderUpdateGoodsStockBack(goodsAttribute.ID, goodsOrder.Quantity, begin)
	if err != nil {
		begin.Rollback()
		log.Error().Msgf("goods stock back err:%#v", err)
		return err
	}
	if goodsOrder.Vm == 0 && strings.Contains(goods.Name, "预售") { // 目前只有主机预售券可以退款；普通的积分兑换不支持退货
		err = begin.Table("user_coupon").Where("uid = ? and activity_id = ?", goodsOrder.Uid, 10).
			Updates(map[string]interface{}{
				"state":      4,
				"updated_at": time.Now(),
			}).Error
		if err != nil {
			begin.Rollback()
			log.Error().Msgf("update state err:%#v", err)
			return err
		}
	}
	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		log.Error().Msgf("commit err:%#v", err)
		return err
	}

	operationLog := &OperationLog{
		SysUid:                uint32(r.SysUser.UserId),
		Description:           "商城购买退货入库",
		OperationType:         OperationTypeMallOrderRefundSendReceive,
		CorrelationId:         goodsOrder.OrderId,
		CorrelationName:       "order_id",
		StoreId:               goodsOrder.DeliverStoreId,
		StoreName:             "",
		CooperativeName:       r.SysUser.CooperativeName,
		CooperativeBusinessId: r.SysUser.CooperativeBusinessId,
		Detail:                "",
	}
	operationLog.AddLog()

	return nil
}

// GenerateRefundOrderNo 生成退款订单号（例如：R202505271545301234567890）
func GenerateRefundOrderNo() string {
	// 设置随机种子
	rand.Seed(time.Now().UnixNano())

	// 当前时间：年月日时分秒（14位）
	timestamp := time.Now().Format("20060102150405")

	// 生成 10 位随机数：范围是 1000000000 ~ 9999999999
	randomNum := rand.Int63n(9000000000) + 1000000000 // int63 支持更大范围

	// 拼接最终退款订单号
	refundOrderNo := fmt.Sprintf("R%s%d", timestamp, randomNum)

	return refundOrderNo
}

func GetWxPayExpressFeeRefundRecord(orderId uint32) (string, error) {
	var openMemberRecord UserOpenMemberRecord
	err := orm.Eloquent.Table("user_open_member_record").Where("order_id=?", orderId).
		Order("id DESC").Limit(1).Find(&openMemberRecord).Error
	if err != nil {
		logger.Errorf("err:", err)
		return "", err
	}
	return openMemberRecord.OpenNo, nil
}

func OrderUpdateGoodsStockBack(attributeId, count uint32, gdb *gorm.DB) error {
	if gdb == nil {
		gdb = orm.Eloquent
	}

	// 防止 sold_count 小于 count，避免变成负数
	sql := `
		UPDATE goods_attribute
		SET stock = stock + ?,
		    sold_count = sold_count - ?
		WHERE id = ?
		AND sold_count >= ?
	`

	err := gdb.Exec(sql, count, count, attributeId, count).Error
	if err != nil {
		logger.Errorf("OrderUpdateGoodsStockBack error: %v", err)
		return err
	}
	return nil
}

// 发货
const (
	DeliverTaskStateOnDeliver = "on_deliver" // 待发货
	DeliverTaskStateDelivered = "delivered"  // 已发货
	DeliverTaskStateCancel    = "cancel"     // 已取消
	DeliverTaskStateComplete  = "complete"   // 已完成
)

// gen:qs
type DeliverTask struct {
	Model
	Uid            uint32            `json:"uid"`
	UserAddressId  uint32            `json:"user_address_id"` // 用户地址
	State          string            `json:"state"`           // 状态
	OrderType      uint32            `json:"order_type"`      // 1-借卡 2-商城购买 3-收回卡
	StoreId        uint32            `json:"store_id"`
	DeliverTime    time.Time         `json:"deliver_time"`          // 发货时间
	DeliverStoreId uint32            `json:"deliver_store_id"`      // 发货门店
	UserAddress    *UserAddress      `json:"user_address" gorm:"-"` // 用户地址
	Subs           []*DeliverTaskSub `json:"subs" gorm:"-"`
	Store          *Store            `json:"store" gorm:"-"` // 门店
	// deliver_task
}

// gen:qs
type DeliverTaskSub struct {
	Model
	Uid           uint32      `json:"uid"`
	DeliverTaskId uint32      `json:"deliver_task_id"`
	UserAddressId uint32      `json:"user_address_id"` // 用户地址
	State         string      `json:"state"`           // 状态
	OrderType     uint32      `json:"order_type"`      // 1-借卡 2-商城购买 3-收回卡
	OrderId       uint32      `json:"order_id"`        // 订单id
	StoreId       uint32      `json:"store_id"`        //
	GoodsOrder    *GoodsOrder `json:"goods_order" gorm:"-"`
	Order         *Order      `json:"order" gorm:"-"`
	// deliver_task_sub
}

type DeliverTaskReq struct {
	PageIdx  int    `json:"pageIndex"`
	PageSize int    `json:"pageSize"`
	Uid      uint32 `json:"uid"`
	State    string `json:"state"` // 状态
	StoreId  uint32 `json:"store_id"`
}

func (m *DeliverTaskReq) List(c *gin.Context) ([]DeliverTask, int64, error) {
	page := m.PageIdx - 1
	if page < 0 {
		page = 0
	}
	if m.PageSize == 0 {
		m.PageSize = 10
	}

	var list []DeliverTask
	qs := orm.Eloquent.Table("deliver_task")

	// 非管理员才判断所属门店
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		sysUser, err := GetSysUserByCtx(c)
		if err != nil {
			return nil, 0, err
		}

		// 返回sysUser未过期的门店id列表
		storeList := GetValidStoreIDs(sysUser.StoreData)
		if m.StoreId != 0 {
			if !Contains(storeList, uint32(m.StoreId)) {
				return nil, 0, errors.New("您没有该门店权限")
			}
		} else {
			if len(storeList) > 0 {
				if len(storeList) == 1 {
					qs = qs.Where("store_id = ?", storeList[0])
				} else {
					qs = qs.Where("store_id IN (?)", storeList)
				}
			} else {
				return nil, 0, errors.New("用户未绑定门店")
			}
		}
	}

	if m.State != "" {
		qs = qs.Where("state=?", m.State)
	}
	if m.Uid != 0 {
		qs = qs.Where("uid=?", m.Uid)
	}
	if m.StoreId != 0 {
		if m.StoreId == 13 {
			fmt.Println("mendianid", m.StoreId)
			qs = qs.Where("store_id in (?)", []uint32{0, m.StoreId})
		} else {
			qs = qs.Where("store_id=?", m.StoreId)
		}
	}
	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, 0, err
	}
	//totalPage := int(count)/m.PageSize + 1

	err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&list).Error
	if err != nil {
		logger.Errorf("err:", err)
		return nil, 0, err
	}
	DeliverTaskListSetUserAddress(list)
	DeliverTaskListSetStore(list)
	return list, count, nil
}

func DeliverTaskListSetUserAddress(list []DeliverTask) {
	ids := make([]uint32, 0)
	for i, _ := range list {
		ids = append(ids, list[i].UserAddressId)
	}
	addressMap := GetUserAddressMap(ids)
	for i, _ := range list {
		v, ok := addressMap[list[i].UserAddressId]
		if ok {
			list[i].UserAddress = v
		}
	}
}

func DeliverTaskListSetStore(list []DeliverTask) {
	ids := make([]uint32, 0)
	for i, _ := range list {
		ids = append(ids, list[i].StoreId)
	}
	ids = append(ids, 13)
	storeMap := GetStoreMapByIds(ids)

	//addressMap := GetUserAddressMap(ids)
	for i, _ := range list {
		storeId := list[i].StoreId
		if storeId == 0 {
			storeId = 13
		}
		v, ok := storeMap[uint64(list[i].StoreId)]
		if ok {
			list[i].Store = v
		}
	}
}

func GetUserAddressMap(ids []uint32) map[uint32]*UserAddress {
	addressMap := make(map[uint32]*UserAddress, 0)
	if len(ids) == 0 {
		return addressMap
	}
	var list []UserAddress
	err := orm.Eloquent.Table("user_address").Where("id in (?)", ids).Find(&list).Error
	if err != nil {
		log.Error().Msgf("user address err:%#v", err)
		return addressMap
	}
	for i, _ := range list {
		addressMap[list[i].ID] = &list[i]
	}

	return addressMap
}

func DeliverTaskSubListSetDetail(list []*DeliverTaskSub) {
	for i, _ := range list {
		if list[i].OrderType == 1 {
			var order Order
			err := orm.Eloquent.Table("order").Where("id=?", list[i].OrderId).
				Find(&order).Error
			if err != nil {
				log.Error().Msgf("goods order err:%#v", err)
				return
			}

			var orderCards []OrderCard
			err = orm.Eloquent.Table("order_card").Where("order_id=?", order.ID).Find(&orderCards).Error
			if err != nil {
				logger.Errorf("err:", err)
				return
			}

			order.OrderCards = OrderCardListSetGameInfo(orderCards)

			list[i].Order = &order
		} else if list[i].OrderType == 2 {
			var goodsOrder GoodsOrder
			err := orm.Eloquent.Table("goods_order").Where("order_id=?", list[i].OrderId).
				Find(&goodsOrder).Error
			if err != nil {
				log.Error().Msgf("goods order err:%#v", err)
				return
			}
			goods := &Goods{GoodsId: goodsOrder.GoodsId}
			err = goods.GetDetail()
			if err != nil {
				log.Error().Msgf("GetDetail err:%#v", err)
				return
			}
			goodsOrder.Goods = goods
			list[i].GoodsOrder = &goodsOrder
		}
	}
}

func UpdateDeliverTaskSubState(orderId uint32) {
	err := orm.Eloquent.Table("deliver_task_sub").Where("order_id=?", orderId).
		Update("state", DeliverTaskStateDelivered).Error
	if err != nil {
		log.Error().Msgf("deliver task sub err:%#v", err)
		return
	}
	var sub DeliverTaskSub
	err = orm.Eloquent.Table("deliver_task_sub").Where("order_id=?", orderId).Find(&sub).Error
	if err != nil {
		log.Error().Msgf("deliver task sub err:%#v", err)
		return
	}
	exist, err := QueryRecordExist(
		fmt.Sprintf("SELECT * FROM deliver_task_sub WHERE deliver_task_id=%d AND state='%s'",
			sub.DeliverTaskId, DeliverTaskStateOnDeliver))
	if err != nil {
		logger.Errorf("deliver task sub exist err:", err)
		return
	}
	if !exist {
		err := orm.Eloquent.Table("deliver_task").Where("id=?", sub.DeliverTaskId).
			Update("state", DeliverTaskStateDelivered).Error
		if err != nil {
			log.Error().Msgf("deliver task sub err:%#v", err)
			return
		}
	}
}

func (o *GoodsOrder) SetDeliverStore() error {
	store, err := GetStore(o.DeliverStoreId)
	if err != nil {
		logger.Errorf("set deliver store err:", err)
		return err
	}
	o.DeliverStore = store
	return nil
}

func GetGoodsFirstSkuCombo(goodsId []uint32) []GoodsAttributeCombo {
	var list []GoodsAttributeCombo
	//查询每个商品按sort字端排序的最大的一个sku的价格
	err := orm.Eloquent.
		Raw(`
SELECT b.*
FROM (SELECT id
      FROM goods_attribute d
               INNER JOIN (SELECT goods_id, MAX(sort) AS max_sort FROM goods_attribute GROUP BY goods_id) c
                          ON c.goods_id = d.goods_id AND c.max_sort = d.sort) AS a
         INNER JOIN goods_attribute_combo b ON a.id = b.goods_attribute_id
WHERE b.goods_id IN (?)
GROUP BY b.goods_id
		`, goodsId).
		Scan(&list).
		Error
	if err != nil {
		logger.Errorf("get goods first sku failed", err)
		return nil
	}

	return list
}

// CheckOnDeliverMall 检测有无待发货的订单，及时提醒运营同事
func CheckOnDeliverMall() {
	var orders []GoodsOrder
	err := orm.Eloquent.Table("goods_order").Where("state = ?", GoodsOrderStateOnDeliver).Find(&orders).Error
	if err != nil {
		logger.Errorf("Failed to query orders: %v", err)
		return
	}

	if len(orders) == 0 {
		logger.Info("No pending delivery orders.")
		return
	}

	// 获取需要通知的手机号列表
	var phoneNumbers = []string{"15019230751", "13590423587", "13940109711"} // 示例多个手机号

	// 短信通知逻辑
	message := fmt.Sprintf("【明慧科技】温馨提示：小程序商城有%d个待发货订单，请及时处理。", len(orders))
	err = GtSendMessage(phoneNumbers, message)
	status := 1
	if err != nil {
		status = 2
		logger.Error(err.Error())
	}

	// 记录短信发送情况
	for _, phone := range phoneNumbers {
		smsSend := &ExpireMemberSmsSend{
			Message:  message,
			SendTime: time.Now(),
			Tel:      phone,
			Status:   uint32(status),
		}
		err = orm.Eloquent.Create(&smsSend).Error
		if err != nil {
			logger.Errorf("Failed to create SMS record: ", err)
		}
	}
}
