package dao

import (
	"errors"
	"fmt"
	"strings"
	"time"

	beego "github.com/astaxie/beego/server/web"

	"git.rosy.net.cn/jx-callback/business/jxutils"
	"git.rosy.net.cn/jx-callback/business/model"
	"git.rosy.net.cn/jx-callback/globals/refutil"

	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/globals"
)

type StoreSkuAndAct struct {
	*model.StoreSkuBind
	ActMap map[int]*model.StoreSkuAct
}

var (
	dataResFieldMap = map[int]string{
		model.VendorIDMTWM:   "mtwm_url",
		model.VendorIDEBAI:   "ebai_url",
		model.VendorIDJDShop: "jds_url",
	}
	salePriceLimit = 100
)

type SkuStoreCatInfo struct {
	VendorID      int    `orm:"column(vendor_id)" json:"vendorID"`
	VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码，如果只有一个，可以为空

	MapID int `orm:"column(map_id)"` // 这个主要用于判断是否有store_sku_category_map
	model.SkuCategory
	VendorCatID   string `orm:"column(vendor_cat_id)"`
	CatSyncStatus int8

	ParentMapID         int `orm:"column(parent_map_id)"` // 这个主要用于判断是否有父store_sku_category_map
	ParentCatName       string
	ParentVendorCatID   string `orm:"column(parent_vendor_cat_id)"`
	ParentCatSyncStatus int8

	StoreCatID         int `orm:"column(store_category_id)"`
	StoreCatName       string
	StoreCatSeq        int
	StoreParentCatName string
	IsSysCat           int
	CityCode           int
	BrandId            int
	IsJxCat            int

	VendorCategoryName string
	VendorCategorySeq  int
	VendorCategoryID   int `orm:"column(vendor_category_id)"`
}

type StoreSkuSyncInfo struct {
	StoreSkuSyncInfoJds []*StoreSkuSyncInfo
	VendorID            int    `orm:"column(vendor_id)" json:"vendorID"`
	VendorOrgCode       string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码，如果只有一个，可以为空

	// 平台无关的store sku信息
	BindID  int `orm:"column(bind_id)"` // 换名的原因是与Sku.ID同名区别
	StoreID int `orm:"column(store_id)"`
	SkuID   int `orm:"column(sku_id)"` // 这个与Sku.ID的区别是SkuID是必然存在的

	BoxFee int64

	Price     int64
	UnitPrice int64
	Stock     int

	// 平台相关的store sku信息
	StoreSkuStatus  int       // 库存状态
	SkuSyncStatus   int8      // 锁定状态
	VendorSkuID     string    `orm:"column(vendor_sku_id)"`      // 子商品id
	VendorSonSkuID  string    `orm:"column(vendor_son_sku_id)"`  // 子商品skuid
	VendorSkuAttrId string    `orm:"column(vendor_sku_attr_id)"` // 主商品skuid
	VendorMainId    string    `orm:"column(vendor_main_id)"`     // 主商品id
	JdsWareID       int64     `orm:"column(jds_ware_id)" json:"jdsWareID"`
	BindDeletedAt   time.Time `orm:"type(datetime)" json:"bindDeletedAt"`
	LocationCode    string    `orm:"column(location_code)" json:"locationCode"` // 商品货架码

	model.Sku
	ExdSkuID           string `orm:"column(exd_sku_id)"`
	ExdCategoryThirdID int    `orm:"column(exd_category_third_id)"`
	BrandID            int    `orm:"column(brand_id)"`
	ExBrandID          int    `orm:"column(ex_brand_id)"`
	StoreName          string

	// sku_name
	Prefix        string
	ExPrefix      string
	ExPrefixBegin *time.Time
	ExPrefixEnd   *time.Time

	// NameID       int    `orm:"column(name_id)"`
	VendorNameID     string `orm:"column(vendor_name_id)"` // 暂时无用
	Name             string
	Unit             string
	Upc              string
	UpcBrandName     string `orm:"column(upc_brand_name)" json:"upcBrandName"`          // upc商品时使用(品牌名称)
	UpcTiktokBrandId string `orm:"column(upc_tiktok_brand_id)" json:"upcTiktokBrandId"` // upc商品时使用(抖音品牌id)
	IsGlobal         int8   `orm:"default(1)" json:"isGlobal"`                          // 是否是全部（全国）可见，如果否的话，可见性由SkuPlace决定
	NameStatus       int
	SellCities       []string
	NameCategoryID   int    `orm:"column(name_category_id)"`
	TiktokAttribute  string `orm:"column(tiktok_attribute)"`
	MtAttribute      string `orm:"column(mt_attribute)"`
	EbaiAttribute    string `orm:"column(ebai_attribute)"`
	SellPoint        string `orm:"column(sell_point)"`       // 目前是美团买点
	SellPointTimes   string `orm:"column(sell_point_times)"` // 目前是美团买点展示时间
	YbNameSuffix     string //银豹的商品条码后缀
	YbBarCode        string //银豹的商品条码
	JdsStockSwitch   int
	PreparationTime  int
	LocalCategoryId  int `orm:"column(local_category_id)"`
	// 平台相关的图片信息
	Img              string
	Img2             string
	Img3             string
	Img4             string
	Img5             string
	DescImg          string
	ImgWatermark     string `json:"imgWatermark"` //图片水印
	ImgMix           string //合成水印后的图片
	ImgOrigin        string //skuname里的img
	QuaPictures      string // 资质图片
	QuaEffectiveDate int64  // 资质有效期
	QuaApprovalDate  int64  // 批准日期
	SpecialPictures  string // 商品扩展规则(营业成分)

	VendorVendorCatID int64  `orm:"column(vendor_vendor_cat_id)"` // 平台商品分类（叶子结点）
	CategoryName      string `json:"categoryName"`                //分类名
	// sku的商家分类信息
	SkuCatSyncStatus int8
	SkuVendorCatID   string `orm:"column(sku_vendor_cat_id)"`

	// sku_name的商家分类信息
	CatSyncStatus     int8
	VendorCatID       string `orm:"column(vendor_cat_id)"`
	SkuVendorMapCatID string `orm:"column(sku_vendor_map_cat_id)"`
	VendorPrice       int64  // 平台价格
	LockTime          *time.Time
	MergedStatus      int
	SkuName           string
	SkuNameOrigin     string
	StatusSaleBegin   int16  `json:"statusSaleBegin"` //商品可售时间范围
	StatusSaleEnd     int16  `json:"statusSaleEnd"`
	VendorActID       string `orm:"column(vendor_act_id);size(48)" json:"vendorActID"`
	ActPercentage     int    `json:"actPercentage"` // 直降活动百分比
	ActSyncStatus     int8   `orm:"default(2)" json:"actSyncStatus"`
	VendorActPrice    int64  `json:"vendorActPrice"`   // 保存数据用，实际的活动价
	MtLadderBoxPrice  int    `json:"mtLadderBoxPrice"` //美团门店商品的包装费
	IsDeletedBySku    bool   `json:"isDeletedBySku"`   //京东商城用，同步下架的商品库里的sku时，要做区分来决定调的api
}

type MissingStoreSkuInfo struct {
	StoreID     int `orm:"column(store_id)"`
	NameID      int `orm:"column(name_id)"`
	SkuID       int `orm:"column(sku_id)"`
	SpecQuality float32
	SpecUnit    string
	Unit        string
	RefPrice    int
}

type StoreSkuBindWithVendorInfo struct {
	model.StoreSkuBind

	VendorStoreID string `orm:"column(vendor_store_id)"`
	VendorSkuID   string `orm:"column(vendor_sku_id)"`
}

type StoreSkuNameInfo struct {
	StoreID   int `orm:"column(store_id)"`
	NameID    int `orm:"column(name_id)"`
	UnitPrice int64
}

// GetStoreSkus用
type StoreSkuNameExt struct {
	StoreID   int    `orm:"column(store_id)" json:"storeID"`
	StoreName string `json:"storeName"`
	SkuID     int    `orm:"column(sku_id)" json:"skuID"`
	model.SkuName
	PayPercentage int            `json:"payPercentage"`
	UnitPrice     int            `json:"unitPrice"`
	Skus          []*StoreSkuExt `orm:"-" json:"skus,omitempty"`
	SkusStr       string         `json:"-"`

	PendingOpType    int8   `json:"pendingOpType"`    // 取值同 StoreOpRequest.Type
	PendingUnitPrice int    `json:"pendingUnitPrice"` // 这个是待审核的价格申请
	RealMidUnitPrice int    `json:"realMidUnitPrice"`
	Count            int    `json:"count"`
	YbSkuName        string `json:"ybSkuName"`
	AuditUnitPrice   int    `json:"auditUnitPrice"` //审核价格
}

type StoreSkuNameExt2 struct {
	ID int `orm:"column(id)" json:"id"`

	Prefix string `orm:"size(255)" json:"prefix"`
	Name   string `orm:"size(255)" json:"name"`

	CategoryID int `orm:"column(category_id);index" json:"categoryID"` // 标准类别

	Unit         string  `orm:"size(8)" json:"unit"`
	SpecQuality  float32 `json:"-"`               // 为份必然为500，这个主要作用只是用于确保SkuName的唯一性
	SpecUnit     string  `orm:"size(8)" json:"-"` // 为份必然为克，这个主要作用只是用于确保SkuName的唯一性
	Price        int     `json:"price"`           // 单位为分，标准价，不为份的就为实际标准价，为份的为每市斤价，实际还要乘质量。todo 为份的确定必须有质量
	Img          string  `orm:"size(512)" json:"img"`
	Img2         string  `orm:"size(512)" json:"img2"`         // 第二张图片
	Img3         string  `orm:"size(512)" json:"img3"`         //第三张图片
	Img4         string  `orm:"size(512)" json:"img4"`         //第三张图片
	Img5         string  `orm:"size(512)" json:"img5"`         //第三张图片
	ImgWatermark string  `orm:"size(512)" json:"imgWatermark"` //图片水印
	ImgMix       string  `orm:"size(512)" json:"imgMix"`       //图片混合水印的图片
	DescImg      string  `orm:"size(255)" json:"descImg"`      // 商品详情图片描述
	Status       int     `orm:"default(1)" json:"status"`      // skuname状态，取值同sku.Status

	YbNameSuffix  string         `json:"ybNameSuffix"` //银豹商品后缀
	StoreID       int            `orm:"column(store_id)" json:"storeID"`
	StoreName     string         `json:"storeName"`
	SkuID         int            `orm:"column(sku_id)" json:"skuID"`
	PayPercentage int            `json:"-"`
	UnitPrice     int            `json:"unitPrice"`
	Skus          []*StoreSkuExt `orm:"-" json:"skus,omitempty"`
	SkusStr       string         `json:"-"`

	PendingUnitPrice int `json:"pendingUnitPrice"` // 这个是待审核的价格申请
	RealMidUnitPrice int `json:"realMidUnitPrice"`
	Count            int `json:"count"`
	AuditUnitPrice   int `json:"auditUnitPrice"` //审核价格
}

// GetStoreSkus用
type StoreSkuNamesInfo struct {
	TotalCount int                `json:"totalCount"`
	SkuNames   []*StoreSkuNameExt `json:"skuNames"`
}

type StoreSkuNamesInfo2 struct {
	TotalCount int                 `json:"totalCount"`
	SkuNames   []*StoreSkuNameExt2 `json:"skuNames"`
}

type StoreSkuVendorInfo struct {
	VendorID int `orm:"column(vendor_id)" json:"vendorID"`

	VendorSkuID string     `orm:"column(vendor_sku_id)" json:"vendorSkuID"`
	SyncStatus  int8       `json:"syncStatus"`
	VendorPrice int        `json:"vendorPrice"`
	LockTime    *time.Time `json:"lockTime,omitempty"`

	ActPrice int `json:"actPrice"`
	ActID    int `orm:"column(act_id)" json:"actID"`
	ActType  int `orm:"column(act_type)" json:"actType"`

	EarningPrice int `json:"earningPrice"`
	EarningActID int `orm:"column(earning_act_id)" json:"earningActID"`

	// 新活动信息
	VendorActID    string `orm:"column(vendor_act_id);size(48)" json:"vendorActID"`
	HintActID      int    `orm:"column(hint_act_id);size(48);index" json:"hintActID"`
	ActPercentage  int    `json:"actPercentage"` // 直降活动百分比
	ActSyncStatus  int8   `orm:"default(2)" json:"actSyncStatus"`
	VendorActPrice int64  `json:"vendorActPrice"` // 保存数据用，实际的活动价
}

