package role

import (
	"github.com/veypi/vbase/cfg"
	"github.com/veypi/vbase/models"
	"github.com/veypi/vigo"
)

type PatchReq struct {
	ID          string  `src:"path@id" desc:"Role ID"`
	Name        *string `json:"name" src:"json" desc:"Role Name"`
	Code        *string `json:"code" src:"json" desc:"Role Code"`
	Scope       *string `json:"scope" src:"json" desc:"Scope"`
	Description *string `json:"description" src:"json" desc:"Role Description"`
	Status      *int    `json:"status" src:"json" desc:"Status"`
}

func patch(x *vigo.X, req *PatchReq) (*models.Role, error) {
	var role models.Role
	if err := cfg.DB().First(&role, "id = ?", req.ID).Error; err != nil {
		return nil, vigo.ErrNotFound
	}

	if role.IsSystem {
		return nil, vigo.NewError("cannot modify system role").WithCode(40300)
	}

	updates := map[string]interface{}{}

	// Check if code is being updated
	if req.Code != nil {
		newCode := *req.Code

		// Check for uniqueness if changed
		if newCode != role.Code {
			var count int64
			if err := cfg.DB().Model(&models.Role{}).Where("code = ? AND id != ?", newCode, role.ID).Count(&count).Error; err != nil {
				return nil, vigo.ErrInternalServer.WithError(err)
			}
			if count > 0 {
				return nil, vigo.ErrAlreadyExists.WithArgs("Role Code")
			}
			updates["code"] = newCode
		}
	}

	if req.Name != nil {
		updates["name"] = *req.Name
	}
	if req.Description != nil {
		updates["description"] = *req.Description
	}
	if req.Status != nil {
		updates["status"] = *req.Status
	}

	if len(updates) > 0 {
		if err := cfg.DB().Model(&role).Updates(updates).Error; err != nil {
			return nil, vigo.ErrDatabase.WithError(err)
		}
	}

	return &role, nil
}
