package rentComputer

import (
	"context"
	"errors"
	"github.com/xuri/excelize/v2"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"log-server/global"
	"log-server/model/rentComputer"
	"log-server/model/rentComputer/request"
	"log-server/model/rentComputer/response"
	"math"
	"os"
	"strconv"
	"time"
)

type ServiceRentComputer struct {
	Log ServiceRentComputerLog
}

func (s *ServiceRentComputer) RentComputerList(ctx context.Context, api rentComputer.RentComputer, info request.PageInfo, order string, desc bool) (interface{}, int64, error) {

	db := global.GVA_DB.Model(&rentComputer.RentComputer{})
	db = db.Select("rent_computer.id,rent_computer.update_time,rent_computer.create_time,rent_computer.pc_num,rent_computer.set_meal_id,rent_computer.director_name," +
		"rent_computer.pc_name,rent_computer.shop_id,rent_computer.rent_start,rent_computer.rent_duration,rent_computer.is_off_shelf,rent_computer.rent_end," +
		"rent_computer.remark,rent_computer.todesk_id,rent_computer.todesk_password,rent_computer.sunflower_id,rent_computer.sunflower_password,rent_computer.rent_price_used,rent_computer.is_expire," +
		"s.name as shop_name, r.name as set_meal_name,r.rent_price,r.price_type,r.rent_price_day")
	db = db.Joins("left join rent_computer_shop s on s.id = rent_computer.shop_id")
	db = db.Joins("left join rent_set_meal r on r.id = rent_computer.set_meal_id")

	if api.PcNum != "" {
		db = db.Where("rent_computer.pc_num = ?", api.PcNum)
	}
	if api.ShopId != 0 {
		db = db.Where("rent_computer.shop_id = ?", api.ShopId)
	}
	if api.SetMealId != 0 {
		db = db.Where("rent_computer.set_meal_id = ?", api.SetMealId)
	}
	if api.DirectorName != "" {
		if api.DirectorName != "ALL" {
			db = db.Where("rent_computer.director_name = ?", api.DirectorName)
		}
	}
	//
	//global.GVA_LOG.Info(strconv.Itoa(int(api.IsOffShelf)))
	global.GVA_LOG.Info(strconv.Itoa(int(api.IsExpire)))
	if api.IsOffShelf != -1 {
		db = db.Where("rent_computer.is_off_shelf = ?", api.IsOffShelf)
	}
	if api.IsExpire != -1 {
		if api.IsExpire == 3 {
			day7 := time.Now().AddDate(0, 0, 7).Format("2006-01-02 15:04:05")
			db = db.Where("rent_computer.rent_end <= ?", day7)
		} else {
			db = db.Where("rent_computer.is_expire = ?", api.IsExpire)
		}
	}

	var total int64
	err := db.Count(&total).Error
	if err != nil {
		return nil, 0, err
	}
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	//var statisticsLogs []*log.LogComputer
	var statisticscomputers []*response.ComputerStatisticsReply2
	db = db.Limit(limit).Offset(offset)
	if order != "" {
		var OrderStr string
		// 设置有效排序key 防止sql注入
		// 感谢 Tom4t0 提交漏洞信息
		orderMap := make(map[string]bool, 3)
		orderMap["pc_num"] = true
		//orderMap["game_id"] = true
		//orderMap["operator"] = true
		if orderMap[order] {
			if desc {
				OrderStr = order + " desc"
			} else {
				OrderStr = order
			}
		} else { // didn't matched any order key in `orderMap`
			global.GVA_LOG.Error("获取失败!", zap.Error(err))
			return statisticscomputers, total, err
		}
		err = db.Order(OrderStr).Find(&statisticscomputers).Error
	} else {
		err = db.Order("pc_num").Find(&statisticscomputers).Error
	}
	if err != nil {
		return nil, 0, err
	}
	var statisticsLogsComputer []*response.ComputerStatisticsReply2

	for _, statisticsLog := range statisticscomputers {

		statisticscomputer := new(response.ComputerStatisticsReply2)
		statisticscomputer.Id = statisticsLog.Id
		statisticscomputer.UpdateTime = statisticsLog.UpdateTime
		statisticscomputer.CreateTime = statisticsLog.CreateTime
		statisticscomputer.PcNum = statisticsLog.PcNum
		statisticscomputer.PcName = statisticsLog.PcName
		statisticscomputer.ShopId = statisticsLog.ShopId
		statisticscomputer.RentStart = statisticsLog.RentStart
		statisticscomputer.RentDuration = statisticsLog.RentDuration
		statisticscomputer.RentEnd = statisticsLog.RentEnd
		statisticscomputer.Remark = statisticsLog.Remark
		statisticscomputer.TodeskId = statisticsLog.TodeskId
		statisticscomputer.TodeskPassword = statisticsLog.TodeskPassword
		statisticscomputer.SunflowerId = statisticsLog.SunflowerId
		statisticscomputer.SunflowerPassword = statisticsLog.SunflowerPassword
		statisticscomputer.RentPrice = statisticsLog.RentPrice
		statisticscomputer.RentPriceDay = statisticsLog.RentPriceDay
		statisticscomputer.RentPriceUsed = statisticsLog.RentPriceUsed
		statisticscomputer.IsExpire = statisticsLog.IsExpire
		statisticscomputer.SetMealId = statisticsLog.SetMealId
		statisticscomputer.PriceType = statisticsLog.PriceType
		statisticscomputer.IsOffShelf = statisticsLog.IsOffShelf
		statisticscomputer.ShopName = statisticsLog.ShopName
		statisticscomputer.SetMealName = statisticsLog.SetMealName
		statisticscomputer.DirectorName = statisticsLog.DirectorName
		statisticsLogsComputer = append(statisticsLogsComputer, statisticscomputer)
	}
	return statisticsLogsComputer, total, err
}

