package models

import (
	"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"
	"gorm.io/gorm"
	"math/rand"
	"time"
)

const (
	ErpRepairOrderUnAudit      = 1 // 待审核
	ErpRepairOrderWaitRepair   = 2 // 待送修
	ErpRepairOrderBingRepaired = 3 // 维修中
	ErpRepairOrderFinished     = 4 // 已完成
)

type RepairRecord struct {
	Model

	SerialNumber   string                  `json:"serial_number"`             // 订单编号
	Uid            uint32                  `json:"uid"`                       // 用户ID
	Tel            string                  `json:"tel"`                       // 手机号
	MemberLevel    uint32                  `json:"member_level"`              // 会员等级：1-普通用户，6-尊享会员
	StoreId        uint32                  `json:"store_id"`                  // 门店ID
	StoreName      string                  `json:"store_name" gorm:"-"`       // 门店名称
	HandlerId      uint32                  `json:"handler_id"`                // 经手人ID
	HandlerName    string                  `json:"handler_name"`              // 经手人名称
	State          uint8                   `json:"state"`                     // 状态（1-待审核，2-待送修，3-维修中，4-已完成）
	MakerId        uint32                  `json:"maker_id"`                  // 制单人ID
	MakerName      string                  `json:"maker_name"`                // 制单人名称
	MakerTime      *time.Time              `json:"maker_time"`                // 制单时间
	AuditorId      uint32                  `json:"auditor_id"`                // 审核人ID
	AuditorName    string                  `json:"auditor_name"`              // 审核人名称
	AuditTime      *time.Time              `json:"audit_time"`                // 审核时间
	SendTime       *time.Time              `json:"send_time"`                 // 送修时间
	SendRemark     string                  `json:"send_remark"`               // 送修备注
	ExpressType    uint8                   `json:"express_type"`              // 邮寄方：1-个人；2-门店
	ExpressNo      string                  `json:"express_no"`                // 快递单号
	ExpressFee     float64                 `json:"express_fee"`               // 快递费用
	RepairUnitId   uint32                  `json:"repair_unit_id"`            // 维修单位ID（供应商）
	RepairUnitName string                  `json:"repair_unit_name" gorm:"-"` // 维修单位名称（供应商）
	RepairFee      float64                 `json:"repair_fee"`                // 维修费用
	CompletedTime  *time.Time              `json:"completed_time"`            // 完成时间
	CompleteRemark string                  `json:"complete_remark"`           // 完成备注
	Commodities    []RepairRecordCommodity `json:"commodities" gorm:"-"`      // 维修商品信息
}

type RepairRecordCommodity struct {
	Model

	RepairRecordId uint32 `json:"repair_record_id"` // 维修记录ID
	CommodityId    uint32 `json:"commodity_id"`     // 商品ID
	CommodityName  string `json:"commodity_name"`   // 商品名称
	OldIMEI        string `json:"old_imei"`         // 旧机器编码
	NewIMEI        string `json:"new_imei"`         // 新机器编码
	Count          uint32 `json:"count"`            // 数量
	FaultImage     string `json:"fault_image"`      // 故障图片
	FaultDesc      string `json:"fault_desc"`       // 故障描述
}

type RepairCreateReq struct {
	Uid         uint32                  `json:"uid"`
	Tel         string                  `json:"tel"`
	StoreId     uint32                  `json:"store_id" binding:"required"`
	HandlerId   uint32                  `json:"handler_id" binding:"required"` // 经手人id
	HandlerName string                  `json:"handler_name"`                  // 经手人名称
	Commodities []RepairRecordCommodity `json:"commodities"`
}