type StoreSkuExt struct {
	NameID           int       `orm:"column(name_id)" json:"nameID"`
	SkuID            int       `orm:"column(sku_id)" json:"id"`
	Comment          string    `orm:"size(255)" json:"comment"`
	SkuCategoryID    int       `orm:"column(sku_category_id)" json:"categoryID"`
	SkuSpecQuality   float32   `json:"specQuality"`
	SkuSpecUnit      string    `orm:"size(8)" json:"specUnit"` // 质量或容量
	Weight           int       `json:"weight"`                 // 重量/质量，单位为克，当相应的SkuName的SpecUnit为g或kg时，必须等于SpecQuality
	SkuStatus        int       `json:"status"`
	Stock            int       `json:"stock"`
	LocationCode     string    `orm:"column(location_code)" json:"locationCode"`
	CategoryName     string    `orm:"column(categoryName)"`
	BindCreatedAt    time.Time `orm:"auto_now_add;type(datetime)" json:"createdAt"`
	BindUpdatedAt    time.Time `orm:"auto_now;type(datetime)" json:"updatedAt"`
	BindLastOperator string    `orm:"size(32)" json:"lastOperator"` // 最后操作员
	BindDeletedAt    time.Time `orm:"type(datetime)" json:"deletedAt"`
	SubStoreID       int       `orm:"column(sub_store_id)" json:"subStoreID"`
	BindPrice        int       `json:"price"`     // 单位为分，不用int64的原因是这里不需要累加
	UnitPrice        int       `json:"unitPrice"` // 这个是一斤的门店商品价，放在这里的原因是避免额外增加一张store sku_name表，逻辑上要保证同一SKU NAME中的所有SKU这个字段的数据一致
	StoreSkuStatus   int       `json:"storeSkuStatus"`
	AutoSaleAt       time.Time `orm:"type(datetime);null" json:"autoSaleAt"`

	StatusSaleBegin int16 `json:"statusSaleBegin"` //商品可售时间范围
	StatusSaleEnd   int16 `json:"statusSaleEnd"`

	Count int `json:"count"`
	Times int `json:"times"`

	// VendorInfoMap用于替换其之下的所有信息
	VendorInfoMap map[int]*StoreSkuVendorInfo `json:"vendorInfoMap,omitempty"`

	JdRemark string `orm:"column(jd_sku_remark)" json:"jdRemark"`
	JdID     string `orm:"column(sku_jd_id);null;index" json:"jdID"`
	EbaiID   string `orm:"column(ebai_id);index" json:"ebaiID"`
	MtwmID   string `orm:"column(mtwm_id)" json:"mtwmID"` // 这个也不是必须的，只是为了DAO取数据语句一致
	YbID     string `orm:"column(yb_id);index" json:"ybID"`
	DdID     string `orm:"column(dd_id);index" json:"ddID"`
	JdsID    string `orm:"column(jds_id);index" json:"jdsID"`
	TaoID    string `orm:"column(tao_id)" json:"taoID"` // 这个也不是必须的，只是为了DAO取数据语句一致

	JdSyncStatus   int8 `orm:"default(2)" json:"jdSyncStatus"`
	EbaiSyncStatus int8 `orm:"default(2)" json:"ebaiSyncStatus"`
	MtwmSyncStatus int8 `orm:"default(2)" json:"mtwmSyncStatus"`
	TaoSyncStatus  int8 `orm:"default(2)" json:"taoSyncStatus"`
	DdSyncStatus   int8 `orm:"default(2)" json:"ddSyncStatus"`
	YbSyncStatus   int8 `orm:"default(2)" json:"ybSyncStatus"`
	JdsSyncStatus  int8 `orm:"default(2)" json:"jdsSyncStatus"` //京东商城

	JdPrice   int `json:"jdPrice"`
	EbaiPrice int `json:"ebaiPrice"`
	MtwmPrice int `json:"mtwmPrice"`
	TaoPrice  int `json:"taoPrice"`
	JxPrice   int `json:"jxPrice"`
	YbPrice   int `json:"ybPrice"`
	JdsPrice  int `json:"jdsPrice"`
	DdPrice   int `json:"ddPrice"`

	JdLockTime   *time.Time `orm:"null" json:"jdLockTime,omitempty"`
	JdsLockTime  *time.Time `orm:"null" json:"jdsLockTime,omitempty"`
	EbaiLockTime *time.Time `orm:"null" json:"ebaiLockTime,omitempty"`
	MtwmLockTime *time.Time `orm:"null" json:"mtwmLockTime,omitempty"`
	TaoLockTime  *time.Time `orm:"null" json:"taoLockTime,omitempty"`
	DdLockTime   *time.Time `orm:"null" json:"ddLockTime,omitempty"`
	JxLockTime   *time.Time `orm:"null" json:"jxLockTime,omitempty"`
	YbLockTime   *time.Time `orm:"null" json:"ybLockTime,omitempty"`

	VendorActMaps  []*VendorActMap `json:"vendorActMaps"`
	ActPrice       int             `json:"actPrice"`
	ActID          int             `orm:"column(act_id)" json:"actID"`
	ActType        int             `orm:"column(act_type)" json:"actType"`
	DiscountType   int             `json:"discountType"`
	DiscountValue1 int             `json:"discountValue1"`
	DiscountValue2 int             `json:"discountValue2"`

	EarningPrice int `json:"earningPrice"`
	EarningActID int `orm:"column(earning_act_id)" json:"earningActID"`

	EclpID           string `orm:"column(eclp_id)" json:"eclpID"`
	TrendType        int    `json:"trendType"`
	TrendPrice       int    `json:"trendPrice"`
	MtLadderBoxPrice int    `json:"mtLadderBoxPrice"`
}

type VendorActMap struct {
	ActID    string `json:"actID"`
	ActType  int    `json:"actType"`
	VendorID int    `json:"vendorID"`
	ActPrice int    `json:"actPrice"`
	Origin   int    `json:"origin"` //创建来源。1表示京西创建，0表示平台创建
}

type SkuNameAndPlace struct {
	model.SkuName
	UnitPrice int                 `json:"unitPrice"`
	CityCode  int                 `json:"cityCode"`
	CityName  string              `json:"cityName"`
	Sequence  int                 `json:"sequence"`
	Count     int                 `json:"count"`
	Type      int                 `json:"type"`
	Skus      []*model.SkuAndName `json:"skus"`
}

type StoreSkuPriceAndWeight struct {
	VendorSkuID string `orm:"column(vendor_sku_id)"`
	SkuID       int    `orm:"column(sku_id)"`
	Weight      int
	Price       int
	Prefix      string
	Name        string
	Unit        string
	Comment     string
	SpecQuality float32
	SpecUnit    string
	Upc         string
}

type StoreSkuAndName struct {
	StoreSkuSyncInfo
	JdSyncStatus   int8 `orm:"default(2)"`
	MtwmSyncStatus int8 `orm:"default(2)"`
	TaoSyncStatus  int8 `orm:"default(2)"`
	EbaiSyncStatus int8 `orm:"default(2)"`
}

// todo 应该通过需要同步的skuid来驱动同步分类，而不是当前这种分开的逻辑
// 单门店模式厂商适用
// 从store_sku_bind中，得到所有依赖的商家分类信息
func GetSkusCategories(db *DaoDB, vendorID, storeID int, skuIDs []int, level int) (cats []*SkuStoreCatInfo, err error) {
	sql := `
	SELECT DISTINCT t4.*,
	t5.id map_id, t5.%s_id vendor_cat_id, t5.%s_sync_status cat_sync_status,
	t4p.name parent_cat_name,
	t5p.id parent_map_id, t5p.%s_id parent_vendor_cat_id, t5p.%s_sync_status parent_cat_sync_status
	FROM store_sku_bind t1
	JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ?
	JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ?
	`
	if level == 2 {
		sql += `
		JOIN sku_category t4 ON (t3.category_id = t4.id OR t2.category_id = t4.id) AND t4.level = 2 AND t4.deleted_at = ?
		`
	} else {
		sql += `
		LEFT JOIN sku_category t4c ON (t3.category_id = t4c.id OR t2.category_id = t4c.id)
		JOIN sku_category t4 ON (t4.id = t4c.parent_id OR (t3.category_id = t4.id OR t2.category_id = t4.id)) AND t4.level = 1 AND t4.deleted_at = ?
		`
	}
	sql += `
	LEFT JOIN store_sku_category_map t5 ON t4.id = t5.category_id AND t5.store_id = t1.store_id AND t5.deleted_at = ?
	LEFT JOIN sku_category t4p ON t4.parent_id = t4p.id
	LEFT JOIN store_sku_category_map t5p ON t4p.id = t5p.category_id AND t5p.store_id = t1.store_id AND t5p.deleted_at = ?
	WHERE t1.deleted_at = ? AND t1.%s_sync_status & ? = 0 AND t1.store_id = ? AND ((t1.status = ? AND t2.status = ? AND t3.status = ?) OR (t1.%s_sync_status & ? = 0))
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		model.SyncFlagDeletedMask,
		storeID,
		model.SkuStatusNormal,
		model.SkuStatusNormal,
		model.SkuStatusNormal,
		model.SyncFlagNewMask,
	}
	if len(skuIDs) > 0 {
		sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")"
		sqlParams = append(sqlParams, skuIDs)
	}
	fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID])
	sql = fmt.Sprintf(sql, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix)
	if err = GetRows(db, &cats, sql, sqlParams...); err != nil {
		return nil, err
	}
	return cats, err
}

// 单门店模式厂商适用
// 单纯的从已经创建的store_sku_category_map中，得到相关的同步信息
func GetStoreCategories(db *DaoDB, vendorID, storeID int, skuIDs []int, level int, mustDirty bool) (cats []*SkuStoreCatInfo, err error) {
	fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID])
	sql := `
	SELECT t4.*, ts.store_category_name store_cat_name, ts.store_category_seq store_cat_seq, ts.id store_category_id,
	t5.id map_id, t5.%s_id vendor_cat_id, t5.%s_sync_status cat_sync_status,
	t4p.name parent_cat_name,
	tsp.store_category_name store_parent_cat_name,
	t5p.id parent_map_id, t5p.%s_id parent_vendor_cat_id, t5p.%s_sync_status parent_cat_sync_status,
	t1.is_sys_cat, t1.vendor_org_code,
	t6.city_code , t6.brand_id 
	FROM store_sku_category_map t5
	JOIN sku_category t4 ON t5.category_id = t4.id 
	LEFT JOIN store_category_map ts ON ts.store_id = t5.store_id AND ts.category_id = t4.id AND ts.deleted_at = ?
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
	}
	fieldPrefixParams := []interface{}{fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix}
	if len(skuIDs) > 0 {
		sql += `
		LEFT JOIN (
			SELECT DISTINCT b.category_id 
			FROM sku a
			JOIN sku_name b ON a.name_id = b.id AND b.deleted_at = ? 
			WHERE a.id IN (` + GenQuestionMarks(len(skuIDs)) + `)
			AND a.deleted_at = ?
		) t6 ON t6.category_id = t4.id
		`
		sqlParams = append(sqlParams, utils.DefaultTimeValue, skuIDs, utils.DefaultTimeValue)
	}
	sql += `
	LEFT JOIN sku_category t4p ON t4.parent_id = t4p.id
	LEFT JOIN store_category_map tsp ON tsp.store_id = t5.store_id AND tsp.category_id = t4p.id AND tsp.deleted_at = ?
	LEFT JOIN store_sku_category_map t5p ON t4p.id = t5p.category_id AND t5.store_id = t5p.store_id
	LEFT JOIN store_map t1 ON t1.store_id = t5.store_id AND t1.vendor_id = ?
	LEFT JOIN store t6 ON t6.id = t5.store_id 
	WHERE t5.store_id = ? AND t5.deleted_at = ?  AND t4.is_sync <> ?`
	sqlParams = append(sqlParams, utils.DefaultTimeValue, vendorID, storeID, utils.DefaultTimeValue, model.YES)
	if mustDirty {
		sql += " AND t5.%s_sync_status <> 0"
		fieldPrefixParams = append(fieldPrefixParams, fieldPrefix)
	}
	if level > 0 {
		sql += " AND t4.level = ?"
		sqlParams = append(sqlParams, level)
	}
	if err = GetRows(db, &cats, fmt.Sprintf(sql, fieldPrefixParams...), sqlParams...); err != nil {
		return nil, err
	}

	// 门店分类采用京西基础分类,且门店为京西品牌之下,排除b2b菜单
	result := make([]*SkuStoreCatInfo, 0, 0)
	for _, v := range cats {
		if v.BrandId == 1 { // 京西菜市才做此判断
			if !strings.Contains(v.ParentCatName, model.B2BTag) {
				result = append(result, v)
			}
		}
	}

	return result, err
}

