const mongoose = require('mongoose'); const CourseModel = require('../models/CourseModel'); const AcademyModel = require('../models/AcademyModel'); const ProjectModel = require('../models/ProjectModel'); const AdvertisingModel = require('../models/AdvertisingModel'); const ShopModel = require('../models/ShopModel'); const ShopProductListingModel = require('../models/ShopProductListingModel'); const BookingConfigModel = require('../models/BookingConfigModel'); const { PUBLIC_COURSE_STATUSES, PUBLIC_BILLBOARD_STATUSES, PUBLIC_PROJECT_STATUSES, } = require('./moderationStatus'); function sameId(a, b) { if (a == null || b == null) return false; const sa = typeof a === 'object' && a._id != null ? String(a._id) : String(a); const sb = typeof b === 'object' && b._id != null ? String(b._id) : String(b); return sa === sb; } // اعتبارسنجی مشترک «آیتم قابل‌لینک‌شدن» // options.requirePublic (پیش‌فرض true): برای لینک داخل پست/استوری وضعیت عمومی لازم است. // برای صفحه «اشتراک‌گذاری لینک» فقط مالکیت کافی است (requirePublic: false). async function resolveLinkedEntity(kind, id, userId, options = {}) { const requirePublic = options.requirePublic !== false; if (!id || !mongoose.Types.ObjectId.isValid(id)) return null; switch (kind) { case 'pkg': { const course = await CourseModel.findById(id) .select('_id user_id academyId status') .lean(); if (!course) return null; if (requirePublic && !PUBLIC_COURSE_STATUSES.includes(course.status)) return null; // مالکیت: user_id مستقیم روی دوره، یا مالک آکادمیِ دوره if (sameId(course.user_id, userId)) return String(course._id); if (course.academyId) { const academy = await AcademyModel.findById(course.academyId).select('userId').lean(); if (academy && sameId(academy.userId, userId)) return String(course._id); } return null; } case 'project': { const project = await ProjectModel.findById(id) .select('_id creator_id status') .lean(); if (!project) return null; if (requirePublic && !PUBLIC_PROJECT_STATUSES.includes(project.status)) return null; if (sameId(project.creator_id, userId)) return String(project._id); return null; } case 'billboard': { const ad = await AdvertisingModel.findById(id) .select('_id creator_id status') .lean(); if (!ad) return null; if (requirePublic && !PUBLIC_BILLBOARD_STATUSES.includes(ad.status)) return null; if (sameId(ad.creator_id, userId)) return String(ad._id); return null; } case 'shop': { const shop = await ShopModel.findById(id).select('_id owner status').lean(); if (!shop) return null; if (requirePublic && !['active', 'pending_review'].includes(shop.status)) return null; if (sameId(shop.owner, userId)) return String(shop._id); return null; } case 'shopproduct': { const listing = await ShopProductListingModel.findById(id) .select('_id shop status') .lean(); if (!listing) return null; if (requirePublic && !['active', 'pending_shop_approval'].includes(listing.status)) { return null; } const shop = await ShopModel.findById(listing.shop).select('_id owner').lean(); if (shop && sameId(shop.owner, userId)) return String(listing._id); return null; } case 'booking': { // ref_id برای رزرو = userId مالک کانفیگ (نه _id خودِ BookingConfig) if (!sameId(id, userId)) return null; const query = requirePublic ? { owner: userId, status: 'active' } : { owner: userId }; const config = await BookingConfigModel.findOne(query).select('_id').lean(); return config ? String(userId) : null; } default: return null; } } module.exports = { resolveLinkedEntity };