import type { Model, Types, DeleteResult } from 'mongoose'; import type { IAgentCategory, AgentCategory } from '../types/agentCategory'; export function createAgentCategoryMethods(mongoose: typeof import('mongoose')) { /** * Get all active categories sorted by order * @returns Array of active categories */ async function getActiveCategories(): Promise { const AgentCategory = mongoose.models.AgentCategory as Model; return await AgentCategory.find({ isActive: true }).sort({ order: 1, label: 1 }).lean(); } /** * Get categories with agent counts * @returns Categories with agent counts */ async function getCategoriesWithCounts(): Promise<(IAgentCategory & { agentCount: number })[]> { const Agent = mongoose.models.Agent; const categoryCounts = await Agent.aggregate([ { $match: { category: { $exists: true, $ne: null } } }, { $group: { _id: '$category', count: { $sum: 1 } } }, ]); const countMap = new Map(categoryCounts.map((c) => [c._id, c.count])); const categories = await getActiveCategories(); return categories.map((category) => ({ ...category, agentCount: countMap.get(category.value) || (0 as number), })) as (IAgentCategory & { agentCount: number })[]; } /** * Get valid category values for Agent model validation * @returns Array of valid category values */ async function getValidCategoryValues(): Promise { const AgentCategory = mongoose.models.AgentCategory as Model; return await AgentCategory.find({ isActive: true }).distinct('value').lean(); } /** * Seed initial categories from existing constants * @param categories - Array of category data to seed * @returns Bulk write result */ async function seedCategories( categories: Array<{ value: string; label?: string; description?: string; order?: number; }>, ): Promise { const AgentCategory = mongoose.models.AgentCategory as Model; const operations = categories.map((category, index) => ({ updateOne: { filter: { value: category.value }, update: { $setOnInsert: { value: category.value, label: category.label || category.value, description: category.description || '', order: category.order || index, isActive: true, }, }, upsert: true, }, })); return await AgentCategory.bulkWrite(operations); } /** * Find a category by value * @param value - The category value to search for * @returns The category document or null */ async function findCategoryByValue(value: string): Promise { const AgentCategory = mongoose.models.AgentCategory as Model; return await AgentCategory.findOne({ value }).lean(); } /** * Create a new category * @param categoryData - The category data to create * @returns The created category */ async function createCategory(categoryData: Partial): Promise { const AgentCategory = mongoose.models.AgentCategory as Model; const category = await AgentCategory.create(categoryData); return category.toObject() as IAgentCategory; } /** * Update a category by value * @param value - The category value to update * @param updateData - The data to update * @returns The updated category or null */ async function updateCategory( value: string, updateData: Partial, ): Promise { const AgentCategory = mongoose.models.AgentCategory as Model; return await AgentCategory.findOneAndUpdate( { value }, { $set: updateData }, { new: true, runValidators: true }, ).lean(); } /** * Delete a category by value * @param value - The category value to delete * @returns Whether the deletion was successful */ async function deleteCategory(value: string): Promise { const AgentCategory = mongoose.models.AgentCategory as Model; const result = await AgentCategory.deleteOne({ value }); return result.deletedCount > 0; } /** * Find a category by ID * @param id - The category ID to search for * @returns The category document or null */ async function findCategoryById(id: string | Types.ObjectId): Promise { const AgentCategory = mongoose.models.AgentCategory as Model; return await AgentCategory.findById(id).lean(); } /** * Get all categories (active and inactive) * @returns Array of all categories */ async function getAllCategories(): Promise { const AgentCategory = mongoose.models.AgentCategory as Model; return await AgentCategory.find({}).sort({ order: 1, label: 1 }).lean(); } return { getActiveCategories, getCategoriesWithCounts, getValidCategoryValues, seedCategories, findCategoryByValue, createCategory, updateCategory, deleteCategory, findCategoryById, getAllCategories, }; } export type AgentCategoryMethods = ReturnType;