// 获取门店分类,区别同步方法
func GetStoreCategories2(db *DaoDB, vendorID, storeID int, skuIDs []int, level int, mustDirty bool) (cats []*SkuStoreCatInfo, err error) {
	fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID])
	sql := `
	SELECT t4.*, ts.store_category_name store_cat_name, ts.store_category_seq store_cat_seq, ts.id store_category_id,
	t5.id map_id, t5.%s_id vendor_cat_id, t5.%s_sync_status cat_sync_status,
	t4p.name parent_cat_name,
	tsp.store_category_name store_parent_cat_name,
	t5p.id parent_map_id, t5p.%s_id parent_vendor_cat_id, t5p.%s_sync_status parent_cat_sync_status,
	t1.is_sys_cat, t1.vendor_org_code,
	t6.city_code , t6.brand_id 
	FROM store_sku_category_map t5
	JOIN sku_category t4 ON t5.category_id = t4.id 
	LEFT JOIN store_category_map ts ON ts.store_id = t5.store_id AND ts.category_id = t4.id AND ts.deleted_at = ?
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
	}
	fieldPrefixParams := []interface{}{fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix}
	if len(skuIDs) > 0 {
		sql += `
		LEFT JOIN (
			SELECT DISTINCT b.category_id 
			FROM sku a
			JOIN sku_name b ON a.name_id = b.id AND b.deleted_at = ? 
			WHERE a.id IN (` + GenQuestionMarks(len(skuIDs)) + `)
			AND a.deleted_at = ?
		) t6 ON t6.category_id = t4.id
		`
		sqlParams = append(sqlParams, utils.DefaultTimeValue, skuIDs, utils.DefaultTimeValue)
	}
	sql += `
	LEFT JOIN sku_category t4p ON t4.parent_id = t4p.id
	LEFT JOIN store_category_map tsp ON tsp.store_id = t5.store_id AND tsp.category_id = t4p.id AND tsp.deleted_at = ?
	LEFT JOIN store_sku_category_map t5p ON t4p.id = t5p.category_id AND t5.store_id = t5p.store_id
	LEFT JOIN store_map t1 ON t1.store_id = t5.store_id AND t1.vendor_id = ?
	LEFT JOIN store t6 ON t6.id = t5.store_id 
	WHERE t5.store_id = ? AND t5.deleted_at = ?  AND t4.is_sync <> ?`
	sqlParams = append(sqlParams, utils.DefaultTimeValue, vendorID, storeID, utils.DefaultTimeValue, model.YES)
	if mustDirty {
		sql += " AND t5.%s_sync_status <> 0"
		fieldPrefixParams = append(fieldPrefixParams, fieldPrefix)
	}
	if level > 0 {
		sql += " AND t4.level = ?"
		sqlParams = append(sqlParams, level)
	}
	if err = GetRows(GetDB(), &cats, fmt.Sprintf(sql, fieldPrefixParams...), sqlParams...); err != nil {
		return nil, err
	}

	return cats, err
}

func GetDirtyStoreCategories(db *DaoDB, vendorID, storeID int, level int, skuIDs []int) (cats []*SkuStoreCatInfo, err error) {
	return GetStoreCategories2(db, vendorID, storeID, skuIDs, level, true)
}

// 以store_sku_bind为基础来做同步，正常情况下使用
// 单多门店模式厂商通用
func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty bool) (skus []*StoreSkuSyncInfo, err error) {
	if vendorID < 0 {
		panic("vendorID<0")
	}
	isSingleStorePF := model.MultiStoresVendorMap[vendorID] != 1
	fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID])
	skuVendorIDField := fmt.Sprintf("t1.%s_id", fieldPrefix)
	if !isSingleStorePF {
		skuVendorIDField = "t2m.vendor_thing_id"
	}
	sql := `
	SELECT
	t14.vendor_id, t14.vendor_org_code, 
	t1.id bind_id, t1.sku_id, t1.price, t1.unit_price, t1.status store_sku_status,
	%s vendor_sku_id, t1.%s_sync_status sku_sync_status, t1.%s_price vendor_price, t1.%s_lock_time lock_time,t1.vendor_son_sku_id,t1.vendor_sku_attr_id,t1.vendor_main_id,
	t1.store_id, t1.deleted_at bind_deleted_at,t1.status_sale_begin,t1.status_sale_end, t1.jds_ware_id, t1.stock, t1.mt_ladder_box_price,t1.location_code,
	t2.*,
	t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc, t3.status name_status, t3.category_id name_category_id, t3.yb_name_suffix,t3.tiktok_attribute,t3.mt_attribute,t3.ebai_attribute,t3.qua_pictures,t3.qua_effective_date,t3.qua_approval_date,t3.special_pictures,
	t3.sell_point,t3.sell_point_times,t3.jds_stock_switch, t3.preparation_time, t3.img_watermark, t3.ex_vendor_id, t3.img img_origin,t3.upc_brand_name,t3.upc_tiktok_brand_id,
	IF(t11.%s <> '', t11.%s, t3.img) img,
	IF(t12.%s <> '', t12.%s, t3.img2) img2,
	IF(t15.%s <> '', t15.%s, t3.img3) img3,
	IF(t20.%s <> '', t20.%s, t3.img4) img4,
	IF(t21.%s <> '', t21.%s, t3.img5) img5,
	IF(t13.%s <> '', t13.%s, t3.desc_img) desc_img,
	t4.%s_category_id vendor_vendor_cat_id,
	t4.name category_name,
	ts.name store_name,
	ts.brand_id,
	tsu.ex_prefix, tsu.begin_at ex_prefix_begin, tsu.end_at ex_prefix_end, tsu.img_watermark, tsu.img_watermark_mix img_mix, tsu.brand_id ex_brand_id,
	tsu1.vendor_category_id sku_vendor_map_cat_id`
	fmtParams := []interface{}{
		skuVendorIDField, fieldPrefix, fieldPrefix, fieldPrefix,
		GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
		GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
		GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
		GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
		GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
		GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
		fieldPrefix,
	}
	if isSingleStorePF {
		sql += `,
		t5.%s_sync_status cat_sync_status, t5.%s_id vendor_cat_id,
		t5sku.%s_sync_status sku_cat_sync_status, t5sku.%s_id sku_vendor_cat_id`
		fmtParams = append(fmtParams, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix)
	} else {
		sql += `,
		t4m.vendor_thing_id vendor_cat_id,
		t5skum.vendor_thing_id sku_vendor_cat_id`
	}
	if globals.IsStoreSkuAct {
		sql += `,
		act.vendor_act_id, act.act_percentage, act.sync_status act_sync_status, act.vendor_act_price`
	}
	sql += `
	FROM store_sku_bind t1
	JOIN store_map t14 ON t14.store_id = t1.store_id AND t14.vendor_id = ? AND t14.deleted_at = ?
	LEFT JOIN store ts ON ts.id = t1.store_id AND ts.deleted_at = ?
	LEFT JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ?/* AND t2.status = ?*/
	LEFT JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ?/* AND t3.status = ?*/
	LEFT JOIN sku_category t4 ON t3.category_id = t4.id AND t4.deleted_at = ?
	LEFT JOIN data_resource t11 ON t11.main_url = t3.img
	LEFT JOIN data_resource t12 ON t12.main_url = t3.img2
	LEFT JOIN data_resource t15 ON t15.main_url = t3.img3
	LEFT JOIN data_resource t20 ON t20.main_url = t3.img4
	LEFT JOIN data_resource t21 ON t21.main_url = t3.img5
	LEFT JOIN data_resource t13 ON t13.main_url = t3.desc_img
	LEFT JOIN sku_exinfo_map tsu ON tsu.name_id = t3.id AND tsu.deleted_at = ? AND tsu.vendor_id = t14.vendor_id
	LEFT JOIN sku_vendor_category_map tsu1 ON tsu1.name_id = t3.id AND tsu1.deleted_at = ? AND tsu1.vendor_id = t14.vendor_id
	`
	sqlParams := []interface{}{
		vendorID, utils.DefaultTimeValue,
		utils.DefaultTimeValue, // model.SkuStatusNormal,
		utils.DefaultTimeValue, // model.SkuStatusNormal,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
	}
	if globals.IsStoreSkuAct {
		sql += `
		LEFT JOIN store_sku_act act ON act.store_id = t1.store_id AND act.sku_id = t1.sku_id AND act.vendor_id = ?`
		sqlParams = append(sqlParams, vendorID)
	}
	if isSingleStorePF {
		sql += `
		LEFT JOIN store_sku_category_map t5 ON t4.id = t5.category_id AND t5.store_id = t1.store_id AND t5.deleted_at = ?
		LEFT JOIN store_sku_category_map t5sku ON t2.category_id = t5sku.category_id AND t5sku.store_id = t1.store_id AND t5sku.deleted_at = ?`
		sqlParams = append(sqlParams, utils.DefaultTimeValue, utils.DefaultTimeValue)
	} else {
		sql += `
		LEFT JOIN sku_category t5sku ON t5sku.id = t2.category_id
		JOIN thing_map t2m ON t2m.thing_id = t1.sku_id AND t2m.vendor_org_code = t14.vendor_org_code AND t2m.thing_type = ? AND t2m.vendor_id = ? AND t2m.deleted_at = ?
		LEFT JOIN thing_map t4m ON t4m.thing_id = t3.category_id AND t4m.vendor_org_code = t14.vendor_org_code AND t4m.thing_type = ? AND t4m.vendor_id = ? AND t4m.deleted_at = ?
		LEFT JOIN thing_map t5skum ON t5skum.thing_id = t5sku.id AND t5skum.vendor_org_code = t14.vendor_org_code AND t5skum.thing_type = ? AND t5skum.vendor_id = ? AND t5skum.deleted_at = ?
		`
		sqlParams = append(sqlParams,
			model.ThingTypeSku, vendorID, utils.DefaultTimeValue,
			model.ThingTypeCategory, vendorID, utils.DefaultTimeValue,
			model.ThingTypeCategory, vendorID, utils.DefaultTimeValue)
	}
	sql += " WHERE 1 = 1"
	if storeID > 0 {
		sql += " AND t1.store_id = ?"
		sqlParams = append(sqlParams, storeID)
	}
	if mustDirty {
		sql += " AND (t1.%s_sync_status <> 0 OR (%s <> %s AND t3.id IS NULL)"
		fmtParams = append(fmtParams, fieldPrefix, skuVendorIDField)
		if isSingleStorePF {
			fmtParams = append(fmtParams, "0")
		} else {
			fmtParams = append(fmtParams, "''")
		}
		sql += ")"
	} else {
		sql += " AND t1.deleted_at = ?"
		sqlParams = append(sqlParams, utils.DefaultTimeValue)
	}
	if len(skuIDs) > 0 {
		sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")"
		sqlParams = append(sqlParams, skuIDs)
	}
	sql = fmt.Sprintf(sql, fmtParams...)
	sql += " ORDER BY t1.price"
	if err = GetRows(db, &skus, sql, sqlParams...); err != nil {
		return nil, err
	}
	return skus, err
}

func GetStoreSkus(db *DaoDB, vendorID, storeID int, skuIDs []int) (skus []*StoreSkuSyncInfo, err error) {
	return GetStoreSkus2(db, vendorID, storeID, skuIDs, true)
}

// 以sku为基础来做全同步，
// 多门店模式厂商适用
func GetFullStoreSkus(db *DaoDB, vendorID, storeID int) (skus []*StoreSkuSyncInfo, err error) {
	// 对于多门店平台，商品库删除后，不需要操作门店商品，所以sku_name用JOIN, sku与sku_name也可以直接排除下架的
	sql := `
	SELECT
	sm.vendor_id, sm.vendor_org_code, sm.yb_app_id, sm.yb_app_key,
	t1.id bind_id, t1.price, t1.unit_price, t1.status store_sku_status,
	t1.%s_sync_status sku_sync_status, t1.%s_price vendor_price, t1.%s_lock_time lock_time,
	t1.store_id, t1.deleted_at bind_deleted_at, t1.stock,t1.location_code,
	t2.*, t2.id sku_id, t2m.vendor_thing_id vendor_sku_id,
	t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc, t3.status name_status, t3.ex_prefix, t3.ex_prefix_begin, t3.ex_prefix_end, t3.category_id name_category_id,t3.tiktok_attribute,
	t3.mt_attribute,t3.ebai_attribute,t3.qua_pictures,t3.qua_effective_date,t3.qua_approval_date,t3.special_pictures,t3.sell_point,t3.sell_point_times,t3.upc_brand_name,t3.upc_tiktok_brand_id,
	IF(t11.%s <> '', t11.%s, t3.img) img,
	IF(t12.%s <> '', t12.%s, t3.img2) img2,
	IF(t13.%s <> '', t13.%s, t3.desc_img) desc_img,
	t4.%s_category_id vendor_vendor_cat_id,
	t4m.sync_status cat_sync_status, t4m.vendor_thing_id vendor_cat_id,
	t5skum.sync_status sku_cat_sync_status, t5skum.vendor_thing_id sku_vendor_cat_id
	FROM sku t2
	JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ?/* AND t3.status = ?*/
	JOIN sku_category t4 ON t3.category_id = t4.id AND t4.deleted_at = ?
	JOIN store_map sm ON sm.vendor_id = ? AND sm.store_id = ? AND sm.deleted_at = ?
	JOIN thing_map t2m ON t2m.thing_id = t2.id 			AND t2m.vendor_org_code = sm.vendor_org_code AND t2m.thing_type = ? AND t2m.vendor_id = ? AND t2m.deleted_at = ?
	JOIN thing_map t4m ON t4m.thing_id = t3.category_id AND t4m.vendor_org_code = sm.vendor_org_code AND t4m.thing_type = ? AND t4m.vendor_id = ? AND t4m.deleted_at = ?
	LEFT JOIN store_sku_bind t1 ON sm.store_id = t1.store_id AND t1.sku_id = t2.id AND t1.deleted_at = ?
	LEFT JOIN sku_category t5sku ON t2.category_id = t5sku.id
	LEFT JOIN thing_map t5skum ON t5skum.thing_id = t2.category_id AND t5skum.vendor_org_code = sm.vendor_org_code AND t5skum.thing_type = ? AND t5skum.vendor_id = ? AND t5skum.deleted_at = ?
	LEFT JOIN data_resource t11 ON t11.main_url = t3.img
	LEFT JOIN data_resource t12 ON t12.main_url = t3.img2
	LEFT JOIN data_resource t13 ON t13.main_url = t3.desc_img
	WHERE t2.deleted_at = ?/* AND t2.status = ?*/ AND t2m.vendor_thing_id <> ''
	ORDER BY t1.price DESC`
	sqlParams := []interface{}{
		utils.DefaultTimeValue, // model.SkuStatusNormal,
		utils.DefaultTimeValue,
		vendorID, storeID, utils.DefaultTimeValue,
		model.ThingTypeSku, vendorID, utils.DefaultTimeValue,
		model.ThingTypeCategory, vendorID, utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		model.ThingTypeCategory, vendorID, utils.DefaultTimeValue,
		utils.DefaultTimeValue, // model.SkuStatusNormal,
	}
	fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID])
	sql = fmt.Sprintf(sql,
		fieldPrefix, fieldPrefix, fieldPrefix,
		GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
		GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
		GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
		fieldPrefix)
	if err = GetRows(db, &skus, sql, sqlParams...); err != nil {
		return nil, err
	}

	return skus, err
}

func GetStoreSkuPriceAndWeight(db *DaoDB, vendorStoreID string, vendorID int, vendorSkuIDs []string) (l []*StoreSkuPriceAndWeight, err error) {
	var vendorSkuIDField, sqlThingMap string
	var thingMapParams []interface{}
	if vendorID == model.VendorIDJX {
		vendorSkuIDField = "t1.id"
	} else if model.MultiStoresVendorMap[vendorID] != 0 {
		sqlThingMap = `
	JOIN thing_map t4 ON t4.thing_type = ? AND t4.thing_id = t1.id AND t4.deleted_at = ? AND t4.vendor_id = t3.vendor_id AND t4.vendor_org_code = t3.vendor_org_code`
		thingMapParams = []interface{}{
			model.ThingTypeSku, utils.DefaultTimeValue,
		}
		vendorSkuIDField = "t4.vendor_thing_id"
	} else {
		vendorSkuIDField = fmt.Sprintf("t2.%s_id", ConvertDBFieldPrefix(model.VendorNames[vendorID]))
	}
	sql := fmt.Sprintf(`
	SELECT %s vendor_sku_id, t1.id sku_id, t2.price, t1.weight, 
	t5.prefix, t5.name, t1.comment, t5.unit, t1.spec_quality, t1.spec_unit, t5.upc
	FROM sku t1
	JOIN store_sku_bind t2 ON t2.sku_id = t1.id AND t2.deleted_at = ?
	JOIN store_map t3 ON t3.store_id = t2.store_id AND t3.vendor_id = ? AND t3.vendor_store_id = ? AND t3.deleted_at = ?
	JOIN sku_name t5 ON t5.id = t1.name_id
	%s
	WHERE %s IN (`+GenQuestionMarks(len(vendorSkuIDs))+`)`, vendorSkuIDField, sqlThingMap, vendorSkuIDField)
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		vendorID, vendorStoreID, utils.DefaultTimeValue,
	}
	sqlParams = append(sqlParams, thingMapParams...)
	if vendorID == model.VendorIDJX {
		sqlParams = append(sqlParams, utils.StringSlice2Int(vendorSkuIDs))
	} else {
		sqlParams = append(sqlParams, vendorSkuIDs)
	}
	err = GetRows(db, &l, sql, sqlParams...)
	return l, err
}

// 这个函数之前是要设置没有删除或同步标志不为0的，会导致将同步标志不为0且删除了的把标志去掉，现在改为只设置没有删除的
func SetStoreSkuSyncStatus(db *DaoDB, vendorID int, storeIDs []int, skuIDs []int, syncStatus int) (num int64, err error) {
	isSingleStorePF := model.MultiStoresVendorMap[vendorID] != 1
	fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID])
	sql := `
	UPDATE store_sku_bind t1
	SET t1.%s_sync_status = t1.%s_sync_status | ?
	`
	fmtParams := []interface{}{
		fieldPrefix,
		fieldPrefix,
	}
	sqlParams := []interface{}{
		syncStatus,
	}
	if isSingleStorePF && (syncStatus&model.SyncFlagNewMask) != 0 {
		sql += `,
		t1.%s_id = 0
		`
		fmtParams = append(fmtParams, fieldPrefix)
	}
	sql += " WHERE t1.deleted_at = ? AND t1.%s_sync_status & ? = 0"
	fmtParams = append(fmtParams, fieldPrefix)
	sqlParams = append(sqlParams, utils.DefaultTimeValue, model.SyncFlagDeletedMask)
	if len(storeIDs) > 0 {
		sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	if len(skuIDs) > 0 {
		sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")"
		sqlParams = append(sqlParams, skuIDs)
	}
	sql = fmt.Sprintf(sql, fmtParams...)
	return ExecuteSQL(db, sql, sqlParams...)
}

func SetStoreCategorySyncStatus(db *DaoDB, vendorID int, storeIDs []int, catIDs []int, syncStatus int) (num int64, err error) {
	isSingleStorePF := model.MultiStoresVendorMap[vendorID] != 1
	fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID])
	sql := `
	UPDATE store_sku_category_map t1
	SET t1.%s_sync_status = IF(t1.deleted_at = ?, t1.%s_sync_status | ?, 0)
	`
	fmtParams := []interface{}{
		fieldPrefix,
		fieldPrefix,
	}
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		syncStatus,
	}
	if isSingleStorePF && (syncStatus&model.SyncFlagNewMask) != 0 {
		sql += `,
		t1.%s_id = 0
		`
		fmtParams = append(fmtParams, fieldPrefix)
	}
	sql += " WHERE (t1.deleted_at = ? OR t1.%s_sync_status <> 0)"
	fmtParams = append(fmtParams, fieldPrefix)
	sqlParams = append(sqlParams, utils.DefaultTimeValue)
	if len(storeIDs) > 0 {
		sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	if len(catIDs) > 0 {
		sql += " AND t1.category_id IN (" + GenQuestionMarks(len(catIDs)) + ")"
		sqlParams = append(sqlParams, catIDs)
	}
	sql = fmt.Sprintf(sql, fmtParams...)
	return ExecuteSQL(db, sql, sqlParams...)
}

// func GetImgFieldName(vendorID int) (fieldName string) {
// 	fieldName = imgFieldMap[vendorID]
// 	if fieldName == "" {
// 		fieldName = "img"
// 	}
// 	return fieldName
// }

func GetDataResFieldName(vendorID int) (fieldName string) {
	fieldName = dataResFieldMap[vendorID]
	if fieldName == "" {
		fieldName = "main_url"
	}
	return fieldName
}

// func GetDescImgFieldName(vendorID int) (fieldName string) {
// 	fieldName = descImgFieldMap[vendorID]
// 	if fieldName == "" {
// 		fieldName = "desc_img"
// 	}
// 	return fieldName
// }

func GetStoresSkusInfo(db *DaoDB, storeIDs, skuIDs []int) (storeSkuList []*model.StoreSkuBind, err error) {
	sql := `
	SELECT *
	FROM store_sku_bind t1
	WHERE t1.deleted_at = ?
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
	}
	if len(storeIDs) > 0 {
		sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	if len(skuIDs) > 0 {
		sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")"
		sqlParams = append(sqlParams, skuIDs)
	}
	err = GetRows(db, &storeSkuList, sql, sqlParams...)
	return storeSkuList, err
}

