package models

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
	orm "go-admin/common/global"
	"go-admin/logger"
	"go-admin/tools"
	"go-admin/tools/config"
	"time"
)

// gen:qs
//
//go:generate goqueryset -in recycle_card.go
type RecycleCardOrder struct {
	Model

	Uid                   uint32    `json:"uid" gorm:"index"`
	GoodsId               uint32    `json:"goods_id" gorm:"index"`
	GoodsName             string    `json:"goods_name"`
	GoodsImg              string    `json:"goods_img"`
	Keyword               string    `json:"keyword"`
	Price                 uint32    `json:"price"`
	State                 uint32    `json:"state"` // 1-待回收 2-已完成 3-已被拒 4-已取消
	StoreId               uint32    `json:"store_id" gorm:"index"`
	StoreName             string    `json:"store_name"`
	Images                string    `json:"images" gorm:"type:text"` // 图片
	SerialNumber          string    `json:"serial_number"`
	EvaluationTime        time.Time `json:"evaluation_time"`
	Attribute             string    `json:"attribute" gorm:"type:text"` //
	Number                string    `json:"number"`                     // 订单
	CheckTime             time.Time `json:"check_time"`
	DepressionRate        uint32    `json:"depression_rate"` //
	UserInfo              *UserInfo `json:"user_info" gorm:"-"`
	Store                 *Store    `json:"store" gorm:"-"`
	Describe              string    `json:"describe"`                             // 描述
	Remark                string    `json:"remark"`                               // 备注
	AssistantName         string    `json:"assistant_name"`                       // 店员
	RetrieveTime          time.Time `json:"retrieve_time"`                        // 审核时
	RetrieveState         uint32    `json:"retrieve_state"`                       // 回收卡状态: 0-未完成 1-未确认 2-确认
	OriginalPrice         uint32    `json:"original_price"`                       // 原价
	CooperativeBusinessId uint32    `json:"cooperative_business_id" gorm:"index"` // 合作商id
	CooperativeName       string    `json:"cooperative_name"`                     // 合作商名称
	// recycle_card_order
}

type RecycleAttribute struct {
	Id        uint32 `json:"id"`
	Name      string `json:"name"`
	ValueId   uint32 `json:"value_id"`
	ValueName string `json:"value_name"`
	Type      uint32 `json:"type"` // 1-sku 2-问题
}

type RecycleCardOrderListReq struct {
	PageIdx               int    `json:"pageIndex"`
	PageSize              int    `json:"pageSize"`
	Uid                   uint32 `json:"uid"`
	StoreId               uint32 `json:"store_id"`
	Number                string `json:"number"`
	State                 uint32 `json:"state"`
	IsExport              uint32 `json:"is_export"`      // 1-导出
	RetrieveState         uint32 `json:"retrieve_state"` // 回收卡状态: 0-未完成 1-未确认 2-确认
	CooperativeBusinessId uint32 `json:"cooperative_business_id"`
	StartTime             string `json:"start_time"`
	EndTime               string `json:"end_time"`
	AuditStartTime        string `json:"audit_start_time"`
	AuditEndTime          string `json:"audit_end_time"`
}
type RecycleCardOrderListRsp struct {
	Total     int64              `json:"total"`
	List      []RecycleCardOrder `json:"list"`
	PageIndex int                `json:"pageIndex"`
	PageSize  int                `json:"pageSize"`
	Url       string             `json:"url"`
}

