package handlers

import (
	"net/http"

	"easydo-echo_win7/models"
	"easydo-echo_win7/services"
	"easydo-echo_win7/utils"

	"easydo-echo_win7/middleware"

	"github.com/labstack/echo-contrib/session"
	"github.com/labstack/echo/v4"
)

func Add_product_pre_plan_to_routes(e *echo.Echo) {
	group := e.Group("/productPrePlan")
	group.Use(middleware.AuthMiddleware)
	group.POST("/getPage", productPrePlanGetPage)
	group.POST("/save", productPrePlanSave)
}

func productPrePlanGetPage(c echo.Context) error {
	var paramMap map[string]interface{}
	if err := c.Bind(&paramMap); err != nil {
		return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("参数解析失败", err.Error()))
	}
	result, err := services.JdbcClient.GetJdbcPage(paramMap, models.SaleOrder{})
	if err != nil {
		utils.PrintSqlErr(err)
		return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
	}
	list := utils.ConvertInterface[[]models.SaleOrder](result.Records)
	if len(list) == 0 {
		list = []models.SaleOrder{}
	}
	for i := range list {
		model := list[i]
		minioList, err := services.JdbcClient.GetMinioFile(model)
		if err != nil {
			utils.PrintSearchFileErr(err)
		}
		model.FileList = &minioList

		detailParam := new(models.SaleOrderDetail)
		detailParam.OrderId = model.ID
		result, err := services.JdbcClient.GetJdbcListByObject(detailParam)
		if err != nil {
			utils.PrintSqlErr(err)
			return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
		}
		detail_list := utils.ConvertInterface[[]models.SaleOrderDetail](result)

		for j := range detail_list {
			detail := detail_list[j]

			material := new(models.ProductMaterial)
			material.Code = detail.MaterialCode
			material.TenantId = model.TenantId
			err = services.JdbcClient.GetJdbcModel(material)
			if err != nil {
				utils.PrintSqlErr(err)
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
			}

			detail.Material = material

			bom := new(models.ProductBom)
			parentId := models.Common_Value_Zero_String
			bom.ParentId = &parentId
			bom.MaterialCode = material.Code
			bom.TenantId = model.TenantId
			status := models.Status_Enable
			bom.Status = &status
			err = services.JdbcClient.GetJdbcModel(bom)
			if err != nil {
				utils.PrintSqlErr(err)
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
			}

			if bom.ID != nil && len(*bom.ID) > 0 {
				//对于有bom的物料,查询出bom下所有组成(bom_list)和库存
				bomParam := new(models.ProductBom)
				bomParam.BomCode = bom.BomCode
				bomParam.TenantId = model.TenantId
				result, err := services.JdbcClient.GetJdbcListByObject(bomParam)
				if err != nil {
					utils.PrintSqlErr(err)
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
				}
				bom_list := utils.ConvertInterface[[]models.ProductBom](result)

				for k := range bom_list {
					bom_model := bom_list[k]

					material := new(models.ProductMaterial)
					material.Code = bom_model.MaterialCode
					material.TenantId = model.TenantId
					err = services.JdbcClient.GetJdbcModel(material)
					if err != nil {
						utils.PrintSqlErr(err)
						return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
					}
					bom_model.Material = material

					warehouseMaterial := new(models.WarehouseMaterial)
					warehouseMaterial.MaterialCode = material.Code
					warehouseMaterial.TenantId = model.TenantId
					warehouse_material_status := models.Status_Enable
					warehouseMaterial.Status = &warehouse_material_status
					warehouse_material_result, err := services.JdbcClient.GetJdbcListByObject(warehouseMaterial)
					if err != nil {
						utils.PrintSqlErr(err)
						return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
					}
					warehouse_material_list := utils.ConvertInterface[[]models.WarehouseMaterial](warehouse_material_result)
					if warehouse_material_list != nil {
						for l := range warehouse_material_list {
							warehouse_material_model := warehouse_material_list[l]

							warehouse := new(models.Warehouse)
							warehouse.ID = warehouse_material_model.WarehouseId
							err = services.JdbcClient.GetJdbcModelById(warehouse)
							if err != nil {
								utils.PrintSqlErr(err)
								return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
							}
							warehouse_material_model.Warehouse = warehouse

							warehouse_material_list[l] = warehouse_material_model
						}

						bom_model.WarehouseMaterialList = &warehouse_material_list
					}

					bom_list[k] = bom_model
				}
				detail.BomList = &bom_list
			} else {
				//对于没有bom的物料,只需要查询出库存
				warehouseMaterial := new(models.WarehouseMaterial)
				warehouseMaterial.MaterialCode = material.Code
				warehouseMaterial.TenantId = model.TenantId
				warehouse_material_status := models.Status_Enable
				warehouseMaterial.Status = &warehouse_material_status
				warehouse_material_result, err := services.JdbcClient.GetJdbcListByObject(warehouseMaterial)
				if err != nil {
					utils.PrintSqlErr(err)
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
				}
				warehouse_material_list := utils.ConvertInterface[[]models.WarehouseMaterial](warehouse_material_result)

				if warehouse_material_list != nil {
					for k := range warehouse_material_list {
						warehouse_material_model := warehouse_material_list[k]

						warehouse := new(models.Warehouse)
						warehouse.ID = warehouse_material_model.WarehouseId
						err = services.JdbcClient.GetJdbcModelById(warehouse)
						if err != nil {
							utils.PrintSqlErr(err)
							return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
						}
						warehouse_material_model.Warehouse = warehouse

						warehouse_material_list[k] = warehouse_material_model
					}

					detail.WarehouseMaterialList = &warehouse_material_list
				}

			}

			detail_list[j] = detail
		}
		model.ChildrenList = &detail_list

		if model.ManagerId != nil && *model.ManagerId != 0 {
			manager := new(models.SysUser)
			manager.ID = model.ManagerId
			err = services.JdbcClient.GetJdbcModelById(manager)
			if err != nil {
				utils.PrintSqlErr(err)
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
			}
			model.ManagerName = manager.NickName
		}
		if model.CustomerId != nil && *model.CustomerId != "" {
			customer := new(models.Customer)
			customer.ID = model.CustomerId
			err = services.JdbcClient.GetJdbcModelById(customer)
			if err != nil {
				utils.PrintSqlErr(err)
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", err.Error()))
			}
			model.CustomerName = customer.Name
		}

		list[i] = model
	}
	result.Records = list
	return c.JSON(http.StatusOK, result)

}