// vendorID, vendorStoreIDs和vendorSkuIDs都是必须参数
func GetStoresSkusInfoByVendorInfo(db *DaoDB, vendorID int, vendorStoreIDs, vendorSkuIDs []string) (storeSkuList []*StoreSkuBindWithVendorInfo, err error) {
	if len(vendorStoreIDs) == 0 || len(vendorSkuIDs) == 0 {
		return nil, nil
	}

	sql := `
	SELECT t1.*,
	%s.%s_id vendor_sku_id, t2.vendor_store_id
	FROM store_sku_bind t1
	JOIN store_map t2 ON t2.store_id = t1.store_id AND t2.vendor_id = ? AND t2.deleted_at = ?
	JOIN sku t3 ON t3.id = t1.sku_id
	WHERE t1.deleted_at = ? AND t2.vendor_store_id IN (` + GenQuestionMarks(len(vendorStoreIDs)) + `)
		AND %s.%s_id IN (` + GenQuestionMarks(len(vendorSkuIDs)) + `)`
	sqlParams := []interface{}{
		vendorID,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		vendorStoreIDs,
		vendorSkuIDs,
	}

	isSingleStorePF := model.MultiStoresVendorMap[vendorID] != 1
	tableName := "t1"
	if !isSingleStorePF {
		tableName = "t3"
	}
	fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID])
	sql = fmt.Sprintf(sql, tableName, fieldPrefix, tableName, fieldPrefix)
	err = GetRows(db, &storeSkuList, sql, sqlParams...)
	return storeSkuList, err
}