type RepairEditReq struct {
	SerialNumber   string                  `json:"serial_number" binding:"required"` // 订单编号
	Uid            uint32                  `json:"uid"`                              // 用户ID
	Tel            string                  `json:"tel"`                              // 手机号
	MemberLevel    uint32                  `json:"member_level"`                     // 会员等级：普通用户、尊享会员
	StoreId        uint32                  `json:"store_id" binding:"required"`      // 门店ID
	HandlerId      uint32                  `json:"handler_id" binding:"required"`    // 经手人ID
	HandlerName    string                  `json:"handler_name"`                     // 经手人名称
	State          uint8                   `json:"state"`                            // 状态（1-待审核，2-已审核，3-维修中，4-已完成）
	MakerId        uint32                  `json:"maker_id" binding:"required"`      // 制单人ID
	MakerName      string                  `json:"maker_name"`                       // 制单人名称
	MakerTime      *time.Time              `json:"maker_time"`                       // 制单时间
	AuditorId      uint32                  `json:"auditor_id"`                       // 审核人ID
	AuditorName    string                  `json:"auditor_name"`                     // 审核人名称
	AuditTime      *time.Time              `json:"audit_time"`                       // 审核时间
	SendTime       *time.Time              `json:"send_time"`                        // 送修时间
	SendRemark     string                  `json:"send_remark"`                      // 送修备注
	ExpressNo      string                  `json:"express_no"`                       // 快递单号
	RepairUnitId   uint32                  `json:"repair_unit_id"`                   // 维修单位ID
	RepairFee      float64                 `json:"repair_fee"`                       // 维修费用
	CompletedTime  *time.Time              `json:"completed_time"`                   // 完成时间
	CompleteRemark string                  `json:"complete_remark"`                  // 完成备注
	Commodities    []RepairRecordCommodity `json:"commodities"`
}

// ErpRepairDeleteReq 删除维修订单入参
type ErpRepairDeleteReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}

// ErpRepairOrderListReq 查询维修订单列表入参
type ErpRepairOrderListReq struct {
	SerialNumber      string   `json:"serial_number"`       // 单据编号
	Uid               uint32   `json:"uid"`                 // 用户ID
	Tel               string   `json:"tel"`                 // 手机号
	MemberLevel       uint32   `json:"member_level"`        // 会员等级：普通用户、尊享会员
	StoreId           []uint32 `json:"store_id"`            // 门店id
	HandlerId         uint32   `json:"handler_id"`          // 经手人id
	State             []uint32 `json:"state"`               // 状态：1-待审核，2-已审核，3-维修中，4-已完成
	RepairUnitId      uint32   `json:"repair_unit_id"`      // 维修单位ID（供应商）
	MakeTimeStart     string   `json:"make_time_start"`     // 制单开始时间
	MakeTimeEnd       string   `json:"make_time_end"`       // 制单结束时间
	AuditTimeStart    string   `json:"audit_time_start"`    // 审核开始时间
	AuditTimeEnd      string   `json:"audit_time_end"`      // 审核结束时间
	SendTimeStart     string   `json:"send_time_start"`     // 送修开始时间
	SendTimeEnd       string   `json:"send_time_end"`       // 送修结束时间
	CompleteTimeStart string   `json:"complete_time_start"` // 维修完成开始时间
	CompleteTimeEnd   string   `json:"complete_time_end"`   // 维修完成结束时间
	PageIndex         int      `json:"pageIndex"`           // 页码
	PageSize          int      `json:"pageSize"`            // 页面条数
}

// ErpRepairOrderListResp 查询维修订单列表出参
type ErpRepairOrderListResp struct {
	List      []RepairRecord `json:"list"`
	Total     int            `json:"total"`     // 总条数
	PageIndex int            `json:"pageIndex"` // 页码
	PageSize  int            `json:"pageSize"`  // 页面条数
}

// ErpRepairDetailReq 查询维修订单详情入参
type ErpRepairDetailReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}

// ErpRepairAuditReq 审核维修订单入参
type ErpRepairAuditReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
	State        int    `json:"state"  binding:"required"`        // 审核操作: 1-审核 2-取消审核
}

// ErpRepairSendReq 维修订单送修入参
type ErpRepairSendReq struct {
	SerialNumber string  `json:"serial_number" binding:"required"`  // 单据编号
	RepairUnitId uint32  `json:"repair_unit_id" binding:"required"` // 维修单位ID（供应商）
	ExpressType  uint8   `json:"express_type" binding:"required"`   // 邮寄方：1-个人；2-门店
	ExpressNo    string  `json:"express_no"`                        // 快递单号
	ExpressFee   float64 `json:"express_fee"`                       // 快递费用
	SendRemark   string  `json:"send_remark"`                       // 送修备注
}

// ErpRepairCompleteReq 维修订单完成入参
type ErpRepairCompleteReq struct {
	SerialNumber   string  `json:"serial_number" binding:"required"` // 单据编号
	RepairFee      float64 `json:"repair_fee"`                       // 维修费用
	CompleteRemark string  `json:"complete_remark"`                  // 完成备注
}