func (s *ServiceRentComputer) GetRentComputerNum(ctx context.Context, api rentComputer.RentComputer) int64 {
	var total int64

	db := global.GVA_DB.Model(&rentComputer.RentComputer{})
	db = db.Distinct("id")
	//db = db.Where("is_off_shelf = 0 and is_expire != 1")
	if api.PcNum != "" {
		db = db.Where("rent_computer.pc_num = ?", api.PcNum)
	}
	if api.ShopId != 0 {
		db = db.Where("rent_computer.shop_id = ?", api.ShopId)
	}
	if api.SetMealId != 0 {
		db = db.Where("rent_computer.set_meal_id = ?", api.SetMealId)
	}
	if api.DirectorName != "" {
		if api.DirectorName != "ALL" {
			db = db.Where("rent_computer.director_name = ?", api.DirectorName)
		}
	}
	if api.IsExpire != -1 {
		if api.IsExpire == 3 {
			day7 := time.Now().AddDate(0, 0, 7).Format("2006-01-02 15:04:05")
			db = db.Where("rent_computer.rent_end <= ?", day7)
		} else {
			db = db.Where("rent_computer.is_expire = ?", api.IsExpire)
		}
	}
	if api.IsOffShelf != -1 {
		db = db.Where("rent_computer.is_off_shelf = ?", api.IsOffShelf)
	}
	_ = db.Count(&total).Error
	return total
}

func (s *ServiceRentComputer) AddRentComputer(requestCoding request.ComputerRequest) (err error) {
	if !errors.Is(global.GVA_DB.Where("pc_num = ? and shop_id = ?", requestCoding.PcNum, requestCoding.ShopId).First(&rentComputer.RentComputer{}).Error, gorm.ErrRecordNotFound) {
		return errors.New("租机编号已存在")
	}
	computer := new(rentComputer.RentComputer)
	//computer.Id = requestCoding.Id
	computer.PcNum = requestCoding.PcNum
	computer.PcName = requestCoding.PcName
	computer.ShopId = requestCoding.ShopId
	computer.RentStart = requestCoding.RentStart
	computer.RentDuration = requestCoding.RentDuration
	computer.RentEnd = requestCoding.RentEnd
	computer.Remark = requestCoding.Remark
	computer.TodeskId = requestCoding.TodeskId
	computer.TodeskPassword = requestCoding.TodeskPassword
	computer.SunflowerId = requestCoding.SunflowerId
	computer.SunflowerPassword = requestCoding.SunflowerPassword
	computer.RentPriceUsed = requestCoding.RentPriceUsed
	computer.IsExpire = requestCoding.IsExpire
	computer.SetMealId = requestCoding.SetMealId
	computer.IsOffShelf = requestCoding.IsOffShelf
	computer.DirectorName = requestCoding.DirectorName
	computer.CreateTime = time.Now().Format("2006-01-02 15:04:05")
	computer.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	//key := codeListCacheKey
	//_ = s.cache.DelBatheHsCache(context.Background(), key)
	return global.GVA_DB.Create(&computer).Error
}

func (s *ServiceRentComputer) GetRentComputerById(id int) (computerShop response.ComputerStatisticsReply2, err error) {
	db := global.GVA_DB.Model(&rentComputer.RentComputer{})
	var api response.ComputerStatisticsReply2
	db = db.Select("rent_computer.id,rent_computer.update_time,rent_computer.create_time,rent_computer.pc_num,rent_computer.set_meal_id,rent_computer.director_name," +
		"rent_computer.pc_name,rent_computer.shop_id,rent_computer.rent_start,rent_computer.rent_duration,rent_computer.is_off_shelf,rent_computer.rent_end," +
		"rent_computer.remark,rent_computer.todesk_id,rent_computer.todesk_password,rent_computer.sunflower_id,rent_computer.sunflower_password,rent_computer.rent_price_used,rent_computer.is_expire," +
		"s.name as shop_name, r.name as set_meal_name,r.rent_price,r.price_type,r.rent_price_day")
	db = db.Joins("left join rent_computer_shop s on s.id = rent_computer.shop_id")
	db = db.Joins("left join rent_set_meal r on r.id = rent_computer.set_meal_id")
	//db = db.Joins("left join responsible_person p on p.name = rent_computer.director_name")
	err = db.Where("rent_computer.id = ?", id).Order(id).Limit(1).Find(&api).Error
	if err != nil {
		return
	}
	computerShop.Id = api.Id
	computerShop.PcNum = api.PcNum
	computerShop.PcName = api.PcName
	computerShop.RentStart = api.RentStart
	computerShop.RentDuration = api.RentDuration
	computerShop.RentEnd = api.RentEnd
	computerShop.TodeskId = api.TodeskId
	computerShop.TodeskPassword = api.TodeskPassword
	computerShop.SunflowerId = api.SunflowerId
	computerShop.SunflowerPassword = api.SunflowerPassword
	computerShop.RentPrice = api.RentPrice
	computerShop.RentPriceDay = api.RentPriceDay
	computerShop.RentPriceUsed = api.RentPriceUsed
	computerShop.IsExpire = api.IsExpire
	computerShop.SetMealId = api.SetMealId
	computerShop.PriceType = api.PriceType
	computerShop.IsOffShelf = api.IsOffShelf
	//global.GVA_LOG.Info(strconv.Itoa(api.IsOffShelf))
	//global.GVA_LOG.Info(strconv.Itoa(computerShop.IsOffShelf))
	computerShop.ShopName = api.ShopName
	computerShop.SetMealName = api.SetMealName
	computerShop.Remark = api.Remark
	computerShop.ShopId = api.ShopId
	computerShop.DirectorName = api.DirectorName
	computerShop.UpdateTime = api.UpdateTime
	computerShop.CreateTime = api.CreateTime
	return
}