func GetMissingStoreSkuFromOrder(db *DaoDB, storeIDs []int, fromTime time.Time) (storeSkuList []*MissingStoreSkuInfo, err error) {
	if time.Now().Sub(fromTime) > 24*time.Hour*60 {
		return nil, fmt.Errorf("GetMissingStoreSkuFromOrder，时间超过60天")
	}
	sql := `
	SELECT IF(t2.jx_store_id <> 0, t2.jx_store_id, t2.store_id) store_id, t4.name_id, t1.sku_id,
	t4.spec_quality, t4.spec_unit, t5.unit,
	COUNT(*) ct, CAST(AVG(IF(t1.vendor_price <> 0, t1.vendor_price, t1.sale_price)) AS SIGNED) ref_price
	FROM order_sku t1
	JOIN goods_order t2 ON t2.vendor_order_id = t1.vendor_order_id
	LEFT JOIN store_sku_bind t3 ON t3.store_id = IF(t2.jx_store_id <> 0, t2.jx_store_id, t2.store_id) AND
		t3.sku_id = t1.sku_id AND t3.deleted_at = ?
	JOIN sku t4 ON t4.id = t1.sku_id
	JOIN sku_name t5 ON t5.id = t4.name_id
	WHERE t2.status = ? AND IF(t2.jx_store_id <> 0, t2.jx_store_id, t2.store_id) > 0 AND t1.sku_id > 0 AND t1.shop_price = 0 AND
		t1.order_created_at > ? AND t3.id IS NULL
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		model.OrderStatusFinished,
		fromTime,
	}
	if len(storeIDs) > 0 {
		sql += " AND IF(t2.jx_store_id <> 0, t2.jx_store_id, t2.store_id) IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	sql += `
	GROUP BY 1,2,3,4,5,6
	ORDER BY 1,2,3,4,5,6
	`
	err = GetRows(db, &storeSkuList, sql, sqlParams...)
	return storeSkuList, err
}

func GetAutoSaleStoreSku(db *DaoDB, storeIDs []int) (storeSkuList []*model.StoreSkuBind, err error) {
	sql := `
	SELECT *
	FROM store_sku_bind t1
	WHERE t1.deleted_at = ? AND t1.auto_sale_at <> ?`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
	}
	if len(storeIDs) > 0 {
		sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	err = GetRows(db, &storeSkuList, sql, sqlParams...)
	return storeSkuList, err
}

func GetExistingStoreSkuNameInfo(db *DaoDB, storeIDs, skuNameIDs []int) (storeSkuNameList []*StoreSkuNameInfo, err error) {
	if len(storeIDs) == 0 || len(skuNameIDs) == 0 {
		return nil, nil
	}
	sql := `
	SELECT t1.store_id, t2.name_id, MAX(t1.unit_price) unit_price
	FROM store_sku_bind t1
	JOIN sku t2 ON t2.id = t1.sku_id
	WHERE t1.deleted_at = ? AND t1.store_id IN (` + GenQuestionMarks(len(storeIDs)) + `)
	AND t2.name_id IN (` + GenQuestionMarks(len(skuNameIDs)) + `)
	GROUP BY 1, 2`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		storeIDs,
		skuNameIDs,
	}
	err = GetRows(db, &storeSkuNameList, sql, sqlParams...)
	return storeSkuNameList, err
}

func (s *StoreSkuSyncInfo) GetSeq() int {
	if s.Seq > 0 {
		return s.Seq
	}
	return int(s.VendorPrice)
}

func GetStoresSkusInfoBySaleTime(db *DaoDB, storeID int) (storeSkuBindList []*model.StoreSkuBind, err error) {
	sql := `
	SELECT t1.*
	FROM store_sku_bind t1 
	WHERE t1.status_sale_begin <> 0 AND t1.status_sale_end <> 0
	  AND t1.status = ?
	  AND t1.deleted_at = ?
	`
	sqlParams := []interface{}{
		model.SkuStatusNormal,
		utils.DefaultTimeValue,
	}
	if storeID > 0 {
		sql += ` AND t1.store_id = ?`
		sqlParams = append(sqlParams, storeID)
	}
	err = GetRows(db, &storeSkuBindList, sql, sqlParams...)
	return storeSkuBindList, err
}

func UpdateStoreSkuBindSyncStatusForSaleStatus(db *DaoDB, vendorIDs []int, storeID int) (num int64, err error) {
	sql := `
		UPDATE store_sku_bind
		   SET 
	`
	fmtParams := []interface{}{}
	sqlParams := []interface{}{}
	if len(vendorIDs) > 0 {
		for _, v := range vendorIDs {
			fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[v])
			sql += ` %s_sync_status = %s_sync_status | ?,`
			fmtParams = append(fmtParams, fieldPrefix)
			fmtParams = append(fmtParams, fieldPrefix)
			sqlParams = append(sqlParams, model.SyncFlagSaleMask)
		}
	} else {
		return 0, errors.New("取平台ID名有错误！partner.GetPurchasePlatformVendorIDs()")
	}
	sql = sql[0:strings.LastIndex(sql, ",")]
	sql = fmt.Sprintf(sql, fmtParams...)
	sql += ` WHERE status = ?
			   AND deleted_at = ?
			   AND status_sale_begin <> 0 
			   AND status_sale_end <> 0
	`
	sqlParams = append(sqlParams, model.StoreSkuBindStatusNormal, utils.DefaultTimeValue)
	if storeID > 0 {
		sql += ` AND store_id = ?`
		sqlParams = append(sqlParams, storeID)
	}
	return ExecuteSQL(db, sql, sqlParams...)
}

func UpdateStoreSkuBindSyncStatusForExPrefix(db *DaoDB, vendorIDs []int) (num int64, err error) {
	sql := `
		UPDATE store_sku_bind a
		  JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ?
	 	  JOIN sku_name c ON c.id = b.name_id AND c.deleted_at = ?
		   SET 
	`
	fmtParams := []interface{}{}
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
	}
	if len(vendorIDs) > 0 {
		for _, v := range vendorIDs {
			fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[v])
			sql += ` %s_sync_status = %s_sync_status | ?,`
			fmtParams = append(fmtParams, fieldPrefix, fieldPrefix)
			sqlParams = append(sqlParams, model.SyncFlagModifiedMask)
		}
	} else {
		return 0, errors.New("取平台ID名有错误！partner.GetPurchasePlatformVendorIDs()")
	}
	sql = sql[0:strings.LastIndex(sql, ",")]
	sql = fmt.Sprintf(sql, fmtParams...)
	sql += ` WHERE a.deleted_at = ?
			   AND c.ex_prefix != ""
			   AND (c.ex_prefix_begin = DATE_FORMAT(DATE_ADD(NOW(),INTERVAL '6' HOUR),'%Y-%m-%d 00:00:00')
			   OR c.ex_prefix_end = DATE_FORMAT(NOW(),'%Y-%m-%d 00:00:00'))
	`
	sqlParams = append(sqlParams, utils.DefaultTimeValue)
	return ExecuteSQL(db, sql, sqlParams...)
}

func UpdateSkuSyncStatusForExPrefix(db *DaoDB, vendorIDs []int) (num int64, err error) {
	sql := `
		UPDATE thing_map t1
		JOIN sku t2 ON t2.id = t1.thing_id AND t2.deleted_at = ?
		JOIN sku_name t3 ON t3.id = t2.name_id AND t3.deleted_at = ?
			AND t3.ex_prefix <> '' AND (t3.ex_prefix_begin = DATE_FORMAT(DATE_ADD(NOW(),INTERVAL '6' HOUR),'%Y-%m-%d 00:00:00')
									 OR t3.ex_prefix_end = DATE_FORMAT(NOW(),'%Y-%m-%d 00:00:00'))
		SET
			t1.sync_status = t1.sync_status | ?
		WHERE t1.deleted_at = ? AND t1.thing_type = ? AND t1.sync_status & ? <> 0
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		model.SyncFlagModifiedMask,
		utils.DefaultTimeValue, model.ThingTypeSku, model.SyncFlagDeletedMask,
	}
	if len(vendorIDs) > 0 {
		sql += " AND t1.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")"
		sqlParams = append(sqlParams, vendorIDs)
	}
	return ExecuteSQL(db, sql, sqlParams...)
}

func DeleteSkuNameExPrefixOverdue(db *DaoDB) (num int64, err error) {
	sql := `
		UPDATE sku_name 
		   SET ex_prefix_begin = null,ex_prefix_end = null
  	     WHERE deleted_at = ?
		   AND DATE_FORMAT(DATE_ADD(NOW(),INTERVAL '6' HOUR),'%Y-%m-%d 00:00:00') >= ex_prefix_end
	`
	sqlParams := []interface{}{utils.DefaultTimeValue}
	return ExecuteSQL(db, sql, sqlParams...)
}