func (m *RecycleCardOrderListReq) List(c *gin.Context) (RecycleCardOrderListRsp, error) {
	rsp := RecycleCardOrderListRsp{
		PageIndex: m.PageIdx,
		PageSize:  m.PageSize,
	}
	page := m.PageIdx - 1
	if page < 0 {
		page = 0
	}
	if m.PageSize == 0 {
		m.PageSize = 10
	}
	fmt.Println("m.CooperativeBusinessId", m.CooperativeBusinessId)

	var list []RecycleCardOrder
	qs := orm.Eloquent.Table("recycle_card_order")

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

		// 返回sysUser未过期的门店id列表
		storeList := GetValidStoreIDs(sysUser.StoreData)
		if m.StoreId != 0 {
			if !Contains(storeList, m.StoreId) {
				return RecycleCardOrderListRsp{}, 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 RecycleCardOrderListRsp{}, errors.New("用户未绑定门店")
			}
		}
	} else {
		if m.CooperativeBusinessId != 0 {
			var stores []Store
			err := orm.Eloquent.Table("store").Where("cooperative_business_id=?", m.CooperativeBusinessId).
				Find(&stores).Error
			if err != nil {
				logger.Error("stores err:", logger.Field("err", err))
				return rsp, err
			}
			storeIds := make([]uint32, 0, len(stores))
			for i, _ := range stores {
				storeIds = append(storeIds, stores[i].ID)
			}
			if len(storeIds) > 0 && m.StoreId == 0 {
				qs = qs.Where("store_id IN (?)", storeIds)
			}
		}
	}

	if m.Uid != 0 {
		qs = qs.Where("uid=?", m.Uid)
	}
	if m.StoreId != 0 {
		qs = qs.Where("store_id=?", m.StoreId)
	}
	if m.Number != "" {
		qs = qs.Where("number=?", m.Number)
	}
	if m.State != 0 {
		qs = qs.Where("state=?", m.State)
	}
	if m.RetrieveState != 0 {
		qs = qs.Where("retrieve_state=?", m.RetrieveState)
	}
	if m.StartTime != "" {
		parse, err := time.Parse(DateTimeFormat, m.StartTime)
		if err != nil {
			logger.Errorf("err:", logger.Field("err", err))
			return rsp, err
		}
		qs = qs.Where("created_at > ?", parse)
	}
	if m.EndTime != "" {
		parse, err := time.Parse(DateTimeFormat, m.EndTime)
		if err != nil {
			logger.Errorf("err:", logger.Field("err", err))
			return rsp, err
		}
		parse = parse.AddDate(0, 0, 1)
		qs = qs.Where("created_at < ?", parse)
	}
	if m.AuditStartTime != "" {
		parse, err := time.Parse(DateTimeFormat, m.AuditStartTime)
		if err != nil {
			logger.Errorf("err:", logger.Field("err", err))
			return rsp, err
		}
		qs = qs.Where("check_time > ?", parse)
	}
	if m.AuditEndTime != "" {
		parse, err := time.Parse(DateTimeFormat, m.AuditEndTime)
		if err != nil {
			logger.Errorf("err:", logger.Field("err", err))
			return rsp, err
		}
		parse = parse.AddDate(0, 0, 1)
		qs = qs.Where("check_time < ?", parse)
	}

	//qs := NewRecycleCardOrderQuerySet(DB).UidEq(m.Uid)
	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Error("err:", logger.Field("err", err))
		return rsp, err
	}
	rsp.Total = count
	//err = qs.Order("id DESC").Offset(m.PageNum * m.PageSize).Limit(m.PageSize).Find(&dailys).Error
	if m.IsExport == 1 {
		err = qs.Order("id DESC").Find(&list).Error
		if err != nil && err != RecordNotFound {
			logger.Error("dailys err:", logger.Field("err", err))
			return rsp, err
		}
		RecycleCardOrderListSetStore(list)
		listExport, err := RecycleCardOrderListExport(list)
		if err != nil {
			logger.Error("list export err:", logger.Field("err", err))
		}
		rsp.Url = listExport
	} else {
		err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&list).Error
		//err = qs.OrderDescByID().Offset(page * m.PageSize).Limit(m.PageSize).All(&list)
		if err != nil {
			logger.Error("err:", logger.Field("err", err))
			return rsp, err
		}
		RecycleCardOrderListSetStore(list)
		rsp.List = list
	}

	return rsp, nil
}