func (s *ServiceRentComputer) EditRentComputer(computer rentComputer.RentComputer) (err error) {

	err = global.GVA_DB.Save(computer).Error
	return err
}

func (s *ServiceRentComputer) DeleteRentComputerByIds(ids request.IdsReq) (err error) {
	err = global.GVA_DB.Delete(&[]rentComputer.RentComputer{}, "id in ?", ids.Ids).Error
	return err
}

func (s *ServiceRentComputer) DeleteRentComputerById(api rentComputer.RentComputer) (err error) {
	var entity rentComputer.RentComputer
	//global.GVA_LOG.Info(strconv.Itoa(int(api.Id)))
	err = global.GVA_DB.Where("id = ?", api.Id).First(&entity).Error // 根据id查询api记录
	if errors.Is(err, gorm.ErrRecordNotFound) {                      // api记录不存在
		return err
	}
	return global.GVA_DB.Delete(&entity).Error
}

// RenewRentComputer 租机续费
func (s *ServiceRentComputer) RenewRentComputer(api request.RenewRentComputerRequest) (err error) {
	var info rentComputer.RentComputer
	if errors.Is(global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("id = ?", api.PcId).First(&info).Error, gorm.ErrRecordNotFound) {
		return err
	}
	//global.GVA_LOG.Info(info.PcNum)
	remark := time.Now().Format("2006-01-02 15:04:05") + ",租机编号" + api.PcNum + "续费" + strconv.Itoa(api.Day) + "天，续费至" + api.RentRenew + ";\n"
	global.GVA_LOG.Info(remark)
	//global.GVA_LOG.Info(strconv.Itoa(api.IsExpire))
	var updateInfo rentComputer.RentComputer
	updateInfo.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	nowUnix := time.Now().Unix()
	rentRenew, _ := time.ParseInLocation("2006-01-02 15:04:05", api.RentRenew, time.Local)
	if rentRenew.Unix() < nowUnix {
		updateInfo.IsExpire = 1
	} else if rentRenew.Unix()-nowUnix <= 24*60*60 {
		updateInfo.IsExpire = 2
	} else if rentRenew.Unix()-nowUnix <= 24*60*60*7 {
		updateInfo.IsExpire = 3
	} else {
		updateInfo.IsExpire = 0
	}
	//updateInfo.Remark = info.Remark + remark
	updateInfo.Remark = remark
	updateInfo.Id = api.PcId
	updateInfo.RentDuration = info.RentDuration + api.Day
	updateInfo.RentEnd = api.RentRenew
	updateInfo.CreateTime = info.CreateTime
	updateInfo.PcNum = info.PcNum
	updateInfo.PcName = info.PcName
	updateInfo.ShopId = info.ShopId
	updateInfo.RentStart = info.RentStart
	updateInfo.TodeskId = info.TodeskId
	updateInfo.TodeskPassword = info.TodeskPassword
	updateInfo.SunflowerId = info.SunflowerId
	updateInfo.SunflowerPassword = info.SunflowerPassword
	updateInfo.RentPriceUsed = info.RentPriceUsed
	updateInfo.SetMealId = info.SetMealId
	updateInfo.IsOffShelf = info.IsOffShelf
	updateInfo.DirectorName = info.DirectorName

	err = global.GVA_DB.Save(updateInfo).Error
	if err == nil {
		//添加log
		var log rentComputer.RentComputerLog
		log.UpdateTime = updateInfo.UpdateTime
		log.CreateTime = updateInfo.UpdateTime
		log.PcNum = updateInfo.PcNum
		log.ShopId = updateInfo.ShopId
		log.SetMealId = updateInfo.SetMealId
		log.Log = remark
		err = s.Log.AddRentComputerLog(log)
		if err != nil {
			return err
		}
	}
	//err = global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("id = ?", api.PcId).Updates(updateInfo).Error
	return err
}

