const mongoose = require('mongoose');
const slugify = require('slugify');

const CategorySchema = new mongoose.Schema({
    name: {
        type: String,
        required: [true, 'Please add a category name'],
        unique: true,
        trim: true,
        maxlength: [50, 'Name cannot be more than 50 characters']
    },
    slug: {
        type: String,
        unique: true
    },
    description: {
        type: String,
        required: [true, 'Please add a description'],
        maxlength: [500, 'Description cannot be more than 500 characters']
    },
    image: {
        type: String,
        default: 'no-image.jpg'
    },
    parent: {
        type: mongoose.Schema.ObjectId,
        ref: 'Category',
        default: null
    },
    level: {
        type: Number,
        default: 1
    },
    path: [{
        type: mongoose.Schema.ObjectId,
        ref: 'Category'
    }],
    isActive: {
        type: Boolean,
        default: true
    },
    order: {
        type: Number,
        default: 0
    },
    createdAt: {
        type: Date,
        default: Date.now
    }
}, {
    toJSON: { virtuals: true },
    toObject: { virtuals: true }
});

// Create category slug from the name
CategorySchema.pre('save', function(next) {
    this.slug = slugify(this.name, { lower: true });
    next();
});

// Virtual for subcategories
CategorySchema.virtual('subcategories', {
    ref: 'Category',
    localField: '_id',
    foreignField: 'parent',
    justOne: false
});

// Update level and path before saving
CategorySchema.pre('save', async function(next) {
    if (this.isModified('parent')) {
        if (this.parent) {
            const parentCategory = await this.constructor.findById(this.parent);
            if (parentCategory) {
                this.level = parentCategory.level + 1;
                this.path = [...parentCategory.path, parentCategory._id];
            }
        } else {
            this.level = 1;
            this.path = [];
        }
    }
    next();
});

// Cascade delete subcategories when a category is deleted
CategorySchema.pre('remove', async function(next) {
    await this.model('Category').deleteMany({ parent: this._id });
    next();
});

// Static method to get category tree
CategorySchema.statics.getCategoryTree = async function() {
    const categories = await this.find()
        .populate('parent', 'name')
        .populate('path', 'name')
        .sort({ level: 1, order: 1, name: 1 });

    const buildTree = (items, parentId = null) => {
        return items
            .filter(item => item.parent?._id?.toString() === parentId?.toString())
            .map(item => ({
                ...item.toObject(),
                children: buildTree(items, item._id)
            }));
    };

    return buildTree(categories);
};

// Static method to get breadcrumbs
CategorySchema.statics.getBreadcrumbs = async function(categoryId) {
    const category = await this.findById(categoryId)
        .populate('path', 'name slug');
    
    if (!category) return null;

    return [
        ...category.path.map(cat => ({
            name: cat.name,
            slug: cat.slug
        })),
        {
            name: category.name,
            slug: category.slug
        }
    ];
};

module.exports = mongoose.model('Category', CategorySchema); 