package core

import (
	"context"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/utils"
	"gorm.io/gorm"
)

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

func NewEditResourceSpecLogic(ctx context.Context, svcCtx *svc.ServiceContext) *EditResourceSpecLogic {
	return &EditResourceSpecLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}
func (l *EditResourceSpecLogic) EditResourceSpec(req *types.EditResourceReq) (resp *types.CommonResp, err error) {
	// 初始化事务
	tx := l.svcCtx.DbEngin.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
			panic(r)
		} else if err != nil {
			tx.Rollback()
		}
	}()

	// 1. 验证资源规格存在
	var existing models.TResourceSpec
	if err = tx.Model(&models.TResourceSpec{}).
		Where("id = ? AND deleted_at IS NULL", req.Id).
		First(&existing).
		Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.Errorf("资源规格不存在 (ID: %d)", req.Id)
		}
		return nil, errors.Wrapf(err, "查询资源规格失败 (ID: %d)", req.Id)
	}

	// 2. 参数校验
	if err = validateRequestParams(req); err != nil {
		return nil, err
	}

	// 3. 转换参数
	statusInt := utils.StringToInt64(req.Status)
	costPerUnit := utils.StringToFloat64(req.CostPerUnit)

	// 4. 更新主资源规格
	if err = updateMainResourceSpec(tx, req.Id, statusInt, req.CostType, costPerUnit, req.UserId); err != nil {
		return nil, err
	}

	// 5. 更新子资源规格
	if err = updateSubResources(tx, req); err != nil {
		return nil, err
	}

	// 提交事务
	if err = tx.Commit().Error; err != nil {
		return nil, errors.Wrap(err, "提交事务失败")
	}

	// 返回成功响应
	return resp, nil
}

// validateRequestParams 验证请求参数合法性
func validateRequestParams(req *types.EditResourceReq) error {
	// 状态校验
	if req.Status != "0" && req.Status != "1" {
		return errors.Errorf("资源规格状态不合法 (ID: %d)", req.Id)
	}

	// 计费类型校验
	validCostTypes := map[string]struct{}{
		"hourly":  {},
		"daily":   {},
		"monthly": {},
		"perUse":  {},
	}
	if _, ok := validCostTypes[req.CostType]; !ok {
		return errors.Errorf("资源规格计费类型不合法 (ID: %d)", req.Id)
	}

	return nil
}

// updateMainResourceSpec 更新主资源规格
func updateMainResourceSpec(tx *gorm.DB, id int64, status int64, costType string, costPerUnit float64, userId int64) error {
	return tx.Model(&models.TResourceSpec{}).
		Where("id = ?", id).
		Updates(map[string]interface{}{
			"status":        status,
			"cost_type":     costType,
			"cost_per_unit": costPerUnit,
			"user_id":       userId,
		}).
		Error
}

// updateSubResources 更新子资源规格
func updateSubResources(tx *gorm.DB, req *types.EditResourceReq) error {
	// 定义更新操作集合
	updateOperations := []struct {
		Value    string
		Unit     string
		SpecType string
		SpecName string
	}{
		{req.CpuValue, req.CpuUnit, "CPU", ""},
		{req.MemoryValue, req.MemoryUnit, "MEMORY", "RAM"},
		{req.StorageValue, req.StorageUnit, "STORAGE", ""},
	}

	// 批量执行更新操作
	for _, op := range updateOperations {
		if op.Value == "" && op.Unit == "" {
			continue
		}

		if err := updateBaseResourceSpec(tx, req.Id, op.SpecType, op.SpecName, op.Value, op.Unit); err != nil {
			return errors.Wrapf(err, "更新%s规格失败 (ID: %d)", op.SpecType, req.Id)
		}
	}
	return nil
}

// updateBaseResourceSpec 通用基础资源规格更新函数
func updateBaseResourceSpec(tx *gorm.DB, specID int64, specType string, specName string, value, unit string) error {
	updates := make(map[string]interface{})
	if value != "" {
		updates["total_value"] = value
	}
	if unit != "" {
		updates["total_unit"] = unit
	}
	if len(updates) == 0 {
		return nil
	}

	query := tx.Model(&models.TBaseResourceSpec{}).
		Where("resource_spec_id = ? AND type = ?", specID, specType)

	if specName != "" {
		query = query.Where("name = ?", specName)
	}

	if err := query.Updates(updates).Error; err != nil {
		return errors.Wrapf(err, "更新%s规格失败", specType)
	}
	return nil
}