// RenewRentComputerByBatch 租机批量续费（仅限于续费天数一致的）
func (s *ServiceRentComputer) RenewRentComputerByBatch(api request.RenewRentComputersRequest) (err error) {
	for _, one := range api.RentMessage {
		var info rentComputer.RentComputer
		if errors.Is(global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("id = ?", one.PcId).First(&info).Error, gorm.ErrRecordNotFound) {
			return err
		}
		remark := time.Now().Format("2006-01-02 15:04:05") + ",租机编号" + one.PcNum + "续费" + strconv.Itoa(one.Day) + "天，续费至" + one.RentRenew + ";\n"
		var updateInfo rentComputer.RentComputer
		nowUnix := time.Now().Unix()
		rentRenew, _ := time.ParseInLocation("2006-01-02 15:04:05", one.RentRenew, time.Local)
		if rentRenew.Unix() < nowUnix {
			updateInfo.IsExpire = 1
		} else if rentRenew.Unix()-nowUnix <= 24*60*60 {
			updateInfo.IsExpire = 2
		} else if rentRenew.Unix()-nowUnix <= 24*60*60*7 {
			updateInfo.IsExpire = 3
		} else {
			updateInfo.IsExpire = 0
		}
		updateInfo.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
		updateInfo.Remark = remark
		updateInfo.RentDuration = info.RentDuration + one.Day
		updateInfo.RentEnd = one.RentRenew
		updateInfo.Id = info.Id
		updateInfo.CreateTime = info.CreateTime
		updateInfo.PcNum = info.PcNum
		updateInfo.PcName = info.PcName
		updateInfo.ShopId = info.ShopId
		updateInfo.RentStart = info.RentStart
		updateInfo.TodeskId = info.TodeskId
		updateInfo.TodeskPassword = info.TodeskPassword
		updateInfo.SunflowerId = info.SunflowerId
		updateInfo.SunflowerPassword = info.SunflowerPassword
		updateInfo.RentPriceUsed = info.RentPriceUsed
		updateInfo.SetMealId = info.SetMealId
		updateInfo.IsOffShelf = info.IsOffShelf
		updateInfo.DirectorName = info.DirectorName

		err = global.GVA_DB.Save(updateInfo).Error
		if err != nil {
			return err
		} else {
			//添加log
			var log rentComputer.RentComputerLog
			log.UpdateTime = updateInfo.UpdateTime
			log.CreateTime = updateInfo.UpdateTime
			log.PcNum = updateInfo.PcNum
			log.ShopId = updateInfo.ShopId
			log.SetMealId = updateInfo.SetMealId
			log.Log = remark
			err = s.Log.AddRentComputerLog(log)
			if err != nil {
				return err
			}
		}
	}
	return err
}

// RentingOutRentComputer 租机退租
func (s *ServiceRentComputer) RentingOutRentComputer(api request.RentingOutRentComputerRequest) (errMessage string, err error, okMessage string) {
	var info rentComputer.RentComputer
	if errors.Is(global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("id = ? ", api.PcId).First(&info).Error, gorm.ErrRecordNotFound) {
		return "待退租的租机编号不存在", err, ""
	}
	nowUnix := time.Now().Unix()
	now := time.Now().Format("2006-01-02 15:04:05")
	const oneDayUnix = 24 * 60 * 60
	rentEnd1, _ := time.ParseInLocation("2006-01-02 15:04:05", info.RentEnd, time.Local)
	rentEnd2, _ := time.ParseInLocation("2006-01-02 15:04:05", api.RentEnd, time.Local)
	if rentEnd1.Unix() < nowUnix {
		return "待退租的租机已到期", err, ""
	}
	surplusDay := math.Ceil(float64((rentEnd1.Unix() - rentEnd2.Unix()) / oneDayUnix))
	remark := now + ",租机编号" + info.PcNum + "于" + api.RentEnd + "执行退租,剩余" + strconv.Itoa(int(surplusDay)) + "天,"

	for i, v := range api.AddList {
		//global.GVA_LOG.Info(v.PcNum)
		//global.GVA_LOG.Info(strconv.Itoa(v.AddDay))
		var infoTemp rentComputer.RentComputer
		if errors.Is(global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("pc_num = ? and  shop_id = ?", v.PcNum, info.ShopId).First(&infoTemp).Error, gorm.ErrRecordNotFound) {
			return "增加时间的租机编号不存在", err, ""
		}
		if i < len(api.AddList) {
			remark += "编号" + v.PcNum + "加" + strconv.Itoa(v.AddDay) + "天,"
		} else {
			remark += "编号" + v.PcNum + "加" + strconv.Itoa(v.AddDay) + "天;\n"
		}

		infoTemp.UpdateTime = now
		infoTemp.RentDuration = infoTemp.RentDuration + v.AddDay
		rentEndTemp, _ := time.ParseInLocation("2006-01-02 15:04:05", infoTemp.RentEnd, time.Local)
		infoTemp.RentEnd = rentEndTemp.AddDate(0, 0, v.AddDay).Format("2006-01-02 15:04:05")
		err = global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("id = ?", infoTemp.Id).Updates(infoTemp).Error
		if err != nil {
			return "增加时间的租机信息修改失败！", err, ""
		} else {
			//添加log
			var log rentComputer.RentComputerLog
			log.UpdateTime = infoTemp.UpdateTime
			log.CreateTime = infoTemp.UpdateTime
			log.PcNum = infoTemp.PcNum
			log.ShopId = infoTemp.ShopId
			log.SetMealId = infoTemp.SetMealId
			log.Log = remark
			err = s.Log.AddRentComputerLog(log)
			if err != nil {
				return "", err, remark
			}
		}
	}
	//修改退租机器信息
	info.RentEnd = api.RentEnd
	info.RentDuration = info.RentDuration - int(surplusDay)
	info.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	//info.Remark = info.Remark + remark
	info.Remark = remark
	info.IsOffShelf = 1
	logPcNum := info.PcNum
	info.PcNum = "offShelf_" + info.PcNum + "_" + strconv.Itoa(int(time.Now().Unix()))
	err = global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("id = ?", info.Id).Updates(info).Error
	if err != nil {
		return "退租机器信息修改失败！", err, ""
	} else {
		//添加log
		var log rentComputer.RentComputerLog
		log.UpdateTime = info.UpdateTime
		log.CreateTime = info.UpdateTime
		log.PcNum = logPcNum
		log.ShopId = info.ShopId
		log.SetMealId = info.SetMealId
		log.Log = remark
		err = s.Log.AddRentComputerLog(log)
		if err != nil {
			return "", err, remark
		}
	}
	return "", err, remark
}