func GetStoreSkusByNameIDs(db *DaoDB, storeIDs []int, nameID int) (skuList []*StoreSkuSyncInfo, err error) {
	sql := `
	SELECT a.*, c.unit, c.name, b.name_id, a.status store_sku_status
	FROM store_sku_bind a 
	JOIN sku b ON a.sku_id = b.id
	JOIN sku_name c ON b.name_id = c.id
	WHERE 1=1 
	AND a.deleted_at = ?
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
	}
	if nameID != 0 {
		sql += " AND b.name_id = ?"
		sqlParams = append(sqlParams, nameID)
	}
	if len(storeIDs) > 0 {
		sql += " AND a.store_id in (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	sql += ` AND a.status != ?
    ORDER BY a.updated_at DESC
  	`
	sqlParams = append(sqlParams, model.SkuStatusDeleted)
	err = GetRows(db, &skuList, sql, sqlParams...)
	return skuList, err
}

func GetTopSkusByStoreIDs(db *DaoDB, storeIDs []int) (storeSkuNameExt []*StoreSkuNameExt, err error) {
	sql := `
	SELECT t1.count, t2.id sku_id, t3.*, t1.store_id, t1.store_name
	FROM(
		SELECT SUM(b.count) count,c.id,a.store_id,d.name store_name
		FROM goods_order a
		JOIN order_sku b ON a.vendor_order_id = b.vendor_order_id AND a.vendor_id = b.vendor_id
		JOIN sku c ON b.sku_id = c.id AND c.deleted_at = ?
		JOIN sku_name t1 ON t1.id = c.name_id AND t1.deleted_at = ?
		STRAIGHT_JOIN store_sku_bind t4 ON t4.store_id = IF(a.jx_store_id = 0,a.store_id,a.jx_store_id) AND t4.sku_id = b.sku_id AND t4.status = ? AND t4.deleted_at = ?
		JOIN store d ON d.id = a.store_id
		WHERE 1=1
		AND a.order_created_at BETWEEN ? and NOW()
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		model.SkuStatusNormal,
		utils.DefaultTimeValue,
		time.Now().AddDate(0, -1, 0),
	}
	if len(storeIDs) > 0 {
		sql += " AND a.store_id IN(" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	sql += `
		AND b.sale_price > ?
		GROUP BY 2,3,4 LIMIT 0, 1000 )t1
	JOIN sku t2 ON t2.id = t1.id
	JOIN sku_name t3 ON t3.id = t2.name_id
	UNION 
	SELECT 0 count, a.sku_id, g.*, a.store_id, e.name store_name
				FROM store_sku_bind a
		   	LEFT JOIN act_store_sku b ON a.store_id = b.store_id AND b.sku_id = a.sku_id
		   	LEFT JOIN act_map c ON c.act_id = b.act_id
			LEFT JOIN act d ON d.id = c.act_id
					JOIN store e ON e.id = a.store_id
					JOIN sku f ON a.sku_id = f.id AND f.deleted_at = ?
				JOIN sku_name g ON g.id = f.name_id AND g.deleted_at = ?
			WHERE 1=1
			`
	sqlParams = append(sqlParams, salePriceLimit, utils.DefaultTimeValue, utils.DefaultTimeValue)
	if len(storeIDs) > 0 {
		sql += " AND a.store_id IN(" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	sql +=
		`
				AND NOW() BETWEEN d.begin_at AND d.end_at
				AND a.status = ?
				AND a.deleted_at = ?
				AND (d.type = ? OR d.type = ?)
	UNION
	SELECT 0 count, a.sku_id, c.*, a.store_id, d.name store_name
	FROM store_sku_bind a
	JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ? AND b.status = ?
	JOIN sku_name c ON b.name_id = c.id AND c.deleted_at = ? AND c.status = ?
	JOIN store d ON d.id = a.store_id AND d.deleted_at = ? AND d.status <> ? 
	WHERE a.store_id IN (` + GenQuestionMarks(len(storeIDs)) + `)
	AND a.deleted_at = ? AND a.status = ?
	ORDER BY 1 DESC
	LIMIT ?
	`
	sqlParams = append(sqlParams, model.StoreSkuBindStatusNormal, utils.DefaultTimeValue, model.ActSkuDirectDown, model.ActSkuSecKill,
		utils.DefaultTimeValue, model.SkuStatusNormal, utils.DefaultTimeValue, model.SkuStatusNormal, utils.DefaultTimeValue, model.StoreStatusDisabled,
		storeIDs, utils.DefaultTimeValue, model.StoreSkuBindStatusNormal, 30)
	err = GetRows(db, &storeSkuNameExt, sql, sqlParams...)
	var skuNamesInfo = &StoreSkuNamesInfo{
		SkuNames: storeSkuNameExt,
	}
	var skuIdList = make([]int, 0, 0)
	for _, v := range storeSkuNameExt {
		var skus []*StoreSkuExt
		sql2 := `
			SELECT a.id sku_id,a.*,t4.created_at bind_created_at, t4.updated_at bind_updated_at, t4.last_operator bind_last_operator, t4.deleted_at bind_deleted_at,
			t4.sub_store_id, t4.price bind_price, IF(t4.unit_price IS NOT NULL, t4.unit_price, t1.price) unit_price, t4.status store_sku_status, t4.auto_sale_at,
			t4.ebai_id, t4.mtwm_id,t4.dd_id,t4.tao_id,
			t4.ebai_sync_status, t4.mtwm_sync_status,t4.dd_sync_status,t4.tao_sync_status,
			t4.jd_price, t4.ebai_price, t4.mtwm_price, t4.jx_price, t4.tao_price, t4.stock,
			a.spec_quality sku_spec_quality, a.spec_unit sku_spec_unit 
			FROM sku a
			JOIN sku_name t1 ON a.name_id = t1.id AND t1.deleted_at = ?
			JOIN store_sku_bind t4 ON t4.sku_id = a.id AND t4.deleted_at = ?
			WHERE a.id = ?
			AND a.deleted_at = ?
		`
		sqlParams2 := []interface{}{
			utils.DefaultTimeValue,
			utils.DefaultTimeValue,
			v.SkuID,
			utils.DefaultTimeValue,
		}
		if len(storeIDs) > 0 {
			sql2 += " AND t4.store_id IN(" + GenQuestionMarks(len(storeIDs)) + ")"
			sqlParams2 = append(sqlParams2, storeIDs)
		}
		err = GetRows(db, &skus, sql2, sqlParams2...)

		if err == nil {
			v.Skus = skus
			skuIdList = append(skuIdList, v.SkuID)
		}
	}
	err = UpdateActPrice4StoreSkuNameNew(db, storeIDs, skuIdList, skuNamesInfo, model.VendorIDJX)

	return storeSkuNameExt, err
}

func GetTopSkusByCityCode(db *DaoDB, cityCode int, orderCreate time.Time) (skuNameAndPlace []*SkuNameAndPlace, err error) {
	sql := `
		SELECT SUM(b.count) count, e.name city_name, d.city_code, f.*
		FROM goods_order a 
		JOIN order_sku b ON a.vendor_order_id = b.vendor_order_id AND a.vendor_id = b.vendor_id
		JOIN sku c ON b.sku_id = c.id AND c.deleted_at = ?
		JOIN sku_name f ON f.id = c.name_id
		JOIN store d ON d.id = IF(a.jx_store_id = 0,a.store_id,a.jx_store_id) AND d.deleted_at = ? AND d.city_code = ?
		JOIN place e ON e.code = d.city_code
		WHERE 1=1
		AND b.sale_price > ?
		AND a.order_created_at BETWEEN ? and NOW()
		GROUP BY 2,3,4
		ORDER BY count DESC LIMIT 100
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		cityCode,
		salePriceLimit,
		orderCreate,
	}
	err = GetRows(db, &skuNameAndPlace, sql, sqlParams...)
	return skuNameAndPlace, err
}

func GetTopCategoriesByStoreIDs(db *DaoDB, storeIDs []int, limit int) (skuCategory []*model.SkuCategory, err error) {
	sql := `
	SELECT DISTINCT t5.* FROM(
		SELECT d.* 
		FROM (
	SELECT t3.*,t1.count
	FROM(
		SELECT SUM(b.count) count,d.category_id 
		FROM goods_order a
		JOIN order_sku b ON a.vendor_order_id = b.vendor_order_id AND a.vendor_id = b.vendor_id
		JOIN sku c ON b.sku_id = c.id AND c.deleted_at = ?
		JOIN sku_name d ON d.id = c.name_id AND d.deleted_at = ?
		JOIN store e ON e.id = IF(a.jx_store_id = 0,a.store_id,a.jx_store_id) AND e.status != -2
		JOIN (SELECT city_code FROM store WHERE 1=1
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
	}
	if len(storeIDs) > 0 {
		sql += " AND id IN(" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}

	sql += `
		)t6 ON t6.city_code = e.city_code
		WHERE 1=1
		AND a.order_created_at BETWEEN ? and NOW()
		AND b.sale_price > ?
		GROUP BY d.category_id)t1
	JOIN sku_category t3 ON t1.category_id = t3.id 
	AND t3.level = ?
	AND t3.deleted_at = ?
	ORDER BY t1.count DESC)t4
	JOIN sku_category d ON d.id = t4.parent_id
	AND d.level = ?
	Order by t4.count DESC)t5
	LIMIT ?
	`
	sqlParams = append(sqlParams, time.Now().AddDate(0, -1, 0), salePriceLimit, 2, utils.DefaultTimeValue, 1, limit)
	err = GetRows(db, &skuCategory, sql, sqlParams...)
	return skuCategory, err
}

func GetStoreSkuCategories(db *DaoDB, storeID, parentID int) (catList []*model.SkuCategory, err error) {
	sql := `
	SELECT * FROM(
	SELECT
	t1.*
	FROM sku_category t1
	JOIN
	(
		SELECT DISTINCT t3.category_id
		FROM store_sku_bind t1
		JOIN sku t2 ON t2.id = t1.sku_id AND t2.deleted_at = ? AND t2.status = ?
		JOIN sku_name t3 ON t3.id = t2.name_id AND t3.deleted_at = ? AND t3.status = ?
		WHERE t1.deleted_at = ? AND t1.status = ? AND t1.store_id = ?
	) t2 ON t2.category_id = t1.id
	WHERE t1.deleted_at  = ?`
	sqlParams := []interface{}{
		utils.DefaultTimeValue, model.SkuStatusNormal,
		utils.DefaultTimeValue, model.SkuStatusNormal,
		utils.DefaultTimeValue, model.SkuStatusNormal, storeID,
		utils.DefaultTimeValue,
	}
	if parentID >= 0 {
		sql += " AND t1.parent_id = ?"
		sqlParams = append(sqlParams, parentID)
	}
	sql += ` UNION
	SELECT
	DISTINCT
	t3.*
	FROM sku_category t1
	JOIN
	(
		SELECT DISTINCT t3.category_id
		FROM store_sku_bind t1
		JOIN sku t2 ON t2.id = t1.sku_id AND t2.deleted_at = ? AND t2.status = ?
		JOIN sku_name t3 ON t3.id = t2.name_id AND t3.deleted_at = ? AND t3.status = ?
		WHERE t1.deleted_at = ? AND t1.status = ? AND t1.store_id = ?
	) t2 ON t2.category_id = t1.id
	JOIN sku_category t3 ON t3.id = t1.parent_id AND t3.deleted_at  = ?
	WHERE t1.deleted_at  = ?
	`
	sqlParams = append(sqlParams, utils.DefaultTimeValue, model.SkuStatusNormal,
		utils.DefaultTimeValue, model.SkuStatusNormal,
		utils.DefaultTimeValue, model.SkuStatusNormal, storeID,
		utils.DefaultTimeValue, utils.DefaultTimeValue,
	)
	if parentID >= 0 {
		sql += " AND t1.parent_id = ?"
		sqlParams = append(sqlParams, parentID)
	}
	sql += `
	) a
	ORDER BY a.level, a.seq`
	err = GetRows(db, &catList, sql, sqlParams...)
	return catList, err
}

func GetStoreSkuNamePrice(db *DaoDB) (storeSkuNamePriceList []*model.StoreSkuNamePrice, err error) {
	sql := `
		SELECT * 
		  FROM store_sku_name_price
		 WHERE deleted_at = ?   
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
	}
	err = GetRows(db, &storeSkuNamePriceList, sql, sqlParams...)
	if err != nil {
		return nil, err
	}
	return storeSkuNamePriceList, err
}

func SetStoreSkuBindVendorPrice(storeSkuBind *model.StoreSkuBind, vendorID int, vendorPrice int, lockTime time.Time) {
	pLockTime := utils.Time2Pointer(lockTime)
	switch vendorID {
	case model.VendorIDJD:
		storeSkuBind.JdPrice = vendorPrice
		storeSkuBind.JdLockTime = pLockTime
	case model.VendorIDMTWM:
		storeSkuBind.MtwmPrice = vendorPrice
		storeSkuBind.MtwmLockTime = pLockTime
	case model.VendorIDEBAI:
		storeSkuBind.EbaiPrice = vendorPrice
		storeSkuBind.EbaiLockTime = pLockTime
	case model.VendorIDJX:
		storeSkuBind.JxPrice = vendorPrice
		storeSkuBind.JxLockTime = pLockTime
	case model.VendorIDDD:
		storeSkuBind.DdPrice = vendorPrice
		storeSkuBind.DdLockTime = pLockTime
	case model.VendorIDTaoVegetable:
		storeSkuBind.TaoPrice = vendorPrice
		storeSkuBind.TaoLockTime = pLockTime
	}
}

func GetStoreSkuBindVendorPrice(storeSkuBind *model.StoreSkuBind, vendorID int) (vendorPrice int) {
	switch vendorID {
	case model.VendorIDJD:
		vendorPrice = storeSkuBind.JdPrice
	case model.VendorIDMTWM:
		vendorPrice = storeSkuBind.MtwmPrice
	case model.VendorIDEBAI:
		vendorPrice = storeSkuBind.EbaiPrice
	case model.VendorIDJX:
		vendorPrice = storeSkuBind.JxPrice
	case model.VendorIDDD:
		vendorPrice = storeSkuBind.DdPrice
	case model.VendorIDTaoVegetable:
		vendorPrice = storeSkuBind.TaoPrice
	}
	return vendorPrice
}

func SetStoreSkuBindSyncStatus(storeSkuBind *model.StoreSkuBind, vendorID int, syncStatus int8) {
	switch vendorID {
	case model.VendorIDJD:
		storeSkuBind.JdSyncStatus = syncStatus
	case model.VendorIDMTWM:
		storeSkuBind.MtwmSyncStatus = syncStatus
	case model.VendorIDEBAI:
		storeSkuBind.EbaiSyncStatus = syncStatus
	case model.VendorIDTaoVegetable:
		storeSkuBind.TaoSyncStatus = syncStatus

	}
}

func GetStoreSkuBindSyncStatus(storeSkuBind *model.StoreSkuBind, vendorID int) (syncStatus int8) {
	switch vendorID {
	case model.VendorIDJD:
		syncStatus = storeSkuBind.JdSyncStatus
	case model.VendorIDMTWM:
		syncStatus = storeSkuBind.MtwmSyncStatus
	case model.VendorIDEBAI:
		syncStatus = storeSkuBind.EbaiSyncStatus
	case model.VendorIDTaoVegetable:
		syncStatus = storeSkuBind.TaoSyncStatus
	}
	return syncStatus
}

func SetStoreCatMapSyncStatus(storeCatMap *model.StoreSkuCategoryMap, vendorID int, syncStatus int8) {
	switch vendorID {
	case model.VendorIDMTWM:
		storeCatMap.MtwmSyncStatus = syncStatus
	case model.VendorIDEBAI:
		storeCatMap.EbaiSyncStatus = syncStatus
	case model.VendorIDTaoVegetable:
		storeCatMap.TaoSyncStatus = syncStatus
	}
}

// skuIDs为空，会导致性能极低，所以要skuIDs必须有值
func UpdateActPrice4StoreSkuNameNew(db *DaoDB, storeIDs, skuIDs []int, skuNamesInfo *StoreSkuNamesInfo, actVendorID int) (err error) {
	if len(storeIDs) == 0 || len(skuIDs) == 0 {
		return nil
	}

	var vendorIDs []int
	var storeMapMap map[int][]*model.StoreMap
	var storeSkuActMap map[int64]*model.StoreSkuAct
	if !globals.IsStoreSkuAct {
		if actVendorID >= 0 {
			vendorIDs = []int{actVendorID}
		}
	} else {
		storeMapList, err := GetStoresMapList(db, nil, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "")
		if err != nil {
			return err
		}
		storeMapMap = StoreMapList2Map(storeMapList)
		storeSkuActList, err2 := GetStoresSkusAct(db, 0, false, storeIDs, skuIDs, nil, false, 0, 0)
		if err = err2; err != nil {
			return err
		}
		storeSkuActMap = make(map[int64]*model.StoreSkuAct)
		for _, v := range storeSkuActList {
			storeSkuActMap[jxutils.Combine2Int(int(jxutils.Combine2Int(v.StoreID, v.SkuID)), v.VendorID)] = v
		}
	}

	actStoreSkuList, err := GetEffectiveActStoreSkuInfo(db, 0, vendorIDs, model.ActTypeAll, storeIDs, skuIDs, time.Now(), time.Now())
	if err != nil {
		return err
	}
	actStoreSkuMap4Act := jxutils.NewActStoreSkuMap(actStoreSkuList, true)
	actStoreSkuMap4EarningPrice := jxutils.NewActStoreSkuMap(actStoreSkuList, false)
	mtactList, _ := GetActMtwmVendors(db, storeIDs, skuIDs)
	mtactMap := make(map[int]map[int]*model.ActMtwmVendor)
	for _, v := range mtactList {
		if mtactMap[v.StoreID] == nil {
			mtactSkuMap := make(map[int]*model.ActMtwmVendor)
			mtactMap[v.StoreID] = mtactSkuMap
		}
		mtactMap[v.StoreID][v.SkuID] = v
	}
	ebaiactList, _ := GetActEbaiVendorSkus(db, storeIDs, skuIDs)
	ebaiactMap := make(map[int]map[int]*model.ActEbaiVendorSku)
	for _, v := range ebaiactList {
		if ebaiactMap[v.StoreID] == nil {
			ebaiactskuMap := make(map[int]*model.ActEbaiVendorSku)
			ebaiactMap[v.StoreID] = ebaiactskuMap
		}
		ebaiactMap[v.StoreID][v.SkuID] = v
	}
	for _, skuName := range skuNamesInfo.SkuNames {
		if len(skuName.Skus) > 0 {
			for _, v := range skuName.Skus {
				actVendorMap := make(map[int]*struct{})
				if actStoreSku := actStoreSkuMap4Act.GetActStoreSku(skuName.StoreID, v.SkuID, -1); actStoreSku != nil {
					v.ActPrice = int(actStoreSku.ActualActPrice)
					v.ActID = actStoreSku.ActID
					v.ActType = actStoreSku.Type
					v.EarningPrice = int(jxutils.CaculateSkuEarningPrice(int64(v.BindPrice), int64(v.ActPrice), skuName.PayPercentage))
					v.TrendType = actStoreSku.TrendType
					v.TrendPrice = actStoreSku.TrendPrice
					v.DiscountType = actStoreSku.DiscountType
					v.DiscountValue1 = actStoreSku.DiscountValue1
					v.DiscountValue2 = actStoreSku.DiscountValue2
					v.VendorActMaps = append(v.VendorActMaps, &VendorActMap{
						ActID:    utils.Int2Str(v.ActID),
						ActType:  v.ActType,
						ActPrice: v.ActPrice,
						VendorID: actStoreSku.VendorID,
						Origin:   1,
					})
					actVendorMap[actStoreSku.VendorID] = &struct{}{}
				}
				if actStoreSku := actStoreSkuMap4EarningPrice.GetActStoreSku(skuName.StoreID, v.SkuID, -1); actStoreSku != nil {
					v.EarningPrice = int(actStoreSku.EarningPrice)
					v.EarningActID = actStoreSku.ActID
				} else {
					earningPrice := int(jxutils.CaculateSkuEarningPrice(int64(v.BindPrice), int64(v.BindPrice), skuName.PayPercentage))
					if v.EarningPrice == 0 || earningPrice < v.EarningPrice {
						v.EarningPrice = earningPrice
					}
				}

				if (actVendorID == -1 || actVendorID == model.VendorIDMTWM) && v.ActPrice == 0 {
					if len(mtactMap) > 0 {
						mtact := mtactMap[skuName.StoreID][v.SkuID]
						if mtact != nil {
							v.ActPrice = int(jxutils.StandardPrice2Int(mtact.ActPrice))
							v.ActType = mtact.ActType
							v.ActID = int(utils.Str2Int64(mtact.ItemID) % 1000)
							v.EarningPrice = 0
						}
					}
				}

				if actVendorMap[model.VendorIDMTWM] == nil {
					if len(mtactMap) > 0 {
						mtact := mtactMap[skuName.StoreID][v.SkuID]
						if mtact != nil {
							v.VendorActMaps = append(v.VendorActMaps, &VendorActMap{
								ActID:    mtact.ItemID,
								ActType:  mtact.ActType,
								ActPrice: int(jxutils.StandardPrice2Int(mtact.ActPrice)),
								VendorID: model.VendorIDMTWM,
							})
						}
					}
				}

				if (actVendorID == -1 || actVendorID == model.VendorIDEBAI) && v.ActPrice == 0 {
					if len(ebaiactMap) > 0 {
						ebaiact := ebaiactMap[skuName.StoreID][v.SkuID]
						if ebaiact != nil {
							v.ActPrice = int(jxutils.StandardPrice2Int(ebaiact.ActPrice))
							v.ActType = model.ActSkuDirectDown
							v.ActID = int(utils.Str2Int64(ebaiact.ActID) % 1000)
							v.EarningPrice = 0
						}
					}
				}

				if actVendorMap[model.VendorIDEBAI] == nil {
					if len(ebaiactMap) > 0 {
						ebaiact := ebaiactMap[skuName.StoreID][v.SkuID]
						if ebaiact != nil {
							v.VendorActMaps = append(v.VendorActMaps, &VendorActMap{
								ActID:    ebaiact.ActID,
								ActType:  model.ActSkuDirectDown,
								ActPrice: int(jxutils.StandardPrice2Int(ebaiact.ActPrice)),
								VendorID: model.VendorIDEBAI,
							})
						}
					}
				}

				if globals.IsStoreSkuAct {
					v.VendorInfoMap = make(map[int]*StoreSkuVendorInfo)
					for _, storeMap := range storeMapMap[skuName.StoreID] {
						vendorID := storeMap.VendorID
						vendorInfo := &StoreSkuVendorInfo{
							VendorID: vendorID,
						}
						vendorInfo.VendorPrice = refutil.GetObjFieldByName(v, GetVendorPriceStructField(model.VendorNames[vendorID])).(int)
						lockTime, _ := refutil.GetObjFieldByName(v, GetVendorLockTimeStructField(model.VendorNames[vendorID])).(*time.Time)
						vendorInfo.LockTime = lockTime
						if vendorID != model.VendorIDJX {
							vendorInfo.VendorSkuID = refutil.GetObjFieldByName(v, GetVendorThingIDStructField(model.VendorNames[vendorID])).(string)
							vendorInfo.SyncStatus = refutil.GetObjFieldByName(v, GetSyncStatusStructField(model.VendorNames[vendorID])).(int8)
						} else {
							vendorInfo.VendorSkuID = utils.Int2Str(v.SkuID)
						}
						if storeSkuAct := storeSkuActMap[jxutils.Combine2Int(int(jxutils.Combine2Int(skuName.StoreID, v.SkuID)), vendorID)]; storeSkuAct != nil {
							vendorInfo.VendorActID = storeSkuAct.VendorActID
							vendorInfo.ActPercentage = storeSkuAct.ActPercentage
							vendorInfo.ActSyncStatus = storeSkuAct.SyncStatus
							vendorInfo.VendorActPrice = storeSkuAct.VendorActPrice
							vendorInfo.HintActID = storeSkuAct.HintActID
						}

						if actStoreSku := actStoreSkuMap4Act.GetActStoreSku(skuName.StoreID, v.SkuID, vendorID); actStoreSku != nil {
							vendorInfo.ActPrice = int(actStoreSku.ActualActPrice)
							vendorInfo.ActID = actStoreSku.ActID
							vendorInfo.ActType = actStoreSku.Type
							vendorInfo.EarningPrice = int(jxutils.CaculateSkuEarningPrice(int64(v.BindPrice), int64(v.ActPrice), skuName.PayPercentage))
						}
						if actStoreSku := actStoreSkuMap4EarningPrice.GetActStoreSku(skuName.StoreID, v.SkuID, vendorID); actStoreSku != nil {
							vendorInfo.EarningPrice = int(actStoreSku.EarningPrice)
							vendorInfo.EarningActID = actStoreSku.ActID
						} else {
							earningPrice := int(jxutils.CaculateSkuEarningPrice(int64(v.BindPrice), int64(v.BindPrice), skuName.PayPercentage))
							if v.EarningPrice == 0 || earningPrice < v.EarningPrice {
								vendorInfo.EarningPrice = earningPrice
							}
						}
						v.VendorInfoMap[vendorID] = vendorInfo
					}
				}
			}
		} else {
			skuName.UnitPrice = skuName.Price
		}
	}
	return err
}

func GetDeletedStoreSkuBind(db *DaoDB, storeID, skuID int) (storeSkuBind *model.StoreSkuBind) {
	sql := `
		SELECT a.*
		FROM store_sku_bind a
		WHERE a.store_id = ? AND a.sku_id = ?
		ORDER BY a.deleted_at DESC`
	sqlParams := []interface{}{
		storeID, skuID,
	}
	if err := GetRow(db, &storeSkuBind, sql, sqlParams...); err != nil {
		storeSkuBind = nil
	}
	return storeSkuBind
}

func GetStoreSkuBindList(db *DaoDB, storeId int) ([]*model.StoreSkuBind, error) {
	storeSkuBind := make([]*model.StoreSkuBind, 0, 0)
	sql := `SELECT * FROM store_sku_bind WHERE store_id = ? AND mtwm_id <> 0 AND deleted_at = ? `

	sqlParams := []interface{}{
		storeId,
		utils.DefaultTimeValue,
	}
	err := GetRows(db, &storeSkuBind, sql, sqlParams...)
	if err != nil {
		return nil, err
	}
	return storeSkuBind, nil
}

func GetStoreSkuBindByNameID(db *DaoDB, storeID, nameID, status int) (storeSkuBind []*model.StoreSkuBind, err error) {
	sql := `
		SELECT c.* 
		FROM sku a 
		JOIN store_sku_bind c ON c.sku_id = a.id
		WHERE c.store_id = ?
		AND a.name_id = ?
		AND c.deleted_at = ?
		AND a.deleted_at = ?
	`
	sqlParams := []interface{}{
		storeID,
		nameID,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
	}
	err = GetRows(db, &storeSkuBind, sql, sqlParams...)
	return storeSkuBind, err
}

func GetStoreSkuByVendorSkuId(storeId int, vendorID int, vendorSkuId string) (storeSkuBind *model.StoreSkuBind, err error) {
	sql := `
			SELECT * FROM store_sku_bind s WHERE s.store_id = ? 
`
	param := []interface{}{
		storeId,
	}
	switch vendorID {
	case model.VendorIDEBAI:
		sql += ` AND s.ebai_id = ?`
		param = append(param, vendorSkuId)
	}
	sql += ` AND s.deleted_at = ? `
	param = append(param, utils.DefaultTimeValue)

	err = GetRow(GetDB(), &storeSkuBind, sql, param...)
	return storeSkuBind, err
}

func GetPriceReferPrice(db *DaoDB, cityCode int, skuID int, snapDate time.Time) (result *PriceReferSnapshotExt, err error) {
	var (
		pRefer     *PriceReferSnapshotExt
		priceRefer = &PriceReferSnapshotExt{}
	)
	sql := `
		SELECT a.max_unit_price, a.min_unit_price, a.avg_unit_price, a.mid_unit_price, a.sku_id id, b.spec_quality, c.unit, b.spec_unit
		FROM price_refer_snapshot a
		JOIN sku b ON a.sku_id = b.id 
		JOIN sku_name c ON c.id = b.name_id
		WHERE 1=1
		AND a.snapshot_at = ?
		AND a.city_code = ?
	`
	sqlParams := []interface{}{
		snapDate,
		cityCode,
	}
	if skuID > 0 {
		sql += " AND a.sku_id = ?"
		sqlParams = append(sqlParams, skuID)
	}
	err = GetRow(db, &pRefer, sql, sqlParams...)
	if err != nil {
		return nil, err
	}
	if pRefer != nil {
		var (
			specQuality float64
		)
		if pRefer.Unit == model.SpecialUnit {
			if pRefer.SpecUnit == model.SpecUnitNames[1] || pRefer.SpecUnit == model.SpecUnitNames[2] {
				specQuality = float64(pRefer.SpecQuality) * 1000
			} else {
				specQuality = float64(pRefer.SpecQuality)
			}
			priceRefer.MaxPrice = int(utils.Float64TwoInt64(specQuality / utils.Int2Float64(model.SpecialSpecQuality) * utils.Int2Float64(pRefer.MaxUnitPrice)))
			priceRefer.MinPrice = int(utils.Float64TwoInt64(specQuality / utils.Int2Float64(model.SpecialSpecQuality) * utils.Int2Float64(pRefer.MinUnitPrice)))
			priceRefer.AvgPrice = int(utils.Float64TwoInt64(specQuality / utils.Int2Float64(model.SpecialSpecQuality) * utils.Int2Float64(pRefer.AvgUnitPrice)))
			priceRefer.MidPrice = int(utils.Float64TwoInt64(specQuality / utils.Int2Float64(model.SpecialSpecQuality) * utils.Int2Float64(pRefer.MidUnitPrice)))
		} else {
			priceRefer.MaxPrice = pRefer.MaxUnitPrice
			priceRefer.MinPrice = pRefer.MinUnitPrice
			priceRefer.AvgPrice = pRefer.AvgUnitPrice
			priceRefer.MidPrice = pRefer.MidUnitPrice
		}
	}
	return priceRefer, err
}

func GetStoreSkusAndSkuName(db *DaoDB, storeIDs, skuIDs, nameIDs []int) (storeSkuAndName []*StoreSkuAndName, err error) {
	sql := `
	SELECT a.id bind_id, a.store_id, a.jd_sync_status, a.mtwm_sync_status, a.ebai_sync_status, a.unit_price, a.price,
	c.id name_id, c.unit, b.*
	FROM store_sku_bind a
	JOIN sku b ON b.id = a.sku_id AND b.deleted_at = ?
	JOIN sku_name c ON c.id = b.name_id AND c.deleted_at = ?
	WHERE a.deleted_at = ?
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
		utils.DefaultTimeValue,
	}
	if len(storeIDs) > 0 {
		sql += " AND a.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	if len(skuIDs) > 0 {
		sql += " AND a.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")"
		sqlParams = append(sqlParams, skuIDs)
	}
	if len(nameIDs) > 0 {
		sql += " AND b.name_id IN (" + GenQuestionMarks(len(nameIDs)) + ")"
		sqlParams = append(sqlParams, nameIDs)
	}
	err = GetRows(db, &storeSkuAndName, sql, sqlParams...)
	return storeSkuAndName, err
}

func UpdateYbOtherSku(db *DaoDB, storeSkuSyncInfo *StoreSkuSyncInfo) (err error) {
	sql := `
		UPDATE store_sku_bind a
		JOIN sku b ON a.sku_id = b.id AND b.name_id = ?
		JOIN (SELECT * FROM store_sku_bind WHERE sku_id = ?)c ON c.store_id = a.store_id
		SET a.yb_id = c.yb_id,a.yb_sync_status = c.yb_sync_status,a.yb_price = c.yb_price
		WHERE a.store_id = ?
		AND a.yb_sync_status <> ?  
	`
	sqlParams := []interface{}{
		storeSkuSyncInfo.NameID,
		storeSkuSyncInfo.SkuID,
		storeSkuSyncInfo.StoreID,
		0,
	}
	_, err = ExecuteSQL(db, sql, sqlParams)
	return err
}

func UpdateJdsWareID(db *DaoDB, storeSkuSyncInfo *StoreSkuSyncInfo) (err error) {
	sql := `
		UPDATE store_sku_bind 
		SET jds_ware_id = ?, jds_id = ?
		WHERE store_id = ?
		AND sku_id = ? 
		AND deleted_at = ? 
	`
	sqlParams := []interface{}{
		storeSkuSyncInfo.JdsWareID,
		storeSkuSyncInfo.VendorSkuID,
		storeSkuSyncInfo.StoreID,
		storeSkuSyncInfo.SkuID,
		utils.DefaultTimeValue,
	}
	_, err = ExecuteSQL(db, sql, sqlParams)
	return err
}

type tStoreSkuAudit struct {
	model.StoreSkuAudit
	SkuName       string  `orm:"size(255)" json:"skuName"`
	StoreName     string  `json:"storeName"`
	Prefix        string  `orm:"size(255)" json:"prefix"`
	Unit          string  `orm:"size(8)" json:"unit"`
	SpecQuality   float32 `json:"-"`               // 为份必然为500，这个主要作用只是用于确保SkuName的唯一性
	SpecUnit      string  `orm:"size(8)" json:"-"` // 为份必然为克，这个主要作用只是用于确保SkuName的唯一性
	Img           string  `orm:"size(512)" json:"img"`
	Name          string  `json:"name"`
	MidUnitPrice  int     `json:"midUnitPrice"`
	CityName      string  `json:"cityName"`
	PayPercentage int     `json:"payPercentage"`
	StoreLevel    string  `json:"storeLevel"`
	OperatorName  string  `json:"operatorName"`
}

func GetStoreSkuAudit(db *DaoDB, storeIDs, nameIDs, skuIDs, statuss, types []int, name, remark, keyword, marketManPhone, cityName string, applyTimeStart, applyTimeEnd, auditTimeStart, auditTimeEnd time.Time, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
	var requestList []*tStoreSkuAudit
	sql := `
		SELECT SQL_CALC_FOUND_ROWS DISTINCT a.*, 
			c.name sku_name, c.prefix, c.unit, c.spec_quality, c.spec_unit, c.img, 
			d.name store_name, b.name, e.mid_unit_price, f.name city_name, d.pay_percentage, d.store_level, u.name operator_name
		  FROM store_sku_audit a
		  LEFT JOIN user b ON a.user_id = b.user_id
		  LEFT JOIN sku_name c ON c.id = a.name_id AND c.deleted_at = ?
		  LEFT JOIN store d ON d.id = a.store_id AND d.deleted_at = ?
		  LEFT JOIN place f ON f.code = d.city_code 
		  LEFT JOIN price_refer_snapshot e ON e.name_id = c.id AND e.city_code = ? AND e.snapshot_at = ? AND e.min_unit_price <> 0 
		  LEFT JOIN user u ON u.mobile = d.operator_phone
		 WHERE a.deleted_at = ? 
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue, utils.DefaultTimeValue,
		0, utils.Time2Date(time.Now().AddDate(0, 0, -1)),
		utils.DefaultTimeValue}
	if len(storeIDs) > 0 {
		sql += " AND a.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	if len(nameIDs) > 0 {
		sql += " AND a.name_id IN (" + GenQuestionMarks(len(nameIDs)) + ")"
		sqlParams = append(sqlParams, nameIDs)
	}
	if len(statuss) > 0 {
		sql += " AND a.status IN (" + GenQuestionMarks(len(statuss)) + ")"
		sqlParams = append(sqlParams, statuss)
	}
	if remark != "" {
		sql += " AND a.remark LIKE ? "
		sqlParams = append(sqlParams, "%"+remark+"%")
	}
	if name != "" {
		sql += " AND b.name LIKE ? "
		sqlParams = append(sqlParams, "%"+name+"%")
	}
	if applyTimeStart != utils.ZeroTimeValue && applyTimeEnd != utils.ZeroTimeValue {
		sql += " AND a.created_at BETWEEN ? AND ?"
		sqlParams = append(sqlParams, applyTimeStart, applyTimeEnd)
	}
	if auditTimeStart != utils.ZeroTimeValue && auditTimeEnd != utils.ZeroTimeValue {
		sql += " AND a.updated_at BETWEEN ? AND ?"
		sqlParams = append(sqlParams, auditTimeStart, auditTimeEnd)
	}
	if len(types) > 0 {
		sql += " AND a.type IN (" + GenQuestionMarks(len(types)) + ")"
		sqlParams = append(sqlParams, types)
	}
	if keyword != "" {
		sql += " AND (b.name LIKE ? OR a.remark LIKE ? OR a.name_id LIKE ? OR c.name LIKE ? OR d.name LIKE ? OR f.name LIKE ?)"
		sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")
	}
	if marketManPhone != "" {
		sql += " AND d.market_man_phone LIKE ? "
		sqlParams = append(sqlParams, "%"+marketManPhone+"%")
	}
	if cityName != "" {
		sql += " AND f.name LIKE ? "
		sqlParams = append(sqlParams, "%"+cityName+"%")
	}
	sql += " ORDER BY a.updated_at LIMIT ? OFFSET ?"
	pageSize = jxutils.FormalizePageSize(pageSize)
	sqlParams = append(sqlParams, pageSize, offset)
	txDB, _ := Begin(db)
	defer Commit(db, txDB)
	if err = GetRowsTx(txDB, &requestList, sql, sqlParams...); err == nil {
		result := &model.PagedInfo{
			Data: requestList,
		}
		result.TotalCount = GetLastTotalRowCount2(db, txDB)

		return result, nil
	}
	return pagedInfo, err
}

func GetStoreSkuAuditLight(db *DaoDB, storeIDs, nameIDs []int, status int) (storeSkuAudit []*model.StoreSkuAudit, err error) {
	sql := `
		SELECT a.*
		  FROM store_sku_audit a
		 WHERE a.deleted_at = ? 
	`
	sqlParams := []interface{}{utils.DefaultTimeValue}
	if len(storeIDs) > 0 {
		sql += " AND a.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	if len(nameIDs) > 0 {
		sql += " AND a.name_id IN (" + GenQuestionMarks(len(nameIDs)) + ")"
		sqlParams = append(sqlParams, nameIDs)
	}
	if status != model.StoreAuditStatusAll {
		sql += " AND a.status = ? "
		sqlParams = append(sqlParams, status)
	}
	err = GetRows(db, &storeSkuAudit, sql, sqlParams...)
	return storeSkuAudit, err
}

func GetTopSkusByNoCityCode(db *DaoDB) (skuNameAndPlace []*SkuNameAndPlace, err error) {
	var skuName1 []model.SkuName
	_, err = db.Db.QueryTable("sku_name").Filter("best_seller", "1").All(&skuName1)
	for k, _ := range skuName1 {
		skuNameAndPlace1 := &SkuNameAndPlace{
			SkuName: skuName1[k],
		}
		skuNameAndPlace = append(skuNameAndPlace, skuNameAndPlace1)
	}
	return skuNameAndPlace, err
}

func GetStoreSkuHistory(db *DaoDB, storeIDs, skuIDs []int, status int, snapShot time.Time) (storeSkuHistory []*model.StoreSkuBindHistory, err error) {
	sql := `
		SELECT a.*
		  FROM store_sku_bind_history a
		 WHERE a.deleted_at = ? 
	`
	sqlParams := []interface{}{utils.DefaultTimeValue}
	if len(storeIDs) > 0 {
		sql += " AND a.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	if len(skuIDs) > 0 {
		sql += " AND a.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")"
		sqlParams = append(sqlParams, skuIDs)
	}
	if status != model.StoreAuditStatusAll {
		sql += " AND a.status = ? "
		sqlParams = append(sqlParams, status)
	}
	if !utils.IsTimeZero(snapShot) {
		sql += " AND a.snapshot_at = ? "
		sqlParams = append(sqlParams, snapShot)
	}
	err = GetRows(db, &storeSkuHistory, sql, sqlParams...)
	return storeSkuHistory, err
}

func GetStoreSkuCategoryMap(db *DaoDB, categoryID, storeID int) (storeSkuCategoryMap *model.StoreSkuCategoryMap, err error) {
	sql := `
		SELECT *
		  FROM store_sku_category_map
		 WHERE deleted_at = ? 
	`
	sqlParams := []interface{}{utils.DefaultTimeValue}
	if categoryID != 0 {
		sql += " AND category_id = ? "
		sqlParams = append(sqlParams, categoryID)
	}
	if storeID != 0 {
		sql += " AND store_id = ? "
		sqlParams = append(sqlParams, storeID)
	}
	GetRow(db, &storeSkuCategoryMap, sql, sqlParams)
	return storeSkuCategoryMap, err
}

// GetDetailStoreSkuCategoryMap 淘宝是所有门店公用一套分类 用默认门店赋值其余门店
func GetDetailStoreSkuCategoryMap(db *DaoDB, storeId int) (storeSkuCategoryMap []*model.StoreSkuCategoryMap, err error) {
	sql := `
		SELECT *
		  FROM store_sku_category_map
		 WHERE deleted_at = ? 
	`
	sqlParams := []interface{}{utils.DefaultTimeValue}

	if storeId != 0 {
		sql += " AND store_id = ? "
		sqlParams = append(sqlParams, storeId)
	} else {
		switch beego.BConfig.RunMode {
		case model.ServerTypeFruits:
			storeId = 0
		case model.ServerTypePet:
			storeId = 0
		case model.ServerTypeVegetable:
			storeId = 668469 //  测试服芬姐(淘宝所有门店公用分类)
		default:
			storeId = 668594 //  正式服印象汇
		}
	}

	GetRows(db, &storeSkuCategoryMap, sql, sqlParams)
	return storeSkuCategoryMap, err
}

// UpdateStoreSkuCategory 修改淘宝门店的分类code以及同步装太
func UpdateStoreSkuCategory(db *DaoDB, categoryId int, storeID int, vendorCode string) {
	sql := ` UPDATE store_sku_category_map SET tao_id = ? ,tao_sync_status = ? WHERE store_id = ? AND category_id = ?`
	param := []interface{}{vendorCode, 0, storeID, categoryId}
	ExecuteSQL(db, sql, param...)
}

func GetStoreSkuListWithVendor(db *DaoDB, storeID, vendorID int, vendorOrgCode string) (skuList []*StoreSkuSyncInfo, err error) {
	sql := `
		SELECT DISTINCT b.*, c.vendor_thing_id vendor_sku_id
		  FROM store_sku_bind a
		  JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ? AND b.status = ? 
	 LEFT JOIN thing_map c ON c.thing_id = b.id AND c.thing_type = ? AND c.vendor_id = ? AND c.vendor_org_code = ? AND c.deleted_at = ? 
	     WHERE a.deleted_at = ? AND a.status = ? AND a.store_id = ?
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue, model.SkuStatusNormal,
		model.ThingTypeSku, vendorID, vendorOrgCode, utils.DefaultTimeValue,
		utils.DefaultTimeValue, model.StoreSkuBindStatusNormal, storeID,
	}
	err = GetRows(db, &skuList, sql, sqlParams)
	return skuList, err
}

type GetStoresSkusForManageStateResult struct {
	SkuID        int `orm:"column(sku_id)"`
	UnitPrice    int
	MidUnitPrice int
}

func GetStoresSkusForManageState(db *DaoDB, storeID, status int) (storeSkuList []*GetStoresSkusForManageStateResult, err error) {
	sql := `
	SELECT t1.sku_id, t1.unit_price, t2.mid_unit_price
	FROM store_sku_bind t1
	LEFT JOIN price_refer_snapshot t2 ON t1.sku_id = t2.sku_id AND t2.city_code = ? AND t2.snapshot_at = ? 
	WHERE t1.deleted_at = ?
	`
	sqlParams := []interface{}{
		0, utils.Time2Date(time.Now().AddDate(0, 0, -1)),
		utils.DefaultTimeValue,
	}
	if storeID != 0 {
		sql += " AND t1.store_id = ?"
		sqlParams = append(sqlParams, storeID)
	}
	if status != model.StoreSkuBindStatusNA {
		sql += " AND t1.status = ? "
		sqlParams = append(sqlParams, status)
	}
	err = GetRows(db, &storeSkuList, sql, sqlParams...)
	return storeSkuList, err
}

type SkuPriceAndWeight struct {
	SkuId     int64 `orm:"column(sku_id)" json:"skuId"`         // 商品本地id
	MtwmPrice int64 `orm:"column(mtwm_price)" json:"mtwmPrice"` // 美团平台价
	JdPrice   int64 `orm:"column(jd_price)" json:"jdPrice"`     // 京东平台价
	EbaiPrice int64 `orm:"column(ebai_price)" json:"ebaiPrice"` // 饿百平台价
	TaoPrice  int64 `orm:"column(tao_price)" json:"taoPrice"`   // 淘宝平台价
	DdPrice   int64 `orm:"column(dd_price)" json:"ddPrice"`     // 抖店平台价
	Weight    int64 `orm:"column(weight)" json:"weight"`        // 商品规格重量
}

// GetStoreSkuBindPriceAndWeight 获取门店绑定商品平台价格和规格
func GetStoreSkuBindPriceAndWeight(db *DaoDB, storeId int) (skuList map[string]*SkuPriceAndWeight, err error) {
	sql := `	SELECT b.sku_id,b.mtwm_price,b.jd_price,b.ebai_price,b.tao_price,b.dd_price,s.weight FROM store_sku_bind b 
				INNER JOIN sku s ON s.id = b.sku_id
				WHERE b.store_id = ?  AND b.deleted_at = ?
			`
	result := make([]*SkuPriceAndWeight, 0, 0)
	sqlParams := []interface{}{storeId, utils.DefaultTimeValue}
	if err = GetRows(db, &result, sql, sqlParams...); err != nil {
		return nil, err
	}

	if len(result) != model.NO {
		skuMap := make(map[string]*SkuPriceAndWeight, 0)
		for _, v := range result {
			skuMap[utils.Int64ToStr(v.SkuId)] = v
		}
		return skuMap, nil
	}
	return nil, errors.New("门店不存在商品数据")
}
