package service import ( "context" "fmt" "time" "bugulma/backend/internal/domain" "github.com/google/uuid" ) type VerificationService struct { trustService *TrustService orgService *OrganizationService } func NewVerificationService(trustService *TrustService, orgService *OrganizationService) *VerificationService { return &VerificationService{ trustService: trustService, orgService: orgService, } } type VerificationQueueFilters struct { Status *domain.VerificationStatus DataType *string OrganizationID *string } // GetVerificationQueue retrieves organizations pending verification func (s *VerificationService) GetVerificationQueue(ctx context.Context, filters VerificationQueueFilters) ([]*domain.VerifiedData, error) { // Get all pending verifications verifiedDataList, err := s.trustService.GetPendingVerifications(ctx) if err != nil { return nil, fmt.Errorf("failed to get pending verifications: %w", err) } // Apply filters var filtered []*domain.VerifiedData for _, vd := range verifiedDataList { if filters.Status != nil && vd.Status != *filters.Status { continue } if filters.DataType != nil && vd.DataType != *filters.DataType { continue } if filters.OrganizationID != nil && vd.OrganizationID != *filters.OrganizationID { continue } filtered = append(filtered, vd) } return filtered, nil } // VerifyOrganization verifies an organization func (s *VerificationService) VerifyOrganization(ctx context.Context, orgID string, verifiedBy string, notes string) error { // Create verified data entry for organization now := time.Now() verifiedData := &domain.VerifiedData{ ID: uuid.New().String(), OrganizationID: orgID, DataType: "organization", DataID: orgID, Status: domain.VerificationVerified, VerifiedBy: verifiedBy, VerifiedAt: &now, Notes: notes, } if err := s.trustService.VerifyData(ctx, verifiedData.ID, verifiedBy, notes); err != nil { // If verified data doesn't exist, create it if err := s.trustService.SubmitForVerification(ctx, verifiedData); err != nil { return fmt.Errorf("failed to submit for verification: %w", err) } // Now verify it if err := s.trustService.VerifyData(ctx, verifiedData.ID, verifiedBy, notes); err != nil { return fmt.Errorf("failed to verify: %w", err) } } // Update organization verified status org, err := s.orgService.GetByID(ctx, orgID) if err != nil { return fmt.Errorf("failed to get organization: %w", err) } org.Verified = true if err := s.orgService.Update(ctx, org); err != nil { return fmt.Errorf("failed to update organization: %w", err) } return nil } // RejectVerification rejects an organization verification func (s *VerificationService) RejectVerification(ctx context.Context, orgID string, reason string, notes string) error { // Get existing verified data for this organization orgVerifications, err := s.trustService.GetVerifiedDataByOrganization(ctx, orgID) if err != nil { return fmt.Errorf("failed to get verifications: %w", err) } var verifiedData *domain.VerifiedData for _, vd := range orgVerifications { if vd.DataType == "organization" && vd.DataID == orgID { verifiedData = vd break } } if verifiedData == nil { // Create new verified data entry verifiedData = &domain.VerifiedData{ ID: uuid.New().String(), OrganizationID: orgID, DataType: "organization", DataID: orgID, Status: domain.VerificationRejected, Notes: fmt.Sprintf("Reason: %s. Notes: %s", reason, notes), } if err := s.trustService.SubmitForVerification(ctx, verifiedData); err != nil { return fmt.Errorf("failed to create verification entry: %w", err) } } else { // Update existing verifiedData.Status = domain.VerificationRejected verifiedData.Notes = fmt.Sprintf("Reason: %s. Notes: %s", reason, notes) if err := s.trustService.UpdateVerifiedData(ctx, verifiedData); err != nil { return fmt.Errorf("failed to update verification: %w", err) } } return nil } // BulkVerify verifies multiple organizations func (s *VerificationService) BulkVerify(ctx context.Context, orgIDs []string, verifiedBy string) error { for _, orgID := range orgIDs { if err := s.VerifyOrganization(ctx, orgID, verifiedBy, "Bulk verification"); err != nil { return fmt.Errorf("failed to verify organization %s: %w", orgID, err) } } return nil } // GetVerificationStats retrieves verification statistics func (s *VerificationService) GetVerificationStats(ctx context.Context) (map[string]interface{}, error) { // Get all verifications allVerifications, err := s.trustService.GetAllVerifications(ctx) if err != nil { return nil, fmt.Errorf("failed to get verifications: %w", err) } stats := map[string]interface{}{ "total": len(allVerifications), "pending": 0, "verified": 0, "rejected": 0, "unverified": 0, "average_time_days": 0, } var totalDays int64 var verifiedCount int for _, vd := range allVerifications { switch vd.Status { case domain.VerificationPending: stats["pending"] = stats["pending"].(int) + 1 case domain.VerificationVerified: stats["verified"] = stats["verified"].(int) + 1 if vd.VerifiedAt != nil { // Calculate days from verification time (simplified - would need creation time from elsewhere) verifiedCount++ } case domain.VerificationRejected: stats["rejected"] = stats["rejected"].(int) + 1 case domain.VerificationUnverified: stats["unverified"] = stats["unverified"].(int) + 1 } } if verifiedCount > 0 { stats["average_time_days"] = float64(totalDays) / float64(verifiedCount) } return stats, nil }