"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const models_1 = require("../users/models");
const models_2 = require("./models");
const models_3 = require("../reels/models");
const models_4 = require("../likes/models");
const models_5 = require("../super-likes/models");
const services_1 = __importDefault(require("../../utils/services"));
const mongoose_1 = require("mongoose");
const promises_1 = __importDefault(require("fs/promises"));
const path_1 = __importDefault(require("path"));
function getComments(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        var _a, _b, _c;
        try {
            let { reel, parent, limit = '10', page = '1' } = req.query;
            limit = +limit;
            page = +page;
            const match = Object.assign({ reel: new mongoose_1.Types.ObjectId(reel) }, (parent
                ? { parent: new mongoose_1.Types.ObjectId(parent) }
                : { parent: { $exists: false } }));
            const pipeline = [
                { $match: match },
                { $sort: { superLike: -1, likes: -1, createdAt: -1 } },
                {
                    $facet: {
                        comments: [
                            { $skip: (page - 1) * limit },
                            { $limit: limit },
                            // populate root user
                            {
                                $lookup: {
                                    from: 'users',
                                    localField: 'user',
                                    foreignField: '_id',
                                    as: 'user'
                                }
                            },
                            { $unwind: '$user' },
                            // ✅ Total replies count (only if no parent filter)
                            ...(!parent ? [
                                {
                                    $lookup: {
                                        from: 'comments',
                                        let: { commentId: '$_id' },
                                        pipeline: [
                                            {
                                                $match: {
                                                    $expr: { $eq: ['$parent', '$$commentId'] }
                                                }
                                            },
                                            { $count: 'count' }
                                        ],
                                        as: 'subComments'
                                    }
                                },
                                {
                                    $addFields: {
                                        totalReplies: {
                                            $ifNull: [{ $arrayElemAt: ['$subComments.count', 0] }, 0]
                                        }
                                    }
                                },
                                { $project: { subComments: 0 } }
                            ] : []),
                            {
                                $project: {
                                    reel: 1,
                                    parent: 1,
                                    superLike: 1,
                                    likes: 1,
                                    createdAt: 1,
                                    updatedAt: 1,
                                    totalReplies: 1,
                                    'user._id': 1,
                                    'user.name': 1,
                                    'user.username': 1,
                                    'user.photo': 1,
                                    data: 1
                                }
                            },
                            // populate data.user one by one
                            {
                                $addFields: {
                                    data: {
                                        $map: {
                                            input: '$data',
                                            as: 'd',
                                            in: {
                                                $cond: [
                                                    { $ifNull: ['$$d.user', false] },
                                                    {
                                                        $mergeObjects: [
                                                            '$$d',
                                                            {
                                                                user: {
                                                                    $let: {
                                                                        vars: { userId: '$$d.user' },
                                                                        in: {
                                                                            $first: {
                                                                                $map: {
                                                                                    input: {
                                                                                        $filter: {
                                                                                            input: {
                                                                                                $concatArrays: [
                                                                                                    ['$ROOT.user'],
                                                                                                ]
                                                                                            },
                                                                                            as: 'dummy',
                                                                                            cond: false
                                                                                        }
                                                                                    },
                                                                                    as: 'filtered',
                                                                                    in: '$$filtered'
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        ]
                                                    },
                                                    '$$d'
                                                ]
                                            }
                                        }
                                    }
                                }
                            },
                            // populate data.user after mapping
                            {
                                $lookup: {
                                    from: 'users',
                                    let: { dataArray: '$data' },
                                    pipeline: [
                                        {
                                            $match: {
                                                $expr: { $in: ['$_id', { $map: { input: '$$dataArray', as: 'd', in: '$$d.user' } }] }
                                            }
                                        },
                                        {
                                            $project: { _id: 1, name: 1, username: 1, photo: 1 }
                                        }
                                    ],
                                    as: 'dataUsers'
                                }
                            },
                            {
                                $addFields: {
                                    data: {
                                        $map: {
                                            input: '$data',
                                            as: 'd',
                                            in: {
                                                $cond: [
                                                    { $ifNull: ['$$d.user', false] },
                                                    {
                                                        $mergeObjects: [
                                                            '$$d',
                                                            {
                                                                user: {
                                                                    $arrayElemAt: [
                                                                        {
                                                                            $filter: {
                                                                                input: '$dataUsers',
                                                                                as: 'u',
                                                                                cond: { $eq: ['$$u._id', '$$d.user'] }
                                                                            }
                                                                        },
                                                                        0
                                                                    ]
                                                                }
                                                            }
                                                        ]
                                                    },
                                                    '$$d'
                                                ]
                                            }
                                        }
                                    }
                                }
                            },
                            { $project: { dataUsers: 0 } },
                            { $sort: { superLike: -1, likes: -1, createdAt: -1 } }
                        ],
                        totalCount: [{ $count: 'count' }]
                    }
                }
            ];
            const result = yield models_2.Comment.aggregate(pipeline);
            const comments = ((_a = result[0]) === null || _a === void 0 ? void 0 : _a.comments) || [];
            const count = ((_c = (_b = result[0]) === null || _b === void 0 ? void 0 : _b.totalCount[0]) === null || _c === void 0 ? void 0 : _c.count) || 0;
            return res.json({ comments, count });
        }
        catch (error) {
            console.error(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postComment(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const user = res.locals.user;
            const { reel: reelId, parent, data } = req.body;
            let userIds = data.filter(e => e.user).map(e => e.user);
            userIds = [...new Set(userIds)];
            if (userIds.length) {
                const users = (yield models_1.User.find({ _id: { $in: userIds } }, { _id: 1 })).map(e => `${e._id}`);
                for (const u of userIds) {
                    if (!users.includes(u)) {
                        return res.status(404).json({ message: `A user with _id ${u} not found` });
                    }
                }
            }
            const reel = yield models_3.Reel.findById(reelId).populate('user');
            if (!reel) {
                return res.status(404).json({ message: 'reel not found' });
            }
            let parentComment;
            if (parent) {
                // @ts-ignore
                parentComment = yield models_2.Comment.findOne({
                    _id: parent,
                    reel: reel._id,
                    parent: { $exists: false }
                }).populate('user');
                if (!parentComment) {
                    return res.status(404).json({ message: 'parent comment not found' });
                }
            }
            const superLike = yield models_5.SuperLike.findOne({
                reel: reel._id,
                user: user._id
            });
            const _comment = yield models_2.Comment.create({
                user: user._id,
                reel: reel._id,
                parent,
                data,
                superLike: superLike === null || superLike === void 0 ? void 0 : superLike._id,
            });
            const count = yield models_2.Comment.countDocuments({ reel: reel._id });
            reel.comments = count;
            yield reel.save();
            const comment = (yield models_2.Comment.findById(_comment._id)
                .populate({ path: 'user', select: { name: 1, username: 1, photo: 1 } })
                .populate({ path: 'data.user', select: { name: 1, username: 1, photo: 1 } }));
            let notification1, notification2;
            if (`${reel.user._id}` !== `${user._id}`) {
                notification1 = yield services_1.default.notifyUser({
                    title: 'New comment posted on your vibe',
                    description: `${user.username} commented on your vibe`,
                    event: 'comment-created',
                    user: reel.user,
                    comment: comment._id,
                    from: user._id,
                    reel: reel._id
                });
            }
            if (parentComment && `${parentComment.user._id}` !== `${user._id}`) {
                notification2 = yield services_1.default.notifyUser({
                    title: 'New reply on your comment',
                    description: `${user.username} replied on your comment`,
                    event: 'comment-created',
                    // @ts-ignore
                    user: parentComment.user,
                    comment: comment._id,
                    from: user._id,
                    reel: reel._id
                });
            }
            // AI prompt to get comment properties
            ;
            (() => __awaiter(this, void 0, void 0, function* () {
                var _a;
                try {
                    const systemPrompt = yield promises_1.default.readFile(path_1.default.join(__dirname, 'comment-prompt.md'), { encoding: 'utf-8' });
                    const userPrompt = JSON.stringify(data);
                    const jsonString = yield services_1.default.runAiPrompt(userPrompt, systemPrompt);
                    if (!jsonString) {
                        return;
                    }
                    const json = JSON.parse(jsonString);
                    if (json.isInappropriate) {
                        reel.comments--;
                        yield reel.save();
                        yield _comment.deleteOne();
                        yield (notification1 === null || notification1 === void 0 ? void 0 : notification1.deleteOne());
                        yield (notification2 === null || notification2 === void 0 ? void 0 : notification2.deleteOne());
                        return;
                    }
                    comment.isKind = json.isKind || undefined;
                    comment.isThankyou = json.isThankyou || undefined;
                    comment.isNegative = json.isNegative || undefined;
                    yield comment.save();
                    if (comment.isKind || comment.isThankyou) {
                        const score = yield services_1.default.getOrCreateTodayScore(user._id);
                        if (!score) {
                            return;
                        }
                        const action1 = score.social.actions.find(e => e.type === 'mindful-comments');
                        if (action1 && !action1.completed) {
                            (_a = action1.count) !== null && _a !== void 0 ? _a : (action1.count = 0);
                            action1.count++;
                            action1.value = action1.count / 3;
                            if (action1.count >= 3) {
                                action1.completed = true;
                            }
                        }
                        const action2 = score.social.actions.find(e => e.type === 'mindful-comment-reply');
                        if (action2 && !action2.completed && parent) {
                            action2.value = 1;
                            action2.completed = true;
                        }
                        yield services_1.default.updateScore(score);
                    }
                }
                catch (error) {
                    console.log(error);
                }
            }))();
            return res.status(201).json({ comment });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function patchComment(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const user = res.locals.user;
            const id = req.params.id;
            const { data } = req.body;
            const comment = yield models_2.Comment.findById(id)
                .populate({ path: 'reel', populate: { path: 'user' } })
                .populate({ path: 'parent', populate: { path: 'user' } });
            if (!comment) {
                return res.status(404).json({ message: 'comment not found' });
            }
            const reel = comment.reel;
            // @ts-ignore
            const reelUser = reel.user;
            const parentComment = comment.parent;
            if (`${comment.user}` !== `${user._id}`) {
                return res.status(403).json({ message: 'permission denied' });
            }
            let userIds = data.filter(e => e.user).map(e => e.user);
            userIds = [...new Set(userIds)];
            if (userIds.length) {
                const users = (yield models_1.User.find({ _id: { $in: userIds } }, { _id: 1 })).map(e => e._id.toString());
                for (const u of userIds) {
                    if (!users.includes(u)) {
                        return res.status(404).json({ message: `A user with _id ${u} not found` });
                    }
                }
            }
            comment.data = data;
            yield comment.save();
            const updatedComment = yield models_2.Comment.findById(comment._id)
                .populate({ path: 'user', select: { name: 1, username: 1, photo: 1 } })
                .populate({ path: 'data.user', select: { name: 1, username: 1, photo: 1 } });
            if (`${reel.user._id}` !== `${user._id}`) {
                yield services_1.default.notifyUser({
                    title: 'A comment has been updated on your vibe',
                    description: `${user.username} updated its comment`,
                    event: 'comment-updated',
                    user: reelUser,
                    comment: comment._id,
                    from: user._id,
                    reel: reel._id
                });
            }
            if (parentComment && `${parentComment.user._id}` !== `${user._id}`) {
                yield services_1.default.notifyUser({
                    title: 'A sub-comment updated',
                    description: `${user.username} updated its sub-comment`,
                    event: 'comment-updated',
                    // @ts-ignore
                    user: parentComment.user,
                    comment: comment._id,
                    from: user._id,
                    reel: reel._id
                });
            }
            return res.json({ comment: updatedComment });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function deleteComment(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const user = res.locals.user;
            const id = req.params.id;
            const comment = yield models_2.Comment.findById(id).populate('reel');
            if (!comment) {
                return res.status(404).json({ message: 'comment not found' });
            }
            if (`${comment.user}` !== `${user._id}`) {
                return res.status(403).json({ message: 'permission denied' });
            }
            (() => __awaiter(this, void 0, void 0, function* () {
                try {
                    yield comment.deleteOne();
                    if (!comment.parent) {
                        const commentIds = (yield models_2.Comment.find({ parent: comment._id }, { _id: 1 })).map(e => e._id);
                        commentIds.push(comment._id);
                        yield models_4.Like.deleteMany({ comment: { $in: commentIds } });
                        yield models_2.Comment.deleteMany({ _id: { $in: commentIds } });
                    }
                    const reel = comment.reel;
                    const count = yield models_2.Comment.countDocuments({ reel: reel._id });
                    reel.comments = count;
                    yield reel.save();
                }
                catch (error) {
                    console.log(error);
                }
            }))();
            return res.json({ message: 'comment deleted successfully' });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
const controllers = {
    getComments,
    postComment,
    patchComment,
    deleteComment
};
exports.default = controllers;