// NewRepairBillSn 生成维修订单号
func NewRepairBillSn() string {
	nowTime := time.Now()
	rand.Seed(nowTime.UnixNano())
	max := 1
	for {
		if max > 5 {
			logger.Error("create sn err")
			return ""
		}
		random := rand.Int31n(9999) + 1000
		sn := fmt.Sprintf("wx%s%d", nowTime.Format("060102"), random)
		exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM repair_record WHERE serial_number='%s'", sn))
		if err != nil {
			logger.Error("exist sn err")
		}
		if !exist {
			return sn
		}

		max++
	}
}

// CreateRepairOrder 创建维修订单
func CreateRepairOrder(req *RepairCreateReq, sysUser *SysUser) (*RepairRecord, error) {
	// 开始事务
	tx := orm.Eloquent.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
			return
		}
	}()

	userMemberLevel := 1
	// 判断是否为尊享会员
	if IsValidPrivilegeMember(req.Uid) {
		userMemberLevel = 6
	}

	nowTime := time.Now()
	// 写入主表
	repair := RepairRecord{
		SerialNumber: NewRepairBillSn(),
		Uid:          req.Uid,
		Tel:          req.Tel,
		MemberLevel:  uint32(userMemberLevel),
		StoreId:      req.StoreId,
		HandlerId:    req.HandlerId,
		HandlerName:  req.HandlerName,
		MakerId:      uint32(sysUser.UserId),
		MakerName:    sysUser.NickName,
		MakerTime:    &nowTime,
		State:        ErpRepairOrderUnAudit, // 初始状态：待审核
	}
	if err := tx.Create(&repair).Error; err != nil {
		tx.Rollback()
		logger.Error("Create RepairRecord err:", logger.Field("err", err))
		return nil, err
	}

	// 写入子表
	for _, com := range req.Commodities {
		item := RepairRecordCommodity{
			RepairRecordId: repair.ID,
			CommodityId:    com.CommodityId,
			CommodityName:  com.CommodityName,
			OldIMEI:        com.OldIMEI,
			NewIMEI:        com.NewIMEI,
			Count:          com.Count,
			FaultImage:     com.FaultImage,
			FaultDesc:      com.FaultDesc,
		}
		if err := tx.Create(&item).Error; err != nil {
			tx.Rollback()
			logger.Error("Create RepairCommodity err:", logger.Field("err", err))
			return nil, err
		}
	}

	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		logger.Error("commit err:", logger.Field("err", err))
		return nil, err
	}

	repair.Commodities = req.Commodities

	return &repair, nil
}

// EditRepairOrder 编辑维修订单
func EditRepairOrder(req *RepairEditReq, sysUser *SysUser) (*RepairRecord, error) {
	// 查询订单信息
	var repairOrder RepairRecord
	err := orm.Eloquent.Table("repair_record").Where("serial_number=?", req.SerialNumber).Find(&repairOrder).Error
	if err != nil {
		logger.Error("repair order err:", logger.Field("err", err))
		return nil, err
	}

	if repairOrder.State != ErpRepairOrderUnAudit { // 只有待审核的订单才能编辑
		return nil, errors.New("订单不是待审核状态")
	}

	begin := orm.Eloquent.Begin()
	// 1-更新维修订单信息
	repairOrder.Uid = req.Uid
	repairOrder.Tel = req.Tel
	repairOrder.MemberLevel = req.MemberLevel
	repairOrder.StoreId = req.StoreId
	repairOrder.HandlerId = req.HandlerId
	repairOrder.HandlerName = req.HandlerName
	repairOrder.MakerId = uint32(sysUser.UserId)
	repairOrder.MakerName = sysUser.NickName

	err = begin.Model(&RepairRecord{}).Where("serial_number=?", req.SerialNumber).
		Omit("created_at").Save(repairOrder).Error
	if err != nil {
		begin.Rollback()
		logger.Error("update erp_order err:", logger.Field("err", err))
		return nil, err
	}

	// 2-更新维修订单商品表
	err = updateRepairCommodityData(begin, repairOrder.ID, req)
	if err != nil {
		begin.Rollback()
		logger.Error("update erp_purchase_commodity err:", logger.Field("err", err))
		return nil, err
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("commit err:", logger.Field("err", err))
		return nil, err
	}

	return &repairOrder, nil
}

