package basic

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"go-admin/app/admin/middleware"
	"go-admin/app/admin/models"
	orm "go-admin/common/global"
	"go-admin/logger"
	"go-admin/tools/app"
	"io"
	"net/http"
)

// CommodityCreate 新增商品
// @Summary 新增商品
// @Tags 商品资料
// @Produce json
// @Accept json
// @Param request body models.CommodityCreateRequest true "商品新增模型"
// @Success 200 {object} models.ErpCommodity
// @Router /api/v1/commodity/create [post]
// 规则：商品名称/商品编号相同则为同一商品，创建的时候由于商品编号不重复，无需判断
func CommodityCreate(c *gin.Context) {
	var req = new(models.CommodityCreateRequest)

	err := c.ShouldBindJSON(&req)
	if err != nil {
		fmt.Println(err.Error())
		app.Error(c, http.StatusBadRequest, errors.New("param err"), "参数错误:"+err.Error())
		return
	}

	//brokerage1Float, err := models.StringToFloat(req.Brokerage1)
	//if err != nil {
	//	//logger.Error("brokerage1 err:", err)
	//	app.Error(c, http.StatusBadRequest, errors.New("param err"), "参数错误")
	//	return
	//}
	//
	//brokerage2Float, err := models.StringToFloat(req.Brokerage2)
	//if err != nil {
	//	//logger.Error("brokerage1 err:", err)
	//	app.Error(c, http.StatusBadRequest, errors.New("param err"), "参数错误")
	//	return
	//}
	//
	//memberDiscountFloat, err := models.StringToFloat(req.MemberDiscount)
	//if err != nil {
	//	//logger.Error("brokerage1 err:", err)
	//	app.Error(c, http.StatusBadRequest, errors.New("param err"), "参数错误")
	//	return
	//}

	barCode := ""
	if req.ErpBarcode != "" { // 条码不为空则校验
		barCode, err = models.CheckAndConvertBarcode(req.ErpBarcode)
		if err != nil {
			app.Error(c, http.StatusBadRequest, errors.New("param err"), "参数错误:"+err.Error())
			return
		}
	} else { // 条码为空则自动生成
		barCode, err = models.GenerateBarcode(req.ErpCategoryId)
		if err != nil {
			app.Error(c, http.StatusBadRequest, errors.New("gen barcode err"), err.Error())
			return
		}
	}

	brokerage1Float := req.Brokerage1
	brokerage2Float := req.Brokerage2
	memberDiscountFloat := req.MemberDiscount

	if models.IsExistingProduct(req.Name) {
		app.Error(c, http.StatusBadRequest, errors.New("param err"), "商品名称已存在，不能重复")
		return
	}

	if req.IsIMEI == 2 { // 是否串码：1-串码类 2-非串码
		req.IMEIType = 1 // 系统生成串码：2-是（系统生成） 3-否（手动添加） 1表示非串码
	}

	commodity := &models.ErpCommodity{
		Number:          1,
		Name:            req.Name,
		ErpCategoryId:   req.ErpCategoryId,
		ErpCategoryName: "",
		ErpBarcode:      barCode,
		IMEIType:        req.IMEIType,
		ErpSupplierId:   req.ErpSupplierId,
		ErpSupplierName: "",
		RetailPrice:     req.RetailPrice,
		MinRetailPrice:  req.MinRetailPrice,
		//StaffCostPrice:  req.StaffCostPrice + req.WholesalePrice,
		StaffCostPrice:   req.StaffCostPrice,
		WholesalePrice:   req.WholesalePrice,
		Brokerage1:       brokerage1Float,
		Brokerage2:       brokerage2Float,
		MemberDiscount:   memberDiscountFloat,
		Origin:           req.Origin,
		Remark:           req.Remark,
		Img:              req.Img,
		StopPurchase:     req.StopPurchase,
		ManufacturerCode: req.ManufacturerCode,
	}
	err = commodity.SetErpCategory()
	if err != nil {
		//logger.Error("set erp category err:", err)
		app.Error(c, http.StatusInternalServerError, err, "创建失败")
		return
	}
	err = commodity.IdInit()
	if err != nil {
		app.Error(c, http.StatusInternalServerError, err, "创建失败:"+err.Error())
		return
	}

	commodity.SerialNumber, err = models.GenerateSerialNumber(req.ErpCategoryId)
	if err != nil {
		app.Error(c, http.StatusInternalServerError, err, err.Error())
		return
	}

	err = orm.Eloquent.Create(commodity).Error
	if err != nil {
		//logger.Error("create commodity err:", err)
		app.Error(c, http.StatusInternalServerError, err, "创建失败")
		return
	}

	app.OK(c, commodity, "OK")
	return
}