func RecycleCardOrderListExport(list []RecycleCardOrder) (string, error) {
	file := excelize.NewFile()
	streamWriter, err := file.NewStreamWriter("Sheet1")
	if err != nil {
		fmt.Println(err)
	}

	//url := "http://39.108.188.218:8000/img/export/"
	fileName := time.Now().Format(TimeFormat) + "回收卡订单" + ".xlsx"

	title := []interface{}{"门店", "用户ID", "订单编号", "下单时间", "卡带", "说明", "回收价", "闲麦价", "审核时间", "审核人", "操作", "复核时间", "复核状态"}
	cell, _ := excelize.CoordinatesToCellName(1, 1)
	if err = streamWriter.SetRow(cell, title); err != nil {
		fmt.Println(err)
	}
	var row []interface{}
	for rowId := 0; rowId < len(list); rowId++ {
		var attributes []RecycleAttribute
		err = json.Unmarshal([]byte(list[rowId].Attribute), &attributes)
		if err != nil {
			logger.Error("attributes err:", logger.Field("err", err))
			return "", err
		}
		desc := ""
		for i, _ := range attributes {
			desc += attributes[i].Name + ":" + attributes[i].ValueName + "    "
		}
		storeName := ""
		if list[rowId].Store != nil {
			storeName = list[rowId].Store.Name
		}
		row = []interface{}{storeName, list[rowId].Uid, list[rowId].Number,
			list[rowId].CreatedAt.Format(TimeFormat), list[rowId].GoodsName, desc,
			list[rowId].Price / 100, list[rowId].OriginalPrice / 100, list[rowId].CheckTime.Format(TimeFormat),
			list[rowId].AssistantName, list[rowId].StateToString(), list[rowId].RetrieveTime.Format(TimeFormat),
			list[rowId].RetrieveStateToString()}
		cell, _ := excelize.CoordinatesToCellName(1, rowId+2)
		if err := streamWriter.SetRow(cell, row); err != nil {
			fmt.Println(err)
		}
	}
	if err := streamWriter.Flush(); err != nil {
		fmt.Println(err)
	}
	if err := file.SaveAs("/www/server/images/export/" + fileName); err != nil {
		//if err := file.SaveAs("./" + fileName); err != nil {
		fmt.Println(err)
	}
	return config.ExportConfig.Url + fileName, nil
}

func RecycleCardOrderStateUpdate() {
	fmt.Println("开始取消超时订单")
	err := orm.Eloquent.Table("recycle_card_order").Where("state=1").
		Where("created_at<?", time.Now().AddDate(0, 0, -1)).
		Update("state", 4).Error
	//err := orm.Eloquent.Table("recycle_card_order").Where("state=1").
	//	Where("created_at<?", time.Now().Add(time.Minute*(-5))).
	//	Update("state", 4).Error
	if err != nil {
		logger.Error("update recycle card order state err:", logger.Field("err", err))
	}
	fmt.Println("取消超时订单完成...")
}

func RecycleCardOrderListSetStore(orders []RecycleCardOrder) {
	ids := make([]uint32, 0, len(orders))
	for i, _ := range orders {
		ids = append(ids, orders[i].StoreId)
	}

	storeMap := GetStoreMapByIds(ids)

	for i, _ := range orders {
		v, ok := storeMap[uint64(orders[i].StoreId)]
		if ok {
			orders[i].Store = v
		}
	}
}

func (m *RecycleCardOrder) StateToString() string {
	switch m.State {
	case 1:
		return "待回收"
	case 2:
		return "已完成"
	case 3:
		return "已被拒"
	case 4:
		return "已取消"
	}
	return ""
}

func (m *RecycleCardOrder) RetrieveStateToString() string {
	switch m.RetrieveState {
	case 0:
		return "未完成"
	case 1:
		return "未确认"
	case 2:
		return "已确认"
	}
	return "未知"
}