// updateRepairCommodityData 更新维修订单商品信息
func updateRepairCommodityData(gdb *gorm.DB, orderId uint32, req *RepairEditReq) error {
	// 查询现有的零售订单信息
	var commodities []RepairRecordCommodity
	err := orm.Eloquent.Table("repair_record_commodity").Where("repair_record_id = ?", orderId).Find(&commodities).Error
	if err != nil {
		logger.Error("query repair_record_commodity err:", logger.Field("err", err))
		return err
	}

	// 1-删除所有的商品信息
	if len(commodities) != 0 {
		err = gdb.Delete(&commodities).Error
		if err != nil {
			logger.Error("更新商品订单信息-删除 error")
			return errors.New("操作失败:" + err.Error())
		}
	}

	for i, _ := range req.Commodities {
		req.Commodities[i].ID = 0
		if req.Commodities[i].RepairRecordId == 0 { //发现前端有时会没传，后端打补丁
			req.Commodities[i].RepairRecordId = orderId
		}
	}

	// 2-更新商品订单信息-新增
	if len(req.Commodities) != 0 {
		err = gdb.Create(&req.Commodities).Error
		if err != nil {
			logger.Error("更新商品订单信息-新增 error")
			return errors.New("操作失败:" + err.Error())
		}
	}

	return nil
}

// List 查询维修订单列表
func (m *ErpRepairOrderListReq) List(c *gin.Context) (*ErpRepairOrderListResp, error) {
	resp := &ErpRepairOrderListResp{
		PageIndex: m.PageIndex,
		PageSize:  m.PageSize,
	}
	page := m.PageIndex - 1
	if page < 0 {
		page = 0
	}
	if m.PageSize == 0 {
		m.PageSize = 10
	}
	qs := orm.Eloquent.Table("repair_record")
	if m.SerialNumber != "" {
		qs = qs.Where("serial_number = ?", m.SerialNumber)
	} else if m.Uid != 0 {
		qs = qs.Where("uid = ?", m.Uid)
	} else if m.Tel != "" {
		qs = qs.Where("tel = ?", m.Tel)
	} else {
		if m.RepairUnitId != 0 {
			qs = qs.Where("repair_unit_id = ?", m.RepairUnitId)
		}
		if len(m.StoreId) != 0 {
			qs = qs.Where("store_id in ?", m.StoreId)
		}
		// 非管理员才判断所属门店
		if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
			sysUser, err := GetSysUserByCtx(c)
			if err != nil {
				return nil, errors.New("操作失败:" + err.Error())
			}

			// 返回sysUser未过期的门店id列表
			storeList := GetValidStoreIDs(sysUser.StoreData)
			if len(storeList) > 0 {
				if len(storeList) == 1 {
					qs = qs.Where("store_id = ?", storeList[0])
				} else {
					qs = qs.Where("store_id IN (?)", storeList)
				}
			} else {
				return nil, errors.New("用户未绑定门店")
			}
		}
		if m.MemberLevel != 0 {
			qs = qs.Where("member_level = ?", m.MemberLevel)
		}
		if len(m.State) > 0 {
			qs = qs.Where("state IN (?)", m.State)
		}
		if m.HandlerId != 0 {
			qs = qs.Where("handler_id=?", m.HandlerId)
		}
		if m.AuditTimeStart != "" {
			parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart)
			if err != nil {
				logger.Errorf("erpRepairOrderList err:", err)
				return nil, err
			}
			qs = qs.Where("audit_time > ?", parse)
		}
		if m.AuditTimeEnd != "" {
			parse, err := time.Parse(QueryTimeFormat, m.AuditTimeEnd)
			if err != nil {
				logger.Errorf("erpRepairOrderList err:", err)
				return nil, err
			}
			//parse = parse.AddDate(0, 0, 1)
			qs = qs.Where("audit_time < ?", parse)
		}
		if m.MakeTimeStart != "" {
			parse, err := time.Parse(QueryTimeFormat, m.MakeTimeStart)
			if err != nil {
				logger.Errorf("err:", err)
			}
			qs = qs.Where("maker_time > ?", parse)
		}
		if m.MakeTimeEnd != "" {
			parse, err := time.Parse(QueryTimeFormat, m.MakeTimeEnd)
			if err != nil {
				logger.Errorf("err:", err)
			}
			qs = qs.Where("maker_time < ?", parse)
		}
		if m.SendTimeStart != "" {
			parse, err := time.Parse(QueryTimeFormat, m.SendTimeStart)
			if err != nil {
				logger.Errorf("err:", err)
			}
			qs = qs.Where("send_time > ?", parse)
		}
		if m.SendTimeEnd != "" {
			parse, err := time.Parse(QueryTimeFormat, m.SendTimeEnd)
			if err != nil {
				logger.Errorf("err:", err)
			}
			qs = qs.Where("send_time < ?", parse)
		}
		if m.CompleteTimeStart != "" {
			parse, err := time.Parse(QueryTimeFormat, m.CompleteTimeStart)
			if err != nil {
				logger.Errorf("err:", err)
			}
			qs = qs.Where("complete_time > ?", parse)
		}
		if m.CompleteTimeEnd != "" {
			parse, err := time.Parse(QueryTimeFormat, m.CompleteTimeEnd)
			if err != nil {
				logger.Errorf("err:", err)
			}
			qs = qs.Where("complete_time < ?", parse)
		}
	}

	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Error("count err:", logger.Field("err", err))
		return resp, err
	}
	resp.Total = int(count)
	var orders []RepairRecord
	err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&orders).Error
	if err != nil && err != RecordNotFound {
		logger.Error("erp commodity list err:", logger.Field("err", err))
		return resp, err
	}

	// 校验时间，如果为01-01-01 08:05，则赋值为空
	for i, v := range orders {
		if v.MakerTime != nil && v.MakerTime.IsZero() {
			orders[i].MakerTime = nil
		}

		if v.AuditTime != nil && v.AuditTime.IsZero() {
			orders[i].AuditTime = nil
		}

		if v.SendTime != nil && v.SendTime.IsZero() {
			orders[i].SendTime = nil
		}

		if v.CompletedTime != nil && v.CompletedTime.IsZero() {
			orders[i].CompletedTime = nil
		}

		// 添加维修单位名称
		supplier, _ := GetSupplierById(v.RepairUnitId)
		orders[i].RepairUnitName = supplier.Name
	}

	resp.List = orders
	return resp, nil
}

