package usecase import ( "fmt" "time" "users_management/m/model/dto/req" "users_management/m/model/dto/res" "users_management/m/model/entity" "users_management/m/repository" "users_management/m/utils/helper" "github.com/go-playground/validator/v10" "github.com/google/uuid" ) type BackboneUseCase interface { CreateBackbone(backbone req.BackboneDTO) error GetAllBackbone() ([]res.BackboneResponse, error) GetByID(id uuid.UUID) (res.BackboneResponse, error) UpdateBackbone(id uuid.UUID, backbone req.UpdateBackboneDTO) error } type backboneUseCase struct { backboneRepo repository.BackboneRepo fishboneRepo repository.FishboneRepo validate *validator.Validate deviceDetailsRepo repository.DeviceDetailsRepo // Add this field } func NewBackboneUseCase(backboneRepo repository.BackboneRepo, fishboneRepo repository.FishboneRepo, deviceDetailsRepo repository.DeviceDetailsRepo) BackboneUseCase { return &backboneUseCase{ backboneRepo: backboneRepo, fishboneRepo: fishboneRepo, deviceDetailsRepo: deviceDetailsRepo, // Initialize the field validate: validator.New(), } } func (u *backboneUseCase) CreateBackbone(backbone req.BackboneDTO) error { err := u.validate.Struct(backbone) if err != nil { return fmt.Errorf("validation error: %w", err) } // Validate that both devices exist and are OTB type startExists, err := u.deviceDetailsRepo.CheckDeviceExists(backbone.DeviceStartID) if err != nil { return fmt.Errorf("error checking start device: %w", err) } if !startExists { return fmt.Errorf("start device does not exist") } endExists, err := u.deviceDetailsRepo.CheckDeviceExists(backbone.DeviceEndID) if err != nil { return fmt.Errorf("error checking end device: %w", err) } if !endExists { return fmt.Errorf("end device does not exist") } // Validate port availability (each backbone connection uses 1 port) if err := u.deviceDetailsRepo.ValidatePortAvailability(backbone.DeviceStartID, 1); err != nil { return fmt.Errorf("start device: %w", err) } if err := u.deviceDetailsRepo.ValidatePortAvailability(backbone.DeviceEndID, 1); err != nil { return fmt.Errorf("end device: %w", err) } newBackbone := entity.Backbone{ ID: uuid.New(), BackboneCode: backbone.BackboneCode, DeviceStartID: backbone.DeviceStartID, DeviceEndID: backbone.DeviceEndID, CoreAmount: backbone.CoreAmount, CreatedAt: time.Now(), UpdatedAt: time.Now(), } // Create backbone err = u.backboneRepo.Post(newBackbone) if err != nil { return err } // Update port usage for both devices u.deviceDetailsRepo.UpdateDevicePortUsage(backbone.DeviceStartID) u.deviceDetailsRepo.UpdateDevicePortUsage(backbone.DeviceEndID) return nil } func (u *backboneUseCase) GetAllBackbone() ([]res.BackboneResponse, error) { backbones, err := u.backboneRepo.GetAll() if err != nil { return nil, err } totalFishbone,err := u.fishboneRepo.CountFishbone() if err != nil { return nil, err } backboneResp, err := helper.ConvertToBackboneResponses(backbones,totalFishbone) if err != nil { return nil, err } return backboneResp, nil } func (u *backboneUseCase) GetByID(id uuid.UUID) (res.BackboneResponse, error) { backbone, err := u.backboneRepo.GetByID(id) if err != nil { return res.BackboneResponse{}, err } fishboneCount, err := u.fishboneRepo.CountFishboneByBackboneID(backbone.ID) if err != nil { return res.BackboneResponse{}, err } backboneResp, err := helper.ConvertToBackboneRespId(backbone,fishboneCount) if err != nil { return res.BackboneResponse{}, err } return backboneResp, nil } func (u *backboneUseCase) UpdateBackbone(id uuid.UUID, backbone req.UpdateBackboneDTO) error { err := u.validate.Struct(backbone) if err != nil { return fmt.Errorf("validation error: %w", err) } // Get original backbone to track changes originalBackbone, err := u.backboneRepo.GetByID(id) if err != nil { return err } updates := make(map[string]interface{}) // Track devices that need port recalculation devicesToUpdate := make(map[uuid.UUID]bool) devicesToUpdate[originalBackbone.DeviceStartID] = true devicesToUpdate[originalBackbone.DeviceEndID] = true if backbone.DeviceStartID != nil { // Validate new start device exists and has available ports exists, err := u.deviceDetailsRepo.CheckDeviceExists(*backbone.DeviceStartID) if err != nil { return fmt.Errorf("error checking new start device: %w", err) } if !exists { return fmt.Errorf("new start device does not exist") } if err := u.deviceDetailsRepo.ValidatePortAvailability(*backbone.DeviceStartID, 1); err != nil { return fmt.Errorf("new start device: %w", err) } updates["dev_start_id"] = *backbone.DeviceStartID devicesToUpdate[*backbone.DeviceStartID] = true } if backbone.DeviceEndID != nil { // Validate new end device exists and has available ports exists, err := u.deviceDetailsRepo.CheckDeviceExists(*backbone.DeviceEndID) if err != nil { return fmt.Errorf("error checking new end device: %w", err) } if !exists { return fmt.Errorf("new end device does not exist") } if err := u.deviceDetailsRepo.ValidatePortAvailability(*backbone.DeviceEndID, 1); err != nil { return fmt.Errorf("new end device: %w", err) } updates["dev_end_id"] = *backbone.DeviceEndID devicesToUpdate[*backbone.DeviceEndID] = true } if backbone.CoreAmount != nil { updates["core_amount"] = *backbone.CoreAmount } if len(updates) == 0 { return fmt.Errorf("no fields to update") } updates["updated_at"] = time.Now() // Update backbone err = u.backboneRepo.Update(id, updates) if err != nil { return err } // Recalculate port usage for all affected devices for deviceID := range devicesToUpdate { u.deviceDetailsRepo.UpdateDevicePortUsage(deviceID) } return nil }