const mongoose = require('mongoose');

// ============================================================================
// Translation Model
// Stores translations for any translatable field in any model
// 
// Design Pattern: Separate Translation Collection
// - Keeps main models clean and unchanged
// - Supports unlimited languages
// - Easy to add new translatable fields
// - Efficient querying with proper indexes
// ============================================================================

const translationSchema = new mongoose.Schema({
    // Reference to the document being translated
    refId: {
        type: mongoose.Schema.Types.ObjectId,
        required: [true, 'Reference ID is required'],
        index: true
    },

    // Model name (e.g., 'FAQ', 'Banner', 'VehicleGroup', 'Zone')
    refModel: {
        type: String,
        required: [true, 'Reference model is required'],
        index: true,
        enum: [
            'FAQ',
            'Banner',
            'Footer',
            'Zone',
            'VehicleGroup',
            'VehicleCategory',
            'AirportRoute',
            'IntercityRoute',
            'CityTaxi',
            'Setting'
        ]
    },

    // Language code (e.g., 'hi', 'fr', 'de', 'ar', 'es')
    // Note: 'en' is the default/source language stored in main documents
    language: {
        type: String,
        required: [true, 'Language code is required'],
        lowercase: true,
        trim: true,
        index: true
    },

    // Translations stored as key-value pairs
    // Key = field path (e.g., 'question', 'title', 'description', 'faqs.0.question')
    // Value = translated text
    translations: {
        type: Map,
        of: String,
        required: true
    },

    // Translation status
    status: {
        type: String,
        enum: ['draft', 'published', 'needs_review'],
        default: 'published'
    },

    // Who created/updated this translation
    createdBy: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    },
    updatedBy: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    }
}, {
    timestamps: true,
    // Ensure we don't have duplicate translations for same doc+model+lang
    collection: 'translations'
});

// Compound unique index: one translation per document per language
translationSchema.index(
    { refId: 1, refModel: 1, language: 1 },
    { unique: true }
);

// Index for efficient language-based queries
translationSchema.index({ refModel: 1, language: 1 });

// ============================================================================
// Static Methods
// ============================================================================

/**
 * Get translations for a document
 * @param {ObjectId} refId - Document ID
 * @param {String} refModel - Model name
 * @param {String} language - Target language
 * @returns {Map|null} - Translations map or null
 */
translationSchema.statics.getTranslation = async function (refId, refModel, language) {
    if (!language || language === 'en') return null; // English is source

    const translation = await this.findOne({
        refId,
        refModel,
        language,
        status: 'published'
    }).lean();

    return translation?.translations || null;
};

/**
 * Get translations for multiple documents at once (batch query)
 * @param {Array<ObjectId>} refIds - Array of document IDs
 * @param {String} refModel - Model name
 * @param {String} language - Target language
 * @returns {Map<String, Map>} - Map of refId -> translations
 */
translationSchema.statics.getBulkTranslations = async function (refIds, refModel, language) {
    if (!language || language === 'en') return new Map();

    const translations = await this.find({
        refId: { $in: refIds },
        refModel,
        language,
        status: 'published'
    }).lean();

    const result = new Map();
    translations.forEach(t => {
        result.set(t.refId.toString(), t.translations);
    });

    return result;
};

/**
 * Upsert translation for a document
 * @param {ObjectId} refId - Document ID
 * @param {String} refModel - Model name
 * @param {String} language - Target language
 * @param {Object} translations - Key-value translations
 * @param {ObjectId} userId - Who is updating
 */
translationSchema.statics.upsertTranslation = async function (refId, refModel, language, translations, userId = null) {
    return this.findOneAndUpdate(
        { refId, refModel, language },
        {
            $set: {
                translations: new Map(Object.entries(translations)),
                status: 'published',
                updatedBy: userId
            },
            $setOnInsert: {
                createdBy: userId
            }
        },
        { upsert: true, new: true }
    );
};

/**
 * Delete all translations for a document
 * @param {ObjectId} refId - Document ID
 * @param {String} refModel - Model name
 */
translationSchema.statics.deleteAllForDocument = async function (refId, refModel) {
    return this.deleteMany({ refId, refModel });
};

/**
 * Get all available translations for a document
 * @param {ObjectId} refId - Document ID
 * @param {String} refModel - Model name
 * @returns {Array} - Array of translations with language codes
 */
translationSchema.statics.getAllTranslations = async function (refId, refModel) {
    return this.find({ refId, refModel }).lean();
};

const Translation = mongoose.model('Translation', translationSchema);

module.exports = Translation;