// SendToRepair 维修订单送修
func SendToRepair(req *ErpRepairSendReq, c *gin.Context) error {
	// 查询订单信息
	var repairRecord RepairRecord
	err := orm.Eloquent.Table("repair_record").Where("serial_number = ?", req.SerialNumber).
		Find(&repairRecord).Error
	if err != nil {
		logger.Error("order err:", logger.Field("err", err))
		return err
	}

	sysUser, err := GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		return err
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !CheckUserStore(repairRecord.StoreId, sysUser) {
			return errors.New("操作失败：您没有该门店权限")
		}
	}

	if repairRecord.ID == 0 {
		return errors.New("未查询到订单信息")
	}

	if repairRecord.State != ErpRepairOrderWaitRepair {
		return errors.New("订单不是待送修状态")
	}

	nowTime := time.Now()
	repairRecord.RepairUnitId = req.RepairUnitId
	repairRecord.ExpressType = req.ExpressType
	repairRecord.ExpressNo = req.ExpressNo
	repairRecord.ExpressFee = req.ExpressFee
	repairRecord.SendRemark = req.SendRemark
	repairRecord.State = ErpRepairOrderBingRepaired
	repairRecord.SendTime = &nowTime

	err = orm.Eloquent.Model(&RepairRecord{}).Where("id = ?", repairRecord.ID).
		Updates(repairRecord).Error
	if err != nil {
		return err
	}

	return nil
}

// CompleteRepairOrder 维修订单完成
func CompleteRepairOrder(req *ErpRepairCompleteReq, c *gin.Context) error {
	// 查询订单信息
	var repairRecord RepairRecord
	err := orm.Eloquent.Table("repair_record").Where("serial_number = ?", req.SerialNumber).
		Find(&repairRecord).Error
	if err != nil {
		logger.Error("order err:", logger.Field("err", err))
		return err
	}

	sysUser, err := GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		return err
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !CheckUserStore(repairRecord.StoreId, sysUser) {
			return errors.New("操作失败：您没有该门店权限")
		}
	}

	if repairRecord.ID == 0 {
		return errors.New("未查询到订单信息")
	}

	if repairRecord.State != ErpRepairOrderBingRepaired {
		return errors.New("订单不是待送修状态")
	}

	nowTime := time.Now()
	repairRecord.RepairFee = req.RepairFee
	repairRecord.CompleteRemark = req.CompleteRemark
	repairRecord.State = ErpRepairOrderFinished
	repairRecord.CompletedTime = &nowTime

	err = orm.Eloquent.Model(&RepairRecord{}).Where("id = ?", repairRecord.ID).
		Updates(repairRecord).Error
	if err != nil {
		return err
	}

	return nil
}

