'use strict'; const mdl_TierCategories = require('../../models/tiers/tier_categories.mdl'); const mdl_TierPlans = require('../../models/tiers/tier_plans.mdl'); const Asset = require('../../models/assets/assets.mdl'); const R = require('../../utils/response.util'); const logActivity = require('../../utils/logActivity.util'); require('../../models/tiers/tier.associations'); const ASSET_ATTRS = ['asset_id', 'file_url', 'display_name', 'mime_type']; const withBadge = [{ model: Asset, as: 'badgeAsset', attributes: ASSET_ATTRS, required: false }]; // ─── GET /admin/tiers/categories ───────────────────────────────────────────── exports.getCategories = async (req, res) => { try { const categories = await mdl_TierCategories.findAll({ include: withBadge, order: [['rank', 'ASC']], }); return R.success(res, 'Subscription categories retrieved.', categories); } catch (err) { console.error('[ADMIN][GET TIER CATEGORIES]', err); return R.error(res, 'Could not retrieve subscription categories.', 500); } }; // ─── GET /admin/tiers/categories/:id ───────────────────────────────────────── exports.getCategory = async (req, res) => { try { const cat = await mdl_TierCategories.findByPk(req.params.id, { include: withBadge }); if (!cat) return R.error(res, 'Subscription category not found.', 404); return R.success(res, 'Subscription category retrieved.', cat); } catch (err) { console.error('[ADMIN][GET TIER CATEGORY]', err); return R.error(res, 'Could not retrieve subscription category.', 500); } }; // ─── POST /admin/tiers/categories ──────────────────────────────────────────── exports.createCategory = async (req, res) => { try { const { slug, name, description, rank, color, badge_asset_id, badge_icon, badge_label, is_special } = req.body; if (!slug || !name) return R.error(res, 'slug and name are required.', 400); const parsedRank = Number(rank ?? 1); if (parsedRank <= 0) return R.error(res, 'Non-default subscription categories must have rank greater than 0.', 400); const exists = await mdl_TierCategories.findOne({ where: { slug } }); if (exists) return R.error(res, `A subscription category with slug "${slug}" already exists.`, 409); const cat = await mdl_TierCategories.create({ slug, name, description: description ?? null, rank: parsedRank, color: color || 'purple', badge_asset_id: badge_asset_id || null, badge_icon: badge_icon || null, badge_label: badge_label ?? null, is_default: false, is_active: true, is_special: !!is_special, }); logActivity(req.user?.user_id, 'create_tier_category', { entityType: 'tier_category', details: { slug, name } }); const result = await mdl_TierCategories.findByPk(cat.tier_category_id, { include: withBadge }); return R.success(res, 'Subscription category created.', result, 201); } catch (err) { console.error('[ADMIN][CREATE TIER CATEGORY]', err); return R.error(res, 'Could not create subscription category.', 500); } }; // ─── PUT /admin/tiers/categories/:id ───────────────────────────────────────── exports.updateCategory = async (req, res) => { try { const cat = await mdl_TierCategories.findByPk(req.params.id); if (!cat) return R.error(res, 'Subscription category not found.', 404); const { name, description, rank, color, badge_asset_id, badge_icon, badge_label, is_active, is_special } = req.body; if (!cat.is_default && rank !== undefined) { const parsedRank = Number(rank); if (parsedRank <= 0) return R.error(res, 'Non-default subscription categories must have rank greater than 0.', 400); } await cat.update({ name: name ?? cat.name, description: description !== undefined ? (description || null) : cat.description, rank: rank !== undefined ? Number(rank) : cat.rank, color: color !== undefined ? (color || cat.color) : cat.color, badge_asset_id: badge_asset_id !== undefined ? (badge_asset_id || null) : cat.badge_asset_id, badge_icon: badge_icon !== undefined ? (badge_icon || null) : cat.badge_icon, badge_label: badge_label !== undefined ? (badge_label || null) : cat.badge_label, // Default category (free) cannot be deactivated is_active: (!cat.is_default && is_active !== undefined) ? is_active : cat.is_active, is_special: is_special !== undefined ? !!is_special : cat.is_special, }); logActivity(req.user?.user_id, 'update_tier_category', { entityType: 'tier_category', details: { id: cat.tier_category_id, slug: cat.slug } }); const result = await mdl_TierCategories.findByPk(cat.tier_category_id, { include: withBadge }); return R.success(res, 'Subscription category updated.', result); } catch (err) { console.error('[ADMIN][UPDATE TIER CATEGORY]', err); return R.error(res, 'Could not update subscription category.', 500); } }; // ─── DELETE /admin/tiers/categories/:id ────────────────────────────────────── exports.deleteCategory = async (req, res) => { try { const cat = await mdl_TierCategories.findByPk(req.params.id); if (!cat) return R.error(res, 'Subscription category not found.', 404); if (cat.is_default) return R.error(res, 'The default (Free) subscription category cannot be deleted.', 400); // Block deletion if active plans still reference this category const activePlans = await mdl_TierPlans.count({ where: { tier_category_id: cat.tier_category_id, is_active: true }, }); if (activePlans > 0) return R.error(res, `Cannot delete — ${activePlans} active plan(s) belong to this category. Archive or reassign them first.`, 409); await cat.destroy(); logActivity(req.user?.user_id, 'delete_tier_category', { entityType: 'tier_category', details: { slug: cat.slug } }); return R.success(res, 'Subscription category deleted.'); } catch (err) { console.error('[ADMIN][DELETE TIER CATEGORY]', err); return R.error(res, 'Could not delete subscription category.', 500); } };