// OffShelfRentComputer 租机下架
func (s *ServiceRentComputer) OffShelfRentComputer(api request.ComputerRequest) (err error) {
	var info rentComputer.RentComputer
	if errors.Is(global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("id = ?", api.Id).First(&info).Error, gorm.ErrRecordNotFound) {
		return err
	}
	//global.GVA_LOG.Info(info.PcNum)
	remark := time.Now().Format("2006-01-02 15:04:05") + ",租机编号" + api.PcNum + "下架;\n"
	global.GVA_LOG.Info(remark)
	var updateInfo rentComputer.RentComputer
	updateInfo.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	updateInfo.IsOffShelf = 1
	logPcNum := api.PcNum
	updateInfo.PcNum = "offShelf_" + api.PcNum + "_" + strconv.Itoa(int(time.Now().Unix()))
	//updateInfo.Remark = info.Remark + remark
	updateInfo.Remark = remark
	err = global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("id = ?", api.Id).Updates(updateInfo).Error
	if err == nil {
		//添加log
		var log rentComputer.RentComputerLog
		log.UpdateTime = updateInfo.UpdateTime
		log.CreateTime = updateInfo.UpdateTime
		log.PcNum = logPcNum
		log.ShopId = updateInfo.ShopId
		log.SetMealId = updateInfo.SetMealId
		log.Log = remark
		err = s.Log.AddRentComputerLog(log)
		if err != nil {
			return err
		}
	}
	return err
}

// ReplaceNumRentComputer 租机换编号
func (s *ServiceRentComputer) ReplaceNumRentComputer(api request.ReplaceNumRentComputerRequest) (errMessage string, err error, okMessage string) {
	var infoOld rentComputer.RentComputer
	if errors.Is(global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("pc_num = ? and shop_id = ?", api.PcNumOld, api.ShopId).First(&infoOld).Error, gorm.ErrRecordNotFound) {
		return "待更换的租机编号不存在", err, ""
	}
	nowUnix := time.Now().Unix()
	const oneDayUnix = 24 * 60 * 60
	rentEndOld, _ := time.ParseInLocation("2006-01-02 15:04:05", infoOld.RentEnd, time.Local)
	if rentEndOld.Unix() < nowUnix {
		return "待更换的租机已到期", err, ""
	}
	var infoNew rentComputer.RentComputer
	if !errors.Is(global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("pc_num = ? and shop_id = ?", api.PcNumNew, api.ShopId).First(&infoNew).Error, gorm.ErrRecordNotFound) {
		return "要更换的租机编号已存在,不允许更换", err, ""
	}
	remark := time.Now().Format("2006-01-02 15:04:05") + ",租机编号" + api.PcNumOld + "更换为租机编号" + api.PcNumNew + ";\n"
	okMessage = remark
	rentDurationNew := math.Ceil(float64((rentEndOld.Unix() - nowUnix) / oneDayUnix))
	infoNew.PcNum = api.PcNumNew
	infoNew.PcName = api.PcNumNew
	infoNew.ShopId = api.ShopId
	infoNew.RentStart = time.Now().Format("2006-01-02 15:04:05")
	infoNew.RentDuration = int(rentDurationNew)
	infoNew.RentEnd = infoOld.RentEnd
	infoNew.Remark = remark
	infoNew.TodeskId = ""
	infoNew.TodeskPassword = ""
	infoNew.SunflowerId = ""
	infoNew.SunflowerPassword = ""
	infoNew.RentPriceUsed = 0
	infoNew.IsExpire = 0
	infoNew.SetMealId = infoOld.SetMealId
	infoNew.IsOffShelf = 0
	infoNew.CreateTime = time.Now().Format("2006-01-02 15:04:05")
	infoNew.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	infoNew.DirectorName = infoOld.DirectorName
	// 修改旧编号信息
	//if infoOld.Remark != "" {
	//	remark = infoOld.Remark + ";" + remark
	//}
	rentStartOld, _ := time.ParseInLocation("2006-01-02 15:04:05", infoOld.RentStart, time.Local)
	rentDurationOld := math.Ceil(float64((rentEndOld.Unix() - rentStartOld.Unix()) / oneDayUnix))
	infoOld.RentDuration = int(rentDurationOld)
	infoOld.RentEnd = time.Now().Format("2006-01-02 15:04:05")
	infoOld.Remark = remark
	infoOld.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	infoOld.IsOffShelf = 1
	logPcNum := infoOld.PcNum
	infoOld.PcNum = "offShelf_" + infoOld.PcNum + "_" + strconv.Itoa(int(time.Now().Unix()))
	err = global.GVA_DB.Model(&rentComputer.RentComputer{}).Where("id = ?", infoOld.Id).Updates(infoOld).Error
	if err != nil {
		return "旧编号租机修改失败！", err, ""
	} else {
		//添加log
		var log rentComputer.RentComputerLog
		log.UpdateTime = infoOld.UpdateTime
		log.CreateTime = infoOld.UpdateTime
		log.PcNum = logPcNum
		log.ShopId = infoOld.ShopId
		log.SetMealId = infoOld.SetMealId
		log.Log = remark
		err = s.Log.AddRentComputerLog(log)
		if err != nil {
			return "旧编号租机日志创建失败！", err, ""
		}
	}
	// 插入新编号至数据库
	err = global.GVA_DB.Create(&infoNew).Error
	if err != nil {
		return "新编号租机创建失败！", err, ""
	} else {
		//添加log
		var log rentComputer.RentComputerLog
		log.UpdateTime = infoNew.UpdateTime
		log.CreateTime = infoNew.UpdateTime
		log.PcNum = infoNew.PcNum
		log.ShopId = infoNew.ShopId
		log.SetMealId = infoNew.SetMealId
		log.Log = remark
		err = s.Log.AddRentComputerLog(log)
		if err != nil {
			return "新编号租机日志创建失败！", err, ""
		}
	}
	return "", err, okMessage
}