// ErpRepairDetailReportReq 维修明细汇总入参
type ErpRepairDetailReportReq struct {
	SerialNumber      string   `json:"serial_number"`       // 单据编号
	Uid               uint32   `json:"uid"`                 // 用户ID
	Tel               string   `json:"tel"`                 // 手机号
	MemberLevel       uint32   `json:"member_level"`        // 会员等级：普通用户、尊享会员
	StoreId           []uint32 `json:"store_id"`            // 门店id
	HandlerId         uint32   `json:"handler_id"`          // 经手人id
	RepairUnitId      uint32   `json:"repair_unit_id"`      // 维修单位ID（供应商）
	MakeTimeStart     string   `json:"make_time_start"`     // 制单开始时间
	MakeTimeEnd       string   `json:"make_time_end"`       // 制单结束时间
	AuditTimeStart    string   `json:"audit_time_start"`    // 审核开始时间
	AuditTimeEnd      string   `json:"audit_time_end"`      // 审核结束时间
	SendTimeStart     string   `json:"send_time_start"`     // 送修开始时间
	SendTimeEnd       string   `json:"send_time_end"`       // 送修结束时间
	CompleteTimeStart string   `json:"complete_time_start"` // 维修完成开始时间
	CompleteTimeEnd   string   `json:"complete_time_end"`   // 维修完成结束时间
	PageIndex         int      `json:"pageIndex"`           // 页码
	PageSize          int      `json:"pageSize"`            // 页面条数
	IsExport          uint32   `json:"is_export"`           // 1-导出
	//State             []uint32 `json:"state"`               // 状态：1-待审核，2-已审核，3-维修中，4-已完成
}

// ErpRepairDetailReportResp 维修明细汇总出参
type ErpRepairDetailReportResp struct {
	Total     int                   `json:"total"`      // 总条数（总订单数）
	PageIndex int                   `json:"pageIndex"`  // 页码
	PageSize  int                   `json:"pageSize"`   // 每页展示条数
	ExportUrl string                `json:"export_url"` // 导出excel地址
	List      []RepairRecord        `json:"list"`       // 零售明细
	SumData   RepairDetailTotalData `json:"sumData"`    // 汇总数据
}

// RepairDetailTotalData 维修明细相关金额汇总
type RepairDetailTotalData struct {
	Count           int32   `json:"count"`             // 维修数量
	TotalExpressFee float64 `json:"total_express_fee"` // 快递费用
	TotalRepairFee  float64 `json:"total_repair_fee"`  // 维修费用
}

// RepairDetailReport 维修明细
func RepairDetailReport(req *ErpRepairDetailReportReq, c *gin.Context) (*ErpRepairDetailReportResp, error) {
	page := req.PageIndex - 1
	if page < 0 {
		page = 0
	}
	if req.PageSize == 0 {
		req.PageSize = 10
	}

	db := orm.Eloquent.Table("repair_record AS rr").
		Select("rr.*, s.name AS store_name, ru.name AS repair_unit_name").
		Joins("LEFT JOIN store s ON rr.store_id = s.id").
		Joins("LEFT JOIN erp_supplier ru ON rr.repair_unit_id = ru.id").
		Where("state in (3,4)")
	// 条件过滤
	db = buildRepairDetailQuery(db, req)

	sumQuery := orm.Eloquent.Table("repair_record AS rr").
		Select("COUNT(*) AS count, COALESCE(SUM(rr.express_fee), 0) AS total_express_fee, COALESCE(SUM(rr.repair_fee), 0) AS total_repair_fee").
		Where("state in (3,4)")
	sumQuery = buildRepairDetailQuery(sumQuery, req)

	// 非管理员才判断所属门店
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		sysUser, err := GetSysUserByCtx(c)
		if err != nil {
			return nil, errors.New("操作失败:" + err.Error())
		}

		// 返回sysUser未过期的门店id列表
		storeList := GetValidStoreIDs(sysUser.StoreData)
		if len(storeList) > 0 {
			if len(storeList) == 1 {
				db = db.Where("store_id = ?", storeList[0])
				sumQuery = sumQuery.Where("store_id = ?", storeList[0])
			} else {
				db = db.Where("store_id IN (?)", storeList)
				sumQuery = sumQuery.Where("store_id IN (?)", storeList)
			}
		} else {
			return nil, errors.New("用户未绑定门店")
		}
	}

	var total int64
	if err := db.Count(&total).Error; err != nil {
		return nil, err
	}

	var records []RepairRecord
	query := db.Order("rr.id DESC")

	if req.IsExport != 1 {
		query = query.Offset(page * req.PageSize).Limit(req.PageSize)
	}

	if err := query.Find(&records).Error; err != nil {
		return nil, err
	}

	// 查询商品明细
	for i := range records {
		var commodities []RepairRecordCommodity
		err := orm.Eloquent.Table("repair_record_commodity AS rc").
			Select("rc.*, ec.name AS commodity_name").
			Joins("LEFT JOIN erp_commodity ec ON rc.commodity_id = ec.id").
			Where("rc.repair_record_id = ?", records[i].ID).
			Find(&commodities).Error
		if err != nil {
			return nil, err
		}
		records[i].Commodities = commodities
	}

	// 汇总数据
	var sumData RepairDetailTotalData
	if err := sumQuery.Scan(&sumData).Error; err != nil {
		return nil, err
	}

	resp := &ErpRepairDetailReportResp{
		Total:     int(total),
		PageIndex: req.PageIndex,
		PageSize:  req.PageSize,
		List:      records,
		SumData:   sumData,
	}

	// 处理导出逻辑
	if req.IsExport == 1 {
		exportUrl, err := ExportRepairDetailExcel(records, sumData)
		if err != nil {
			return nil, err
		}
		resp.ExportUrl = exportUrl
		resp.List = nil

	}

	return resp, nil
}

