package logic

import (
	"encoding/json"
	"errors"
	"fmt"
	"fusenapi/model/gmodel"
	"fusenapi/utils/auth"
	"fusenapi/utils/basic"
	"strings"
	"time"

	"gorm.io/gorm"

	"context"

	"fusenapi/server/product-model/internal/svc"
	"fusenapi/server/product-model/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type UpdateProductModelLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewUpdateProductModelLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateProductModelLogic {
	return &UpdateProductModelLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *UpdateProductModelLogic) UpdateProductModel(req *types.UpdateProductModelReq, userInfo *auth.BackendUserInfo) (resp *basic.Response) {
	if req.ModelData.Id <= 0 {
		return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "modelData`s id is required")
	}
	//查询模型信息
	productModel3dInfo, err := l.svcCtx.AllModels.FsProductModel3d.FindOne(l.ctx, req.ModelData.Id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "3d model info is not exists")
		}
		logx.Error(err)
		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product 3d model info")
	}
	lightInfoBytes, _ := json.Marshal(req.LightData.Info)
	lightInfoJson := string(lightInfoBytes)
	modelLightSaveData := gmodel.FsProductModel3dLight{
		Name: &req.LightData.Name,
		Info: &lightInfoJson,
	}
	//开启事务
	tx := l.svcCtx.MysqlConn.Begin()
	lightModel := gmodel.NewFsProductModel3dLightModel(tx)
	productModel3dModel := gmodel.NewFsProductModel3dModel(tx)
	now := time.Now().UTC().Unix()
	if req.LightData.Id > 0 { //更新
		modelLightSaveData.Id = req.LightData.Id
		err = lightModel.Update(l.ctx, req.LightData.Id, &modelLightSaveData)
	} else { //添加
		modelLightSaveData.Ctime = &now
		err = lightModel.Create(l.ctx, &modelLightSaveData)
	}
	if err != nil {
		logx.Error(err)
		tx.Rollback()
		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to save light info")
	}
	partListStr := ""
	for _, v := range req.ModelData.PartsList {
		partListStr += fmt.Sprintf("%d,", v)
		partListStr = strings.TrimRight(partListStr, ",")
	}
	//赋值
	req.ModelData.LightData = modelLightSaveData.Id
	//目前1个模型只有1组灯光
	req.ModelData.LightList = []int64{modelLightSaveData.Id}
	modelInfoBytes, _ := json.Marshal(req.ModelData)
	modelInfoJson := string(modelInfoBytes)
	lightIdsBytes, _ := json.Marshal([]int64{modelLightSaveData.Id})
	lightIdsStr := string(lightIdsBytes)
	modelSaveData := gmodel.FsProductModel3d{
		Name:      productModel3dInfo.Name,
		ModelInfo: &modelInfoJson,
		Light:     &modelLightSaveData.Id,
		LightList: &lightIdsStr,
		PartId:    &req.ModelData.Parts,
		PartList:  &partListStr,
	}
	if err = productModel3dModel.Update(l.ctx, req.ModelData.Id, &modelSaveData); err != nil {
		logx.Error(err)
		tx.Rollback()
		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to save model info")
	}
	tx.Commit()
	return resp.SetStatusWithMessage(basic.CodeOK, "success", types.UpdateProductModelRsp{
		ModelId:   productModel3dInfo.Id,
		LightId:   modelLightSaveData.Id,
		LightList: []int64{modelLightSaveData.Id},
	})
}