func productPrePlanSave(c echo.Context) error {
	tx, _ := services.MYSQL_DB.Beginx()

	sess, _ := session.Get("auth_session", c)
	user_id, ok := sess.Values["user_id"].(int64)
	if !ok {
		return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("用户请先登录", ""))
	}

	planVo := new(models.ProductPrePlanVo)
	if err := c.Bind(planVo); err != nil {
		return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("参数解析失败", err.Error()))
	}

	sale_order := new(models.SaleOrder)
	sale_order.ID = planVo.SaleOrderId
	err := services.JdbcClient.GetJdbcModelById(sale_order, tx)
	if err != nil {
		utils.PrintSqlErr(err)
		tx.Rollback()
		return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
	}
	saleOrderStatus := models.Sale_Order_Status_Processing
	sale_order.Status = &saleOrderStatus
	err = services.JdbcClient.JdbcUpdateById(sale_order, tx)
	if err != nil {
		utils.PrintSqlErr(err)
		tx.Rollback()
		return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
	}

	product_plan_vo_list := *planVo.ProductPlanVoList

	if len(product_plan_vo_list) > 0 {
		plan_filter_list := utils.Filter(product_plan_vo_list, func(item models.ProductPlanVo) bool {
			return *item.PlanProductNumber > 0
		})
		plan_warehouse_filter_list := utils.Filter(product_plan_vo_list, func(item models.ProductPlanVo) bool {
			return len(*item.WarehouseMaterialVoList) > 0
		})
		product_plan := new(models.ProductPlan)
		if len(plan_filter_list) > 0 {
			product_plan.TenantId = sale_order.TenantId
			product_plan.SaleOrderId = sale_order.ID
			err_msg := productPlan_generateCode(product_plan, tx)
			if err_msg != "" {
				tx.Rollback()
				return c.JSON(http.StatusBadRequest, utils.ErrorResponse(err_msg, ""))
			}

			if planVo.ProductPlanName != nil && len(*planVo.ProductPlanName) > 0 {
				product_plan.Name = planVo.ProductPlanName
			} else {
				product_plan.Name = product_plan.Code
			}

			status := models.Product_Plan_Status_Pending
			product_plan.Status = &status
			product_plan.CreateId = &user_id
			product_plan.BeginDate = planVo.PlanBeginDate
			product_plan.EndDate = planVo.PlanEndDate
			err = services.JdbcClient.JdbcInsert(product_plan, tx)
			if err != nil {
				utils.PrintSqlErr(err)
				tx.Rollback()
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
			}
		}

		for _, detail := range plan_filter_list {
			product_plan_bom := new(models.ProductPlanBom)
			product_plan_bom.BomId = detail.BomId
			product_plan_bom.PlanId = product_plan.ID
			product_plan_bom.Number = detail.PlanProductNumber

			bom := new(models.ProductBom)
			bom.ID = detail.BomId
			err = services.JdbcClient.GetJdbcModelById(bom, tx)
			if err != nil {
				utils.PrintSqlErr(err)
				tx.Rollback()
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
			}
			product_plan_bom.RouteId = bom.RouteId

			route := new(models.ProcessRoute)
			route.ID = bom.RouteId
			err = services.JdbcClient.GetJdbcModelById(route, tx)
			if err != nil {
				utils.PrintSqlErr(err)
				tx.Rollback()
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
			}
			product_plan_bom.InspectProgramId = route.InspectProgramId

			err := services.JdbcClient.JdbcInsert(product_plan_bom, tx)
			if err != nil {
				utils.PrintSqlErr(err)
				tx.Rollback()
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
			}
		}
		for _, detail := range plan_warehouse_filter_list {

			warehouseMaterialVoList := *detail.WarehouseMaterialVoList
			for _, warehouseMaterial := range warehouseMaterialVoList {
				warehouse_record_model := new(models.WarehouseRecord)
				recordType := models.Warehouse_Record_Type_Lock
				warehouse_record_model.Type = &recordType
				warehouse_record_model.MaterialCode = detail.MaterialCode
				warehouse_record_model.Number = warehouseMaterial.LockedNumber
				warehouse_record_model.FromWarehouseId = warehouseMaterial.WarehouseId
				warehouse_record_model.TenantId = sale_order.TenantId
				warehouse_record_model.CreateId = &user_id
				recordRefType := models.Warehouse_Record_Ref_Type_Product
				warehouse_record_model.RefType = &recordRefType
				warehouse_record_model.RefId = product_plan.ID
				warehouse_record_model.SaleOrderId = sale_order.ID
				err := services.JdbcClient.JdbcInsert(warehouse_record_model, tx)
				if err != nil {
					utils.PrintSqlErr(err)
					tx.Rollback()
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
				}

				warehouse_material_model := new(models.WarehouseMaterial)
				warehouse_material_model.WarehouseId = warehouseMaterial.WarehouseId
				warehouse_material_model.MaterialCode = detail.MaterialCode
				err = services.JdbcClient.GetJdbcModel(warehouse_material_model, tx)
				if err != nil {
					utils.PrintSqlErr(err)
					tx.Rollback()
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
				}
				warehouseMaterialNumber := *warehouse_material_model.Number - *warehouseMaterial.LockedNumber
				warehouse_material_model.Number = &warehouseMaterialNumber
				warehouseMaterialLockedNumber := *warehouse_material_model.LockedNumber + *warehouseMaterial.LockedNumber
				warehouse_material_model.LockedNumber = &warehouseMaterialLockedNumber
				warehouse_material_model.UpdateId = &user_id
				err = services.JdbcClient.JdbcUpdateById(warehouse_material_model, tx)
				if err != nil {
					utils.PrintSqlErr(err)
					tx.Rollback()
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
				}

			}
		}
	}

	purchase_plan_vo_list := *planVo.PurchasePlanVoList
	if len(purchase_plan_vo_list) > 0 {
		plan_filter_list := utils.Filter(purchase_plan_vo_list, func(item models.PurchasePlanVo) bool {
			return *item.PlanPurchaseNumber > 0
		})
		warehouse_filter_list := utils.Filter(purchase_plan_vo_list, func(item models.PurchasePlanVo) bool {
			return len(*item.WarehouseMaterialVoList) > 0
		})

		purchase_plan := new(models.PurchasePlan)
		if len(plan_filter_list) > 0 {
			purchase_plan.TenantId = sale_order.TenantId
			err_msg := purchasePlan_generateCode(purchase_plan, tx)
			if err_msg != "" {
				tx.Rollback()
				return c.JSON(http.StatusBadRequest, utils.ErrorResponse(err_msg, ""))
			}
			if planVo.PurchasePlanName != nil && len(*planVo.PurchasePlanName) > 0 {
				purchase_plan.Name = planVo.PurchasePlanName
			} else {
				purchase_plan.Name = purchase_plan.Code
			}
			purchase_plan.SaleOrderId = planVo.SaleOrderId
			purchasePlanStatus := models.Purchase_Plan_Status_Pending
			purchase_plan.Status = &purchasePlanStatus
			purchase_plan.TenantId = sale_order.TenantId
			purchase_plan.BeginDate = planVo.PlanBeginDate
			purchase_plan.EndDate = planVo.PlanEndDate
			purchase_plan.CreateId = &user_id
			err := services.JdbcClient.JdbcInsert(purchase_plan, tx)
			if err != nil {
				utils.PrintSqlErr(err)
				tx.Rollback()
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
			}

		}

		for _, detail := range plan_filter_list {
			purchase_plan_detail := new(models.PurchasePlanDetail)
			purchase_plan_detail.MaterialCode = detail.MaterialCode
			purchase_plan_detail.PlanId = purchase_plan.ID
			purchase_plan_detail.Number = detail.PlanPurchaseNumber

			err := services.JdbcClient.JdbcInsert(purchase_plan_detail, tx)
			if err != nil {
				utils.PrintSqlErr(err)
				tx.Rollback()
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
			}
		}

		for _, detail := range warehouse_filter_list {
			warehouseMaterialVoList := *detail.WarehouseMaterialVoList
			for _, warehouseMaterial := range warehouseMaterialVoList {
				warehouse_record_model := new(models.WarehouseRecord)
				recordType := models.Warehouse_Record_Type_Lock
				warehouse_record_model.Type = &recordType
				warehouse_record_model.MaterialCode = detail.MaterialCode
				warehouse_record_model.Number = warehouseMaterial.LockedNumber
				warehouse_record_model.FromWarehouseId = warehouseMaterial.WarehouseId
				warehouse_record_model.TenantId = sale_order.TenantId
				warehouse_record_model.CreateId = &user_id
				recordRefType := models.Warehouse_Record_Ref_Type_Purchase
				warehouse_record_model.RefType = &recordRefType
				warehouse_record_model.RefId = purchase_plan.ID
				warehouse_record_model.SaleOrderId = sale_order.ID
				err := services.JdbcClient.JdbcInsert(warehouse_record_model, tx)
				if err != nil {
					utils.PrintSqlErr(err)
					tx.Rollback()
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
				}

				warehouse_material_model := new(models.WarehouseMaterial)
				warehouse_material_model.WarehouseId = warehouseMaterial.WarehouseId
				warehouse_material_model.MaterialCode = detail.MaterialCode
				err = services.JdbcClient.GetJdbcModel(warehouse_material_model, tx)
				if err != nil {
					utils.PrintSqlErr(err)
					tx.Rollback()
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
				}
				warehouseMaterialNumber := *warehouse_material_model.Number - *warehouseMaterial.LockedNumber
				warehouse_material_model.Number = &warehouseMaterialNumber
				warehouseMaterialLockedNumber := *warehouse_material_model.LockedNumber + *warehouseMaterial.LockedNumber
				warehouse_material_model.LockedNumber = &warehouseMaterialLockedNumber
				warehouse_material_model.UpdateId = &user_id
				err = services.JdbcClient.JdbcUpdateById(warehouse_material_model, tx)
				if err != nil {
					utils.PrintSqlErr(err)
					tx.Rollback()
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
				}

			}
		}
	}

	outsourcing_plan_vo_list := *planVo.OutsourcingPlanVoList
	if len(outsourcing_plan_vo_list) > 0 {
		plan_filter_list := utils.Filter(outsourcing_plan_vo_list, func(item models.OutsourcingPlanVo) bool {
			return *item.PlanOutsourcingNumber > 0
		})
		warehouse_filter_list := utils.Filter(outsourcing_plan_vo_list, func(item models.OutsourcingPlanVo) bool {
			return len(*item.WarehouseMaterialVoList) > 0
		})

		outsourcing_plan := new(models.OutsourcingPlan)
		if len(plan_filter_list) > 0 {
			outsourcing_plan.TenantId = sale_order.TenantId
			err_msg := outsourcingPlan_generateCode(outsourcing_plan, tx)
			if err_msg != "" {
				tx.Rollback()
				return c.JSON(http.StatusBadRequest, utils.ErrorResponse(err_msg, ""))
			}
			if planVo.OutsourcingPlanName != nil && len(*planVo.OutsourcingPlanName) > 0 {
				outsourcing_plan.Name = planVo.OutsourcingPlanName
			} else {
				outsourcing_plan.Name = outsourcing_plan.Code
			}
			outsourcing_plan.SaleOrderId = planVo.SaleOrderId
			purchasePlanStatus := models.Outsourcing_Plan_Status_Pending
			outsourcing_plan.Status = &purchasePlanStatus
			outsourcing_plan.TenantId = sale_order.TenantId
			outsourcing_plan.BeginDate = planVo.PlanBeginDate
			outsourcing_plan.EndDate = planVo.PlanEndDate
			outsourcing_plan.CreateId = &user_id
			err := services.JdbcClient.JdbcInsert(outsourcing_plan, tx)
			if err != nil {
				utils.PrintSqlErr(err)
				tx.Rollback()
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
			}
		}
		
		for _, detail := range plan_filter_list {
			outsourcing_plan_detail := new(models.OutsourcingPlanDetail)
			outsourcing_plan_detail.MaterialCode = detail.MaterialCode
			outsourcing_plan_detail.PlanId = outsourcing_plan.ID
			outsourcing_plan_detail.Number = detail.PlanOutsourcingNumber
			err := services.JdbcClient.JdbcInsert(outsourcing_plan_detail, tx)
			if err != nil {
				utils.PrintSqlErr(err)
				tx.Rollback()
				return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
			}
		}

		for _, detail := range warehouse_filter_list {
			warehouseMaterialVoList := *detail.WarehouseMaterialVoList
			for _, warehouseMaterial := range warehouseMaterialVoList {
				warehouse_record_model := new(models.WarehouseRecord)
				recordType := models.Warehouse_Record_Type_Lock
				warehouse_record_model.Type = &recordType
				warehouse_record_model.MaterialCode = detail.MaterialCode
				warehouse_record_model.Number = warehouseMaterial.LockedNumber
				warehouse_record_model.FromWarehouseId = warehouseMaterial.WarehouseId
				warehouse_record_model.TenantId = sale_order.TenantId
				warehouse_record_model.CreateId = &user_id
				recordRefType := models.Warehouse_Record_Ref_Type_Outsourcing
				warehouse_record_model.RefType = &recordRefType
				warehouse_record_model.RefId = outsourcing_plan.ID
				warehouse_record_model.SaleOrderId = sale_order.ID
				err := services.JdbcClient.JdbcInsert(warehouse_record_model, tx)
				if err != nil {
					utils.PrintSqlErr(err)
					tx.Rollback()
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
				}

				warehouse_material_model := new(models.WarehouseMaterial)
				warehouse_material_model.WarehouseId = warehouseMaterial.WarehouseId
				warehouse_material_model.MaterialCode = detail.MaterialCode
				err = services.JdbcClient.GetJdbcModel(warehouse_material_model, tx)
				if err != nil {
					utils.PrintSqlErr(err)
					tx.Rollback()
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
				}
				warehouseMaterialNumber := *warehouse_material_model.Number - *warehouseMaterial.LockedNumber
				warehouse_material_model.Number = &warehouseMaterialNumber
				warehouseMaterialLockedNumber := *warehouse_material_model.LockedNumber + *warehouseMaterial.LockedNumber
				warehouse_material_model.LockedNumber = &warehouseMaterialLockedNumber
				warehouse_material_model.UpdateId = &user_id
				err = services.JdbcClient.JdbcUpdateById(warehouse_material_model, tx)
				if err != nil {
					utils.PrintSqlErr(err)
					tx.Rollback()
					return c.JSON(http.StatusInternalServerError, utils.ErrorResponse("系统错误", ""))
				}

			}
		}
	}

	tx.Commit()
	return c.JSON(http.StatusOK, planVo)

}