// CommodityList 商品列表
// @Summary 商品列表
// @Tags 商品资料
// @Produce json
// @Accept json
// @Param request body models.ErpCommodityListReq true "商品列表模型"
// @Success 200 {object} models.ErpCommodityListResp
// @Router /api/v1/commodity/list [post]
func CommodityList(c *gin.Context) {
	req := &models.ErpCommodityListReq{}
	if err := c.ShouldBindJSON(&req); err != nil {
		//logger.Error(err)
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	resp, err := req.List()
	if err != nil {
		//logger.Error("erp commodity list err:", err)
		app.Error(c, http.StatusInternalServerError, err, "获取失败")
		return
	}

	app.OK(c, resp, "")
	return
}

// CommodityDetail 商品详情
// @Summary 商品详情
// @Tags 商品资料
// @Produce json
// @Accept json
// @Param request body  models.CommodityDetailRequest true "商品详情模型"
// @Success 200 {object} models.ErpCommodity
// @Router /api/v1/commodity/detail [post]
func CommodityDetail(c *gin.Context) {
	var req = new(models.CommodityDetailRequest)

	if err := c.ShouldBindJSON(&req); err != nil {
		//logger.Error(err)
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	var commodity models.ErpCommodity
	qs := orm.Eloquent.Table("erp_commodity")
	if req.ErpCommodityId != 0 {
		qs = qs.Where("id=?", req.ErpCommodityId)
	}
	if req.SerialNumber != "" {
		qs = qs.Where("serial_number=?", req.SerialNumber)
	}
	err := qs.Find(&commodity).Error
	if err != nil {
		//logger.Error("erp commodity err:", err)
		app.Error(c, http.StatusInternalServerError, err, "获取失败")
		return
	}

	if commodity.IMEIType == 1 { //无串码
		commodity.IsIMEI = 2 // 非串码
	} else {
		commodity.IsIMEI = 1 // 串码
	}

	// 查询是否有库存
	var count int64
	err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and state = ?",
		commodity.ID, models.InStock).Count(&count).Error
	if err != nil {
		app.Error(c, http.StatusInternalServerError, err, "获取商品库存信息失败")
		return
	}
	commodity.StockCount = uint32(count)

	app.OK(c, commodity, "")
	return
}

// CommodityEdit 编辑商品
// @Summary 编辑商品
// @Tags 商品资料
// @Produce json
// @Accept json
// @Param request body  models.CommodityEditRequest true "编辑商品模型"
// @Success 200 {object} models.ErpCommodity
// @Router /api/v1/commodity/edit [post]
func CommodityEdit(c *gin.Context) {
	var req = new(models.CommodityEditRequest)

	err := c.ShouldBindJSON(&req)
	if err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误:"+err.Error())
		return
	}
	barCode := ""
	if req.ErpBarcode != "" { // 条码不为空则校验
		barCode, err = models.CheckBarcodeById(req.ErpBarcode, req.Id)
		if err != nil {
			app.Error(c, http.StatusBadRequest, errors.New("param err"), "参数错误:"+err.Error())
			return
		}
	} else { // 条码为空则自动生成
		barCode, err = models.GenerateBarcode(req.ErpCategoryId)
		if err != nil {
			app.Error(c, http.StatusBadRequest, errors.New("gen barcode err"), err.Error())
			return
		}
	}

	brokerage1Float := req.Brokerage1
	brokerage2Float := req.Brokerage2
	memberDiscountFloat := req.MemberDiscount

	commodity := &models.ErpCommodity{
		Name:            req.Name,
		ErpCategoryId:   req.ErpCategoryId,
		ErpCategoryName: "",
		ErpBarcode:      barCode,
		IMEIType:        req.IMEIType,
		ErpSupplierId:   req.ErpSupplierId,
		ErpSupplierName: "",
		RetailPrice:     req.RetailPrice,
		MinRetailPrice:  req.MinRetailPrice,
		//StaffCostPrice:  req.StaffCostPrice + req.WholesalePrice,
		StaffCostPrice:   req.StaffCostPrice,
		WholesalePrice:   req.WholesalePrice,
		Brokerage1:       brokerage1Float,
		Brokerage2:       brokerage2Float,
		MemberDiscount:   memberDiscountFloat,
		Origin:           req.Origin,
		Remark:           req.Remark,
		Img:              req.Img,
		StopPurchase:     req.StopPurchase,
		ManufacturerCode: req.ManufacturerCode,
	}
	commodity.ID = req.Id
	err = commodity.SetErpCategory()
	if err != nil {
		logger.Error("set erp category err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}
	commodity.IdInit()

	var catCommodity models.ErpCommodity
	err = orm.Eloquent.Table("erp_commodity").Where("id=?", req.Id).Find(&catCommodity).Error
	if err != nil {
		logger.Error("cat erp commodity err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}
	commodity.Number = catCommodity.Number
	commodity.SerialNumber = catCommodity.SerialNumber

	if commodity.ErpCategory != nil && commodity.ErpCategory.ID != 0 {
		if commodity.ErpCategory.ID != catCommodity.ErpCategoryId { // 编辑时更换了分类ID
			commodity.ErpCategoryId = commodity.ErpCategory.ID
			commodity.ErpCategoryName = commodity.ErpCategory.Name
			commodity.SerialNumber, err = models.GenerateSerialNumber(commodity.ErpCategoryId) // 更新商品编号
			if err != nil {
				app.Error(c, http.StatusInternalServerError, err, err.Error())
				return
			}
		} else {
			commodity.ErpCategory = nil
		}
	}

	if req.IsIMEI == 2 { // 是否串码：1-串码类 2-非串码
		commodity.IMEIType = 1 // 系统生成串码：2-是（系统生成） 3-否（手动添加） 1表示非串码
	}

	var sysIsIMEI uint32
	switch catCommodity.IMEIType {
	case 1:
		sysIsIMEI = 2 // 非串码
	case 2:
		fallthrough
	case 3:
		sysIsIMEI = 1 // 串码
	}

	if req.IsIMEI != sysIsIMEI {
		// 查询是否有库存
		var count int64
		err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and state = ?",
			commodity.ID, models.InStock).Count(&count).Error
		if err != nil {
			app.Error(c, http.StatusInternalServerError, err, "获取商品库存信息失败")
			return
		}

		if count > 0 {
			app.Error(c, http.StatusInternalServerError, err, "该商品已有库存，不能修改串码/非串码选项")
			return
		}
	}

	begin := orm.Eloquent.Begin()
	err = begin.Omit("created_at").Save(commodity).Error
	if err != nil {
		logger.Error("create commodity err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	// 同步更新库存表和库存商品表的"指导零售价"和"最低零售价"、"分类id"、"分类名称"、"商品编号"；库存商品表的"商品条码"
	err = models.UpdateErpStockAmountInfo(begin, req, barCode, commodity.SerialNumber, commodity.ErpCategory)
	if err != nil {
		begin.Rollback()
		logger.Error("UpdateErpStockAmountInfo err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("commit err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	app.OK(c, commodity, "")
	return
}

// CommodityDel 删除商品
// @Summary 删除商品
// @Tags 商品资料
// @Produce json
// @Accept json
// @Param request body  models.CommodityDelRequest true "删除商品模型"
// @Success 200 {object} app.Response
// @Router /api/v1/commodity/delete [post]
func CommodityDel(c *gin.Context) {
	var req = new(models.CommodityDelRequest)

	if err := c.ShouldBindJSON(&req); err != nil {
		//logger.Error(err)
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	// 检查商品是否存在
	if !models.IsExistingCommodity(req.ErpCommodityId) {
		app.Error(c, http.StatusInternalServerError, errors.New("该商品不存在"), "该商品不存在")
		return
	}

	// 删除商品之前需要判断该商品是否有库存
	if models.CheckCommodityIsHavaStock(req.ErpCommodityId) {
		app.Error(c, http.StatusInternalServerError, errors.New("该商品有库存不可删除"), "该商品有库存不可删除")
		return
	}

	err := orm.Eloquent.Table("erp_commodity").Where("id=?", req.ErpCommodityId).Delete(&models.ErpCommodity{}).Error
	if err != nil {
		//logger.Error("erp commodity err:", err)
		app.Error(c, http.StatusInternalServerError, err, "获取失败")
		return
	}

	app.OK(c, nil, "删除成功")
	return
}

// CommodityImportView 导入商品资料预览
// @Summary 导入商品资料预览
// @Tags 商品资料
// @Produce json
// @Accept json
// @Param file body string true "上传excel文件"
// @Success 200 {array} models.CommodityExcel
// @Router /api/v1/commodity/import_commodity_view [post]
func CommodityImportView(c *gin.Context) {
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		//logger.Error("form file err:", err)
		app.Error(c, http.StatusInternalServerError, err, "预览失败")
		return
	}

	readAll, err := io.ReadAll(file)
	if err != nil {
		//logger.Error("read all err:", err)
		app.Error(c, http.StatusInternalServerError, err, "预览失败")
		return
	}

	fmt.Println("header:", header.Filename)
	_, colsMap, err := models.FileExcelReader([]byte(readAll), nil)
	if err != nil {
		//logger.Error("file excel reader err:", err)
		app.Error(c, http.StatusInternalServerError, err, "预览失败")
		return
	}
	fmt.Println("colsMap:", colsMap)
	if len(colsMap) != 0 {
		colsMap = colsMap[1:]
	}

	app.OK(c, &colsMap, "")
	return
}

// CommodityImport 导入商品资料
// @Summary 导入商品资料
// @Tags 商品资料
// @Produce json
// @Accept json
// @Param file body string true "上传excel文件"
// @Success 200 {object} app.Response
// @Router /api/v1/commodity/import_commodity [post]
func CommodityImport(c *gin.Context) {
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		//logger.Error("form file err:", err)
		app.Error(c, http.StatusInternalServerError, err, "预览失败")
		return
	}

	readAll, err := io.ReadAll(file)
	if err != nil {
		//logger.Error("read all err:", err)
		app.Error(c, http.StatusInternalServerError, err, "预览失败")
		return
	}

	fmt.Println("header:", header.Filename)
	_, colsMap, err := models.FileExcelImport(c, []byte(readAll), nil, 2, 0)
	if err != nil {
		//logger.Error("file excel reader err:", err)
		app.Error(c, http.StatusInternalServerError, err, err.Error())
		return
	}
	fmt.Println("colsMap:", colsMap)
	if len(colsMap) != 0 {
		colsMap = colsMap[1:]
	}

	err = models.ImportCommodityData(colsMap, middleware.GetCooperativeBusinessId(c))
	if err != nil {
		//logger.Error("file excel reader err:", err)
		app.Error(c, http.StatusInternalServerError, err, err.Error())
		return
	}

	app.OK(c, nil, "导入成功")
	return
}