func buildRepairDetailQuery(base *gorm.DB, req *ErpRepairDetailReportReq) *gorm.DB {
	if req.SerialNumber != "" {
		base = base.Where("rr.serial_number = ?", req.SerialNumber)
	}
	if req.Uid > 0 {
		base = base.Where("rr.uid = ?", req.Uid)
	}
	if req.Tel != "" {
		base = base.Where("rr.tel = ?", req.Tel)
	}
	if req.MemberLevel > 0 {
		base = base.Where("rr.member_level = ?", req.MemberLevel)
	}
	if len(req.StoreId) > 0 {
		base = base.Where("rr.store_id IN (?)", req.StoreId)
	}
	if req.HandlerId > 0 {
		base = base.Where("rr.handler_id = ?", req.HandlerId)
	}
	//if len(req.State) > 0 {
	//	base = base.Where("rr.state IN (?)", req.State)
	//}
	if req.RepairUnitId > 0 {
		base = base.Where("rr.repair_unit_id = ?", req.RepairUnitId)
	}
	if req.MakeTimeStart != "" && req.MakeTimeEnd != "" {
		base = base.Where("rr.maker_time BETWEEN ? AND ?", req.MakeTimeStart, req.MakeTimeEnd)
	}
	if req.AuditTimeStart != "" && req.AuditTimeEnd != "" {
		base = base.Where("rr.audit_time BETWEEN ? AND ?", req.AuditTimeStart, req.AuditTimeEnd)
	}
	if req.SendTimeStart != "" && req.SendTimeEnd != "" {
		base = base.Where("rr.send_time BETWEEN ? AND ?", req.SendTimeStart, req.SendTimeEnd)
	}
	if req.CompleteTimeStart != "" && req.CompleteTimeEnd != "" {
		base = base.Where("rr.completed_time BETWEEN ? AND ?", req.CompleteTimeStart, req.CompleteTimeEnd)
	}
	return base
}