func (exa *ServiceRentComputer) ParseExcel2InfoList(filePath string) (err error) {
	skipHeader := true
	fixedHeader := []string{"租机编码", "供应商", "所属套餐", "套餐类型", "起租日", "到期日", "todesk号", "todesk密码", "向日葵号", "向日葵密码"}
	file, err := excelize.OpenFile(filePath)
	if err != nil {
		return err
	}
	var insertComputers []*rentComputer.RentComputer
	//var updateComputers []*rentComputer.RentComputer
	rows, err := file.Rows("Sheet1")
	if err != nil {
		return err
	}
	//查询数据库里的套餐与供应商=====================================
	var setMeals []*response.SetMealStatisticsReply1
	db := global.GVA_DB.Model(&rentComputer.RentSetMeal{})
	db = db.Select("rent_set_meal.id, rent_set_meal.name," +
		"rent_set_meal.price_type,rent_set_meal.shop_id,s.name as shop_name")
	db = db.Joins("left join rent_computer_shop s on s.id = rent_set_meal.shop_id")
	err = db.Order("id").Find(&setMeals).Error
	if err != nil {
		return err
	}
	// =========================================================
	index := 0
	for rows.Next() {
		index++
		row, err := rows.Columns()
		if err != nil {
			return err
		}
		if skipHeader {
			if exa.compareStrSlice(row, fixedHeader) {
				skipHeader = false
				continue
			} else {
				return errors.New("Excel格式错误")
			}
		}
		if len(row) == 0 {
			//global.GVA_LOG.Info("数组为空")
			continue
		}
		c := new(rentComputer.RentComputer)
		c.PcNum = row[0]
		c.PcName = row[0]
		flagShopId := false
		flagSetMealName := false
		for _, setMeal := range setMeals {
			if row[1] == setMeal.ShopName {
				flagShopId = true
				c.ShopId = setMeal.ShopId
				//break
			}
			priceType := 0
			if row[3] == "天卡" {
				priceType = 0
			} else if row[3] == "周卡" {
				priceType = 1
			} else {
				priceType = 2
			}
			if row[2] == setMeal.Name && priceType == setMeal.PriceType {
				flagSetMealName = true
				c.SetMealId = setMeal.Id
				break
			}
		}
		if flagShopId == false || flagSetMealName == false {
			return errors.New("供应商错误")
		}
		// 时间统一设置为日期+12:00:00
		rentStart, _ := time.ParseInLocation("2006-01-02 15:04:05", row[4]+" 12:00:00", time.Local)
		rentEnd, _ := time.ParseInLocation("2006-01-02 15:04:05", row[5]+" 12:00:00", time.Local)
		//global.GVA_LOG.Info(strconv.FormatInt(rentStart.Unix(), 10))
		//global.GVA_LOG.Info(strconv.FormatInt(rentEnd.Unix(), 10))
		c.RentStart = row[4] + " 00:00:00"
		c.RentEnd = row[5] + " 00:00:00"
		c.RentDuration = int(math.Abs(float64(SubDays(rentStart, rentEnd)))) + 1
		c.IsExpire = 0
		c.IsOffShelf = 0
		// 获取工作表中指定单元格的值
		todeskId, _ := file.GetCellValue("Sheet1", "G"+strconv.Itoa(index))
		todeskPassword, _ := file.GetCellValue("Sheet1", "H"+strconv.Itoa(index))
		sunflowerId, _ := file.GetCellValue("Sheet1", "I"+strconv.Itoa(index))
		sunflowerPassword, _ := file.GetCellValue("Sheet1", "J"+strconv.Itoa(index))
		c.TodeskId = todeskId                   //todesk账号密码
		c.TodeskPassword = todeskPassword       //todesk账号密码
		c.SunflowerId = sunflowerId             //向日葵账号密码
		c.SunflowerPassword = sunflowerPassword //向日葵账号密码

		c.CreateTime = time.Now().Format("2006-01-02 15:04:05")
		c.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
		// 租机编号已存在,存入更新数组中
		if !errors.Is(global.GVA_DB.Where("pc_num = ? and shop_id = ?", c.PcNum, c.ShopId).First(&rentComputer.RentComputer{}).Error, gorm.ErrRecordNotFound) {
			// 租机编号已存在,存入更新数组中
			//updateComputers = append(updateComputers, c)
			continue
		} else {
			insertComputers = append(insertComputers, c)
		}

	}
	defer func() {
		global.GVA_LOG.Info("defer 删除文件")
		err = os.RemoveAll(filePath)
		if err != nil {
			return
		}
	}()

	//if updateComputers != nil {
	//	err = global.GVA_DB.Updates(updateComputers).Error
	//	if err != nil {
	//		return
	//	}
	//}
	if insertComputers != nil {
		err = global.GVA_DB.Create(insertComputers).Error
		if err != nil {
			return
		}
	}

	//var cp log.Computer
	//err = cp.DelAllOnlinePcCodeCache()
	return
}

