package company

import (
	"context"
	"errors"
	"time"
	"tm/pkg/logger"
	"tm/pkg/mongo"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

// Repository defines the interface for company data operations
type Repository interface {
	Create(ctx context.Context, company *Company) error
	GetByID(ctx context.Context, id string) (*Company, error)
	GetByName(ctx context.Context, name string) (*Company, error)
	GetByRegistrationNumber(ctx context.Context, registrationNumber string) (*Company, error)
	GetByTaxID(ctx context.Context, taxID string) (*Company, error)
	GetByIDs(ctx context.Context, ids []string) ([]*Company, error)
	Update(ctx context.Context, company *Company) error
	Delete(ctx context.Context, id string) error
	List(ctx context.Context, limit, offset int) ([]*Company, error)
	Search(ctx context.Context, search string, companyType *string, status *string, industry *string, isVerified *bool, isCompliant *bool, language *string, currency *string, cpvCodes []string, categories []string, keywords []string, specializations []string, employeeCountMin *int, employeeCountMax *int, annualRevenueMin *float64, annualRevenueMax *float64, foundedYearMin *int, foundedYearMax *int, limit, offset int, sortBy, sortOrder string) ([]*Company, error)
	Count(ctx context.Context) (int64, error)
	CountByType(ctx context.Context, companyType CompanyType) (int64, error)
	CountByStatus(ctx context.Context, status CompanyStatus) (int64, error)
	CountByIndustry(ctx context.Context, industry string) (int64, error)
	CountVerified(ctx context.Context) (int64, error)
	UpdateStatus(ctx context.Context, id string, status CompanyStatus) error
	UpdateVerification(ctx context.Context, id string, isVerified, isCompliant bool, complianceNotes *string) error
	UpdateTags(ctx context.Context, id string, tags *CompanyTags) error
	AddTags(ctx context.Context, id string, cpvCodes []string, categories []string, keywords []string, specializations []string, certifications []string) error
	RemoveTags(ctx context.Context, id string, cpvCodes []string, categories []string, keywords []string, specializations []string, certifications []string) error
	GetCompanyStats(ctx context.Context) (*CompanyStatsResponse, error)
	SearchByTags(ctx context.Context, cpvCodes []string, categories []string, keywords []string, specializations []string, limit, offset int) ([]*Company, error)
}

// companyRepository implements the Repository interface using the MongoDB ORM
type companyRepository struct {
	ormRepo mongo.Repository[Company]
	logger  logger.Logger
}

// NewCompanyRepository creates a new company repository
func NewCompanyRepository(mongoManager *mongo.ConnectionManager, logger logger.Logger) Repository {
	// Create indexes using the ORM's index management
	indexes := []mongo.Index{
		*mongo.CreateUniqueIndex("name_idx", bson.D{{Key: "name", Value: 1}}),
		*mongo.CreateUniqueIndex("registration_number_idx", bson.D{{Key: "registration_number", Value: 1}}),
		*mongo.CreateUniqueIndex("tax_id_idx", bson.D{{Key: "tax_id", Value: 1}}),
		*mongo.NewIndex("type_idx", bson.D{{Key: "type", Value: 1}}),
		*mongo.NewIndex("status_idx", bson.D{{Key: "status", Value: 1}}),
		*mongo.NewIndex("industry_idx", bson.D{{Key: "industry", Value: 1}}),
		*mongo.NewIndex("is_verified_idx", bson.D{{Key: "is_verified", Value: 1}}),
		*mongo.NewIndex("is_compliant_idx", bson.D{{Key: "is_compliant", Value: 1}}),
		*mongo.NewIndex("language_idx", bson.D{{Key: "language", Value: 1}}),
		*mongo.NewIndex("currency_idx", bson.D{{Key: "currency", Value: 1}}),
		*mongo.NewIndex("employee_count_idx", bson.D{{Key: "employee_count", Value: 1}}),
		*mongo.NewIndex("annual_revenue_idx", bson.D{{Key: "annual_revenue", Value: 1}}),
		*mongo.NewIndex("founded_year_idx", bson.D{{Key: "founded_year", Value: 1}}),
		*mongo.NewIndex("created_at_idx", bson.D{{Key: "created_at", Value: -1}}),
		// Tag indexes for efficient search
		*mongo.NewIndex("cpv_codes_idx", bson.D{{Key: "tags.cpv_codes", Value: 1}}),
		*mongo.NewIndex("categories_idx", bson.D{{Key: "tags.categories", Value: 1}}),
		*mongo.NewIndex("keywords_idx", bson.D{{Key: "tags.keywords", Value: 1}}),
		*mongo.NewIndex("specializations_idx", bson.D{{Key: "tags.specializations", Value: 1}}),
		*mongo.NewIndex("certifications_idx", bson.D{{Key: "tags.certifications", Value: 1}}),
		// Text index for search
		*mongo.CreateTextIndex("search_idx", "name", "description", "industry"),
	}

	// Create indexes
	err := mongoManager.CreateIndexes("companies", indexes)
	if err != nil {
		logger.Warn("Failed to create company indexes", map[string]interface{}{
			"error": err.Error(),
		})
	}

	// Create ORM repository
	ormRepo := mongo.NewRepository[Company](mongoManager.GetCollection("companies"), logger)

	return &companyRepository{
		ormRepo: ormRepo,
		logger:  logger,
	}
}

// Create creates a new company
func (r *companyRepository) Create(ctx context.Context, company *Company) error {
	// Set created/updated timestamps using Unix timestamps
	now := time.Now().Unix()
	company.SetCreatedAt(now)
	company.SetUpdatedAt(now)

	// Use ORM to create company
	err := r.ormRepo.Create(ctx, company)
	if err != nil {
		r.logger.Error("Failed to create company", map[string]interface{}{
			"error":               err.Error(),
			"name":                company.Name,
			"registration_number": company.RegistrationNumber,
		})
		return err
	}

	r.logger.Info("Company created successfully", map[string]interface{}{
		"company_id": company.ID,
		"name":       company.Name,
		"type":       company.Type,
	})

	return nil
}

// GetByID retrieves a company by ID
func (r *companyRepository) GetByID(ctx context.Context, id string) (*Company, error) {
	company, err := r.ormRepo.FindByID(ctx, id)
	if err != nil {
		if errors.Is(err, mongo.ErrDocumentNotFound) {
			return nil, errors.New("company not found")
		}
		r.logger.Error("Failed to get company by ID", map[string]interface{}{
			"error":      err.Error(),
			"company_id": id,
		})
		return nil, err
	}

	return company, nil
}

// GetByName retrieves a company by name
func (r *companyRepository) GetByName(ctx context.Context, name string) (*Company, error) {
	filter := bson.M{"name": name}
	company, err := r.ormRepo.FindOne(ctx, filter)
	if err != nil {
		if errors.Is(err, mongo.ErrDocumentNotFound) {
			return nil, errors.New("company not found")
		}
		r.logger.Error("Failed to get company by name", map[string]interface{}{
			"error": err.Error(),
			"name":  name,
		})
		return nil, err
	}

	return company, nil
}

// GetByRegistrationNumber retrieves a company by registration number
func (r *companyRepository) GetByRegistrationNumber(ctx context.Context, registrationNumber string) (*Company, error) {
	filter := bson.M{"registration_number": registrationNumber}
	company, err := r.ormRepo.FindOne(ctx, filter)
	if err != nil {
		if errors.Is(err, mongo.ErrDocumentNotFound) {
			return nil, errors.New("company not found")
		}
		r.logger.Error("Failed to get company by registration number", map[string]interface{}{
			"error":               err.Error(),
			"registration_number": registrationNumber,
		})
		return nil, err
	}

	return company, nil
}

// GetByTaxID retrieves a company by tax ID
func (r *companyRepository) GetByTaxID(ctx context.Context, taxID string) (*Company, error) {
	filter := bson.M{"tax_id": taxID}
	company, err := r.ormRepo.FindOne(ctx, filter)
	if err != nil {
		if errors.Is(err, mongo.ErrDocumentNotFound) {
			return nil, errors.New("company not found")
		}
		r.logger.Error("Failed to get company by tax ID", map[string]interface{}{
			"error":  err.Error(),
			"tax_id": taxID,
		})
		return nil, err
	}

	return company, nil
}

// GetByIDs retrieves multiple companies by their IDs
func (r *companyRepository) GetByIDs(ctx context.Context, ids []string) ([]*Company, error) {
	if len(ids) == 0 {
		return []*Company{}, nil
	}

	// Convert string IDs to ObjectIDs for MongoDB query
	objectIDs := make([]interface{}, len(ids))
	for i, id := range ids {
		objectID, err := primitive.ObjectIDFromHex(id)
		if err != nil {
			r.logger.Warn("Invalid company ID format", map[string]interface{}{
				"id":    id,
				"error": err.Error(),
			})
			continue
		}
		objectIDs[i] = objectID
	}

	if len(objectIDs) == 0 {
		return []*Company{}, nil
	}

	filter := bson.M{"_id": bson.M{"$in": objectIDs}}
	companies, err := r.ormRepo.FindMany(ctx, filter, len(ids))
	if err != nil {
		r.logger.Error("Failed to get companies by IDs", map[string]interface{}{
			"error": err.Error(),
			"ids":   ids,
		})
		return nil, err
	}

	// Convert to pointer slice
	result := make([]*Company, len(companies))
	for i := range companies {
		result[i] = &companies[i]
	}

	r.logger.Info("Retrieved companies by IDs", map[string]interface{}{
		"requested_count": len(ids),
		"found_count":     len(result),
	})

	return result, nil
}

// Update updates a company
func (r *companyRepository) Update(ctx context.Context, company *Company) error {
	// Set updated timestamp using Unix timestamp
	company.SetUpdatedAt(time.Now().Unix())

	// Use ORM to update company
	err := r.ormRepo.Update(ctx, company)
	if err != nil {
		r.logger.Error("Failed to update company", map[string]interface{}{
			"error":      err.Error(),
			"company_id": company.ID,
		})
		return err
	}

	r.logger.Info("Company updated successfully", map[string]interface{}{
		"company_id": company.ID,
		"name":       company.Name,
	})

	return nil
}

// Delete deletes a company (soft delete by setting status to inactive)
func (r *companyRepository) Delete(ctx context.Context, id string) error {
	// Get company first
	company, err := r.GetByID(ctx, id)
	if err != nil {
		return err
	}

	// Update status to inactive
	company.Status = CompanyStatusInactive
	company.SetUpdatedAt(time.Now().Unix())

	// Update in database
	err = r.ormRepo.Update(ctx, company)
	if err != nil {
		r.logger.Error("Failed to delete company", map[string]interface{}{
			"error":      err.Error(),
			"company_id": id,
		})
		return err
	}

	r.logger.Info("Company deleted successfully", map[string]interface{}{
		"company_id": id,
	})

	return nil
}

// List retrieves companies with pagination
func (r *companyRepository) List(ctx context.Context, limit, offset int) ([]*Company, error) {
	// Build pagination
	pagination := mongo.NewPaginationBuilder().
		Limit(limit).
		Skip(offset).
		SortDesc("created_at").
		Build()

	// Only active companies by default
	filter := bson.M{"status": bson.M{"$ne": CompanyStatusInactive}}

	// Use ORM to find companies
	result, err := r.ormRepo.FindAll(ctx, filter, pagination)
	if err != nil {
		r.logger.Error("Failed to list companies", map[string]interface{}{
			"error":  err.Error(),
			"limit":  limit,
			"offset": offset,
		})
		return nil, err
	}

	// Convert []Company to []*Company
	companies := make([]*Company, len(result.Items))
	for i := range result.Items {
		companies[i] = &result.Items[i]
	}

	return companies, nil
}

// Search retrieves companies with search and filters
func (r *companyRepository) Search(ctx context.Context, search string, companyType *string, status *string, industry *string, isVerified *bool, isCompliant *bool, language *string, currency *string, cpvCodes []string, categories []string, keywords []string, specializations []string, employeeCountMin *int, employeeCountMax *int, annualRevenueMin *float64, annualRevenueMax *float64, foundedYearMin *int, foundedYearMax *int, limit, offset int, sortBy, sortOrder string) ([]*Company, error) {
	// Build filter
	filter := bson.M{}

	if search != "" {
		filter["$text"] = bson.M{"$search": search}
	}

	if companyType != nil {
		filter["type"] = *companyType
	}

	if status != nil {
		filter["status"] = *status
	}

	if industry != nil {
		filter["industry"] = *industry
	}

	if isVerified != nil {
		filter["is_verified"] = *isVerified
	}

	if isCompliant != nil {
		filter["is_compliant"] = *isCompliant
	}

	if language != nil {
		filter["language"] = *language
	}

	if currency != nil {
		filter["currency"] = *currency
	}

	// Tag filters
	if len(cpvCodes) > 0 {
		filter["tags.cpv_codes"] = bson.M{"$in": cpvCodes}
	}

	if len(categories) > 0 {
		filter["tags.categories"] = bson.M{"$in": categories}
	}

	if len(keywords) > 0 {
		filter["tags.keywords"] = bson.M{"$in": keywords}
	}

	if len(specializations) > 0 {
		filter["tags.specializations"] = bson.M{"$in": specializations}
	}

	// Range filters
	if employeeCountMin != nil || employeeCountMax != nil {
		rangeFilter := bson.M{}
		if employeeCountMin != nil {
			rangeFilter["$gte"] = *employeeCountMin
		}
		if employeeCountMax != nil {
			rangeFilter["$lte"] = *employeeCountMax
		}
		filter["employee_count"] = rangeFilter
	}

	if annualRevenueMin != nil || annualRevenueMax != nil {
		rangeFilter := bson.M{}
		if annualRevenueMin != nil {
			rangeFilter["$gte"] = *annualRevenueMin
		}
		if annualRevenueMax != nil {
			rangeFilter["$lte"] = *annualRevenueMax
		}
		filter["annual_revenue"] = rangeFilter
	}

	if foundedYearMin != nil || foundedYearMax != nil {
		rangeFilter := bson.M{}
		if foundedYearMin != nil {
			rangeFilter["$gte"] = *foundedYearMin
		}
		if foundedYearMax != nil {
			rangeFilter["$lte"] = *foundedYearMax
		}
		filter["founded_year"] = rangeFilter
	}

	// Build pagination
	pagination := mongo.NewPaginationBuilder().
		Limit(limit).
		Skip(offset)

	// Set sort
	if sortBy != "" {
		if sortOrder == "desc" {
			pagination.SortDesc(sortBy)
		} else {
			pagination.SortAsc(sortBy)
		}
	} else {
		pagination.SortDesc("created_at") // Default sort
	}

	// Use ORM to find companies
	result, err := r.ormRepo.FindAll(ctx, filter, pagination.Build())
	if err != nil {
		r.logger.Error("Failed to search companies", map[string]interface{}{
			"error":  err.Error(),
			"search": search,
		})
		return nil, err
	}

	// Convert []Company to []*Company
	companies := make([]*Company, len(result.Items))
	for i := range result.Items {
		companies[i] = &result.Items[i]
	}

	return companies, nil
}

// Count counts all companies
func (r *companyRepository) Count(ctx context.Context) (int64, error) {
	filter := bson.M{"status": bson.M{"$ne": CompanyStatusInactive}}

	count, err := r.ormRepo.Count(ctx, filter)
	if err != nil {
		r.logger.Error("Failed to count companies", map[string]interface{}{
			"error": err.Error(),
		})
		return 0, err
	}

	return count, nil
}

// CountByType counts companies by type
func (r *companyRepository) CountByType(ctx context.Context, companyType CompanyType) (int64, error) {
	filter := bson.M{
		"type":   companyType,
		"status": bson.M{"$ne": CompanyStatusInactive},
	}

	count, err := r.ormRepo.Count(ctx, filter)
	if err != nil {
		r.logger.Error("Failed to count companies by type", map[string]interface{}{
			"error":        err.Error(),
			"company_type": companyType,
		})
		return 0, err
	}

	return count, nil
}

// CountByStatus counts companies by status
func (r *companyRepository) CountByStatus(ctx context.Context, status CompanyStatus) (int64, error) {
	filter := bson.M{"status": status}

	count, err := r.ormRepo.Count(ctx, filter)
	if err != nil {
		r.logger.Error("Failed to count companies by status", map[string]interface{}{
			"error":  err.Error(),
			"status": status,
		})
		return 0, err
	}

	return count, nil
}

// CountByIndustry counts companies by industry
func (r *companyRepository) CountByIndustry(ctx context.Context, industry string) (int64, error) {
	filter := bson.M{
		"industry": industry,
		"status":   bson.M{"$ne": CompanyStatusInactive},
	}

	count, err := r.ormRepo.Count(ctx, filter)
	if err != nil {
		r.logger.Error("Failed to count companies by industry", map[string]interface{}{
			"error":    err.Error(),
			"industry": industry,
		})
		return 0, err
	}

	return count, nil
}

// CountVerified counts verified companies
func (r *companyRepository) CountVerified(ctx context.Context) (int64, error) {
	filter := bson.M{
		"is_verified": true,
		"status":      bson.M{"$ne": CompanyStatusInactive},
	}

	count, err := r.ormRepo.Count(ctx, filter)
	if err != nil {
		r.logger.Error("Failed to count verified companies", map[string]interface{}{
			"error": err.Error(),
		})
		return 0, err
	}

	return count, nil
}

// UpdateStatus updates company status
func (r *companyRepository) UpdateStatus(ctx context.Context, id string, status CompanyStatus) error {
	// Get company first
	company, err := r.GetByID(ctx, id)
	if err != nil {
		return err
	}

	// Update status
	company.Status = status
	company.SetUpdatedAt(time.Now().Unix())

	// Update in database
	err = r.ormRepo.Update(ctx, company)
	if err != nil {
		r.logger.Error("Failed to update company status", map[string]interface{}{
			"error":      err.Error(),
			"company_id": id,
			"status":     status,
		})
		return err
	}

	r.logger.Info("Company status updated successfully", map[string]interface{}{
		"company_id": id,
		"status":     status,
	})

	return nil
}

// UpdateVerification updates company verification status
func (r *companyRepository) UpdateVerification(ctx context.Context, id string, isVerified, isCompliant bool, complianceNotes *string) error {
	// Get company first
	company, err := r.GetByID(ctx, id)
	if err != nil {
		return err
	}

	// Update verification fields
	company.IsVerified = isVerified
	company.IsCompliant = isCompliant
	company.ComplianceNotes = complianceNotes
	company.SetUpdatedAt(time.Now().Unix())

	// Update in database
	err = r.ormRepo.Update(ctx, company)
	if err != nil {
		r.logger.Error("Failed to update company verification", map[string]interface{}{
			"error":      err.Error(),
			"company_id": id,
		})
		return err
	}

	r.logger.Info("Company verification updated successfully", map[string]interface{}{
		"company_id":   id,
		"is_verified":  isVerified,
		"is_compliant": isCompliant,
	})

	return nil
}

// UpdateTags updates company tags
func (r *companyRepository) UpdateTags(ctx context.Context, id string, tags *CompanyTags) error {
	// Get company first
	company, err := r.GetByID(ctx, id)
	if err != nil {
		return err
	}

	// Update tags
	company.Tags = tags
	company.SetUpdatedAt(time.Now().Unix())

	// Update in database
	err = r.ormRepo.Update(ctx, company)
	if err != nil {
		r.logger.Error("Failed to update company tags", map[string]interface{}{
			"error":      err.Error(),
			"company_id": id,
		})
		return err
	}

	r.logger.Info("Company tags updated successfully", map[string]interface{}{
		"company_id": id,
	})

	return nil
}

// AddTags adds tags to a company
func (r *companyRepository) AddTags(ctx context.Context, id string, cpvCodes []string, categories []string, keywords []string, specializations []string, certifications []string) error {
	// Get company first
	company, err := r.GetByID(ctx, id)
	if err != nil {
		return err
	}

	// Initialize tags if nil
	if company.Tags == nil {
		company.Tags = &CompanyTags{}
	}

	// Add tags (avoiding duplicates)
	company.Tags.CPVCodes = r.addUniqueStrings(company.Tags.CPVCodes, cpvCodes)
	company.Tags.Categories = r.addUniqueStrings(company.Tags.Categories, categories)
	company.Tags.Keywords = r.addUniqueStrings(company.Tags.Keywords, keywords)
	company.Tags.Specializations = r.addUniqueStrings(company.Tags.Specializations, specializations)
	company.Tags.Certifications = r.addUniqueStrings(company.Tags.Certifications, certifications)

	company.SetUpdatedAt(time.Now().Unix())

	// Update in database
	err = r.ormRepo.Update(ctx, company)
	if err != nil {
		r.logger.Error("Failed to add tags to company", map[string]interface{}{
			"error":      err.Error(),
			"company_id": id,
		})
		return err
	}

	r.logger.Info("Tags added to company successfully", map[string]interface{}{
		"company_id": id,
	})

	return nil
}

// RemoveTags removes tags from a company
func (r *companyRepository) RemoveTags(ctx context.Context, id string, cpvCodes []string, categories []string, keywords []string, specializations []string, certifications []string) error {
	// Get company first
	company, err := r.GetByID(ctx, id)
	if err != nil {
		return err
	}

	// Initialize tags if nil
	if company.Tags == nil {
		company.Tags = &CompanyTags{}
	}

	// Remove tags
	company.Tags.CPVCodes = r.removeStrings(company.Tags.CPVCodes, cpvCodes)
	company.Tags.Categories = r.removeStrings(company.Tags.Categories, categories)
	company.Tags.Keywords = r.removeStrings(company.Tags.Keywords, keywords)
	company.Tags.Specializations = r.removeStrings(company.Tags.Specializations, specializations)
	company.Tags.Certifications = r.removeStrings(company.Tags.Certifications, certifications)

	company.SetUpdatedAt(time.Now().Unix())

	// Update in database
	err = r.ormRepo.Update(ctx, company)
	if err != nil {
		r.logger.Error("Failed to remove tags from company", map[string]interface{}{
			"error":      err.Error(),
			"company_id": id,
		})
		return err
	}

	r.logger.Info("Tags removed from company successfully", map[string]interface{}{
		"company_id": id,
	})

	return nil
}

// GetCompanyStats returns company statistics
func (r *companyRepository) GetCompanyStats(ctx context.Context) (*CompanyStatsResponse, error) {
	// This would typically use aggregation pipelines for better performance
	// For now, we'll use basic counts

	totalCompanies, _ := r.Count(ctx)
	activeCompanies, _ := r.CountByStatus(ctx, CompanyStatusActive)
	verifiedCompanies, _ := r.CountVerified(ctx)

	// For this implementation, we'll return basic stats
	// In a real implementation, you'd use MongoDB aggregation pipelines
	stats := &CompanyStatsResponse{
		TotalCompanies:      totalCompanies,
		ActiveCompanies:     activeCompanies,
		VerifiedCompanies:   verifiedCompanies,
		CompaniesByType:     make(map[string]int64),
		CompaniesByIndustry: make(map[string]int64),
		CompaniesByStatus:   make(map[string]int64),
		TopCategories:       []CategoryCount{},
		TopCPVCodes:         []CPVCodeCount{},
	}

	return stats, nil
}

// SearchByTags searches companies by tags
func (r *companyRepository) SearchByTags(ctx context.Context, cpvCodes []string, categories []string, keywords []string, specializations []string, limit, offset int) ([]*Company, error) {
	filter := bson.M{}

	// Build tag filters
	var tagFilters []bson.M

	if len(cpvCodes) > 0 {
		tagFilters = append(tagFilters, bson.M{"tags.cpv_codes": bson.M{"$in": cpvCodes}})
	}

	if len(categories) > 0 {
		tagFilters = append(tagFilters, bson.M{"tags.categories": bson.M{"$in": categories}})
	}

	if len(keywords) > 0 {
		tagFilters = append(tagFilters, bson.M{"tags.keywords": bson.M{"$in": keywords}})
	}

	if len(specializations) > 0 {
		tagFilters = append(tagFilters, bson.M{"tags.specializations": bson.M{"$in": specializations}})
	}

	if len(tagFilters) > 0 {
		filter["$or"] = tagFilters
	}

	// Only active companies
	filter["status"] = bson.M{"$ne": CompanyStatusInactive}

	// Build pagination
	pagination := mongo.NewPaginationBuilder().
		Limit(limit).
		Skip(offset).
		SortDesc("created_at").
		Build()

	// Use ORM to find companies
	result, err := r.ormRepo.FindAll(ctx, filter, pagination)
	if err != nil {
		r.logger.Error("Failed to search companies by tags", map[string]interface{}{
			"error": err.Error(),
		})
		return nil, err
	}

	// Convert []Company to []*Company
	companies := make([]*Company, len(result.Items))
	for i := range result.Items {
		companies[i] = &result.Items[i]
	}

	return companies, nil
}

// Helper functions for tag management
func (r *companyRepository) addUniqueStrings(existing []string, new []string) []string {
	existingMap := make(map[string]bool)
	for _, s := range existing {
		existingMap[s] = true
	}

	result := make([]string, len(existing))
	copy(result, existing)

	for _, s := range new {
		if !existingMap[s] {
			result = append(result, s)
			existingMap[s] = true
		}
	}

	return result
}

func (r *companyRepository) removeStrings(existing []string, toRemove []string) []string {
	removeMap := make(map[string]bool)
	for _, s := range toRemove {
		removeMap[s] = true
	}

	var result []string
	for _, s := range existing {
		if !removeMap[s] {
			result = append(result, s)
		}
	}

	return result
}