// ExportRepairDetailExcel 导出维修明细报表excel
func ExportRepairDetailExcel(list []RepairRecord, sumData RepairDetailTotalData) (string, error) {
	file := excelize.NewFile()
	sheet := "Sheet1"

	url := config.ExportConfig.Url
	fileName := time.Now().Format(TimeFormat) + "维修明细.xlsx"
	savePath := config.ExportConfig.Path + fileName
	fmt.Println("生成路径:", url+fileName)

	storeMap, err := GetAllStoreData()
	if err != nil {
		return "", err
	}

	// 表头
	title := []interface{}{
		"维修单号", "门店", "用户ID", "联系电话", "会员等级", "状态", "制单人", "制单时间", "审核人", "审核时间",
		"送修时间", "送修备注", "邮寄方式", "快递单号", "快递费用", "维修单位", "维修费用", "完成时间", "完成备注",
		"商品名称", "旧机器编码", "新机器编码", "数量", "故障描述",
	}

	// 写表头
	for i, v := range title {
		cell, _ := excelize.CoordinatesToCellName(i+1, 1)
		_ = file.SetCellValue(sheet, cell, v)
	}

	rowIndex := 2
	for _, record := range list {
		memberLevelStr := GetUserTypeString(int(record.MemberLevel))

		stateMap := map[uint8]string{
			1: "待审核",
			2: "待送修",
			3: "维修中",
			4: "已完成",
		}
		stateStr := stateMap[record.State]

		sendTypeStr := map[uint8]string{
			1: "个人",
			2: "门店",
		}[record.ExpressType]

		nFlag := 0
		for _, comm := range record.Commodities {
			var row []interface{}
			if nFlag >= 1 {
				row = []interface{}{
					record.SerialNumber,
					storeMap[record.StoreId].Name,
					record.Uid,
					record.Tel,
					memberLevelStr,
					stateStr,
					record.MakerName,
					formatDateTime(record.MakerTime),
					record.AuditorName,
					formatTime(record.AuditTime),
					formatTime(record.SendTime),
					record.SendRemark,
					sendTypeStr,
					record.ExpressNo,
					"",
					record.RepairUnitName,
					"",
					formatTime(record.CompletedTime),
					record.CompleteRemark,
					comm.CommodityName,
					comm.OldIMEI,
					comm.NewIMEI,
					comm.Count,
					comm.FaultDesc,
				}
			} else {
				row = []interface{}{
					record.SerialNumber,
					storeMap[record.StoreId].Name,
					record.Uid,
					record.Tel,
					memberLevelStr,
					stateStr,
					record.MakerName,
					formatDateTime(record.MakerTime),
					record.AuditorName,
					formatTime(record.AuditTime),
					formatTime(record.SendTime),
					record.SendRemark,
					sendTypeStr,
					record.ExpressNo,
					record.ExpressFee,
					record.RepairUnitName,
					record.RepairFee,
					formatTime(record.CompletedTime),
					record.CompleteRemark,
					comm.CommodityName,
					comm.OldIMEI,
					comm.NewIMEI,
					comm.Count,
					comm.FaultDesc,
				}
			}

			for j, val := range row {
				cell, _ := excelize.CoordinatesToCellName(j+1, rowIndex)
				_ = file.SetCellValue(sheet, cell, val)
			}
			rowIndex++
			nFlag++
		}
	}

	// 汇总行
	summary := []interface{}{
		fmt.Sprintf("维修单数: %d", len(list)),
		"", "", "", "", "", "", "", "", "", "", "", "", "", sumData.TotalExpressFee, "", sumData.TotalRepairFee,
	}

	for i, val := range summary {
		cell, _ := excelize.CoordinatesToCellName(i+1, rowIndex)
		_ = file.SetCellValue(sheet, cell, val)
	}

	// 设置样式
	style, _ := file.NewStyle(`{
		"alignment":{"horizontal":"center","vertical":"center"},
		"border":[
			{"type":"left","color":"000000","style":1},
			{"type":"top","color":"000000","style":1},
			{"type":"right","color":"000000","style":1},
			{"type":"bottom","color":"000000","style":1}
		]
	}`)

	lastCol, _ := excelize.ColumnNumberToName(len(title))
	endCell := fmt.Sprintf("%s%d", lastCol, rowIndex)
	_ = file.SetCellStyle(sheet, "A1", endCell, style)

	// 设置列宽（根据字段名称微调）
	file.SetColWidth(sheet, "A", "A", 18)
	file.SetColWidth(sheet, "B", "B", 25)
	file.SetColWidth(sheet, "C", "C", 10)
	file.SetColWidth(sheet, "D", "D", 15)
	file.SetColWidth(sheet, "E", "E", 15)
	file.SetColWidth(sheet, "J", "J", 18)
	file.SetColWidth(sheet, "K", "K", 18)
	file.SetColWidth(sheet, "N", "N", 20)
	file.SetColWidth(sheet, "S", "S", 18)
	file.SetColWidth(sheet, "T", "T", 25)
	file.SetColWidth(sheet, "X", "X", 30)

	// 保存
	if err := file.SaveAs(savePath); err != nil {
		logger.Error("保存文件失败:", logger.Field("err", err))
		return "", err
	}
	return url + fileName, nil
}

// formatTime 格式化时间为空判断
func formatTime(t *time.Time) string {
	if t == nil {
		return ""
	}
	return t.Format("2006-01-02 15:04:05")
}

// formatDateTime 格式化时间为空判断（仅保留日期）
func formatDateTime(t *time.Time) string {
	if t == nil {
		return ""
	}
	return t.Format("2006-01-02")
}