func (exa *ServiceRentComputer) compareStrSlice(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	if (b == nil) != (a == nil) {
		return false
	}
	for key, value := range a {
		if value != b[key] {
			return false
		}
	}
	return true
}

// CheckIsExpire 定时检查是否有电脑到期，修改租机状态
func (s *ServiceRentComputer) CheckIsExpire() {
	global.GVA_LOG.Info("检查是否有电脑到期开始执行:" + time.Now().Format("2006-01-02 15:04:05"))
	db := global.GVA_DB.Model(&rentComputer.RentComputer{})
	//SELECT pc_num,rent_start,rent_end,is_expire FROM shuyou_rent_computer
	//db = db.Where("is_off_shelf = 0")
	var computers []*rentComputer.RentComputer
	err := db.Order("id").Find(&computers).Error
	if err != nil {
		global.GVA_LOG.Error("检查是否有电脑到期执行失败:" + time.Now().Format("2006-01-02 15:04:05"))
		return
	}
	const overtime = 24 * 60 * 60
	const overtime7 = 24 * 60 * 60 * 7
	nowUnix := time.Now().Unix()

	//global.GVA_LOG.Info(strconv.FormatInt(nowUnix, 10))
	//global.GVA_LOG.Info("---------------------------------------------------------------------------------")
	computer := new(rentComputer.RentComputer)
	for _, c := range computers {
		endUnix, _ := time.ParseInLocation("2006-01-02 15:04:05", c.RentEnd, time.Local)
		//global.GVA_LOG.Info(strconv.FormatInt(endUnix.Unix(), 10))

		if endUnix.Unix() < nowUnix {
			computer.IsExpire = 1
		} else if endUnix.Unix()-nowUnix <= overtime {
			computer.IsExpire = 2
		} else if endUnix.Unix()-nowUnix <= overtime7 {
			computer.IsExpire = 3
		} else {
			computer.IsExpire = 0
		}

		if c.IsExpire == computer.IsExpire {
			continue
		}
		computer.Id = c.Id
		computer.UpdateTime = c.UpdateTime
		computer.CreateTime = c.CreateTime
		computer.PcNum = c.PcNum
		computer.PcName = c.PcName
		computer.ShopId = c.ShopId
		computer.RentStart = c.RentStart
		computer.RentDuration = c.RentDuration
		computer.RentEnd = c.RentEnd
		computer.Remark = c.Remark
		computer.TodeskId = c.TodeskId
		computer.TodeskPassword = c.TodeskPassword
		computer.SunflowerId = c.SunflowerId
		computer.SunflowerPassword = c.SunflowerPassword
		computer.RentPriceUsed = c.RentPriceUsed
		computer.SetMealId = c.SetMealId
		computer.IsOffShelf = c.IsOffShelf
		computer.DirectorName = c.DirectorName
		//if c.PcNum == "S11" {
		//	global.GVA_LOG.Info(strconv.FormatInt(nowUnix, 10))
		//	global.GVA_LOG.Info(strconv.FormatInt(endUnix.Unix(), 10))
		//	global.GVA_LOG.Info(strconv.FormatInt(overtime7, 10))
		//	global.GVA_LOG.Info(strconv.Itoa(computer.IsExpire))
		//}
		err = global.GVA_DB.Save(computer).Error
	}
	global.GVA_LOG.Info("检查是否有电脑到期执行成功:" + time.Now().Format("2006-01-02 15:04:05"))
	return
}

// CreateRentComputerLedger 定时生成今日租机台账表（财务）
func (s *ServiceRentComputer) CreateRentComputerLedger() {
	global.GVA_LOG.Info("定时生成今日租机台账表开始执行:" + time.Now().Format("2006-01-02 15:04:05"))
	//查询当前所有在租电脑
	db := global.GVA_DB.Model(&rentComputer.RentComputer{})
	var computers []*rentComputer.RentComputerSetMeal
	db = db.Select("rent_computer.pc_num, rent_computer.pc_name,rent_computer.shop_id, rent_computer.rent_start, rent_computer.rent_duration, rent_computer.rent_end, rent_computer.is_expire, " +
		"r.rent_price,r.rent_price_day,rent_computer.set_meal_id,rent_computer.remark")
	db = db.Joins("left join rent_set_meal r on r.id = rent_computer.set_meal_id")
	db = db.Where("rent_computer.is_expire != 1")
	err := db.Order("rent_computer.id").Find(&computers).Error
	if err != nil {
		global.GVA_LOG.Error("定时生成今日租机台账表执行失败:"+time.Now().Format("2006-01-02 15:04:05"), zap.Error(err))
		return
	}
	//查询昨日租机台账表中的rent_price_used_then参数
	var computersYest []*rentComputer.RentComputerLedger
	dbYest := global.GVA_DB.Model(&rentComputer.RentComputerLedger{})
	dbYest = dbYest.Select("rent_price_used_then").Order("id")
	err = dbYest.Find(&computersYest).Error
	if err != nil {
		global.GVA_LOG.Error("定时生成今日租机台账表执行失败,查询昨日数据失败:"+time.Now().Format("2006-01-02 15:04:05"), zap.Error(err))
		return
	}
	nowTime := time.Now().Format("2006-01-02 15:04:05")
	nowDate := time.Now().Format("2006-01-02")
	var insertInfos []rentComputer.RentComputerLedger
	for _, computer := range computers {
		var info rentComputer.RentComputerLedger
		info.UpdateTime = nowTime
		info.CreateTime = nowTime
		info.NewDate = nowDate
		info.PcNum = computer.PcNum
		info.PcName = computer.PcName
		info.ShopId = computer.ShopId
		info.RentStartThen = computer.RentStart
		info.RentDurationThen = computer.RentDuration
		info.RentEndThen = computer.RentEnd
		info.RentPriceThen = computer.RentPrice
		info.RentPriceDayThen = computer.RentPriceDay
		info.IsExpire = computer.IsExpire
		info.SetMealId = computer.SetMealId
		info.Remark = computer.Remark

		flag := false
		for _, yest := range computersYest {
			if info.PcNum == yest.PcNum {
				flag = true
				info.RentPriceUsedThen = yest.RentPriceUsedThen + computer.RentPriceDay
				break
			}
		}
		if flag == false {
			info.RentPriceUsedThen = computer.RentPriceDay
		}
		if !errors.Is(global.GVA_DB.Where("pc_num = ? and shop_id = ? and new_date = ?", computer.PcNum, computer.ShopId, nowDate).First(&rentComputer.RentComputerLedger{}).Error, gorm.ErrRecordNotFound) {
			// 已存在,更新
			err = global.GVA_DB.Model(&rentComputer.RentComputerLedger{}).Where("pc_num = ? and shop_id = ? and new_date = ?", computer.PcNum, computer.ShopId, nowDate).Updates(info).Error
			if err != nil {
				global.GVA_LOG.Error("定时生成今日租机台账表执行失败,更新数据失败:"+time.Now().Format("2006-01-02 15:04:05"), zap.Error(err))
				return
			}
		} else {
			insertInfos = append(insertInfos, info)
		}

	}
	if insertInfos != nil {
		err = global.GVA_DB.Create(&insertInfos).Error
		if err != nil {
			global.GVA_LOG.Error("定时生成今日租机台账表执行失败,插入数据失败:"+time.Now().Format("2006-01-02 15:04:05"), zap.Error(err))
			return
		}
	}
	global.GVA_LOG.Info("定时生成今日租机台账表执行成功:" + time.Now().Format("2006-01-02 15:04:05"))
	return
}

// SubDays 计算日期相差多少天
// 返回值day>0, t1晚于t2; day<0, t1早于t2
func SubDays(t1, t2 time.Time) (day int) {
	swap := false
	if t1.Unix() < t2.Unix() {
		t_ := t1
		t1 = t2
		t2 = t_
		swap = true
	}
	//global.GVA_LOG.Info(strconv.Itoa(int(t1.Unix())))
	//global.GVA_LOG.Info(strconv.Itoa(int(t2.Unix())))
	day = int(t1.Sub(t2).Hours() / 24)
	// 计算在被24整除外的时间是否存在跨自然日
	if int(t1.Sub(t2).Milliseconds())%86400000 > int(86400000-t2.Unix()%86400000) {
		day += 1
	}
	if swap {
		day = -day
	}
	//global.GVA_LOG.Info(strconv.Itoa(day))
	return
}
