"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("./models");
const models_2 = require("../reward-hashes/models");
const helpers_1 = __importDefault(require("../../utils/helpers"));
const constants_1 = __importDefault(require("../../utils/constants"));
const services_1 = __importDefault(require("../../utils/services"));
function getMeetmeRewards(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        var _a, _b;
        try {
            const user = res.locals.user;
            let { limit = '10', page = '1' } = req.query;
            limit = +limit;
            page = +page;
            const skip = (page - 1) * limit;
            const twoDaysAgo = new Date();
            twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
            const match = {
                isMeetme: true,
                $and: [
                    {
                        $or: [
                            { expiredAt: { $exists: false } },
                            { expiredAt: { $gt: twoDaysAgo } },
                        ]
                    }
                ]
            };
            if (constants_1.default.locationMode && user.location) {
                match.$and.push({
                    $or: [
                        {
                            location: {
                                $geoWithin: {
                                    $centerSphere: [
                                        user.location.coordinates, // [lng, lat]
                                        constants_1.default.locationDistance / constants_1.default.earthRadius // meters → radians
                                    ]
                                }
                            }
                        },
                        { location: { $exists: false } }
                    ]
                });
            }
            // 1️⃣ Get paginated data
            const rewards = yield models_1.Reward.aggregate([
                { $match: match },
                { $sort: { createdAt: -1 } },
                { $skip: skip },
                { $limit: limit },
                {
                    $lookup: {
                        from: 'reward-hashes',
                        let: { rewardId: '$_id', userId: user._id },
                        pipeline: [
                            {
                                $match: {
                                    $expr: {
                                        $and: [
                                            { $eq: ['$reward', '$$rewardId'] },
                                            { $eq: ['$user', '$$userId'] }
                                        ]
                                    }
                                }
                            },
                            { $limit: 1 }
                        ],
                        as: 'hash'
                    }
                },
                {
                    $unwind: {
                        path: '$hash',
                        preserveNullAndEmptyArrays: true
                    }
                }
            ]);
            for (const e of rewards) {
                e.isConsumed = (_a = e.hash) === null || _a === void 0 ? void 0 : _a.isConsumed;
                e.hash = (_b = e.hash) === null || _b === void 0 ? void 0 : _b._id;
            }
            // 2️⃣ Get total count
            const count = yield models_1.Reward.countDocuments(match);
            return res.json({ rewards, count });
        }
        catch (error) {
            console.error(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function getProfileRewards(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const user = res.locals.user;
            const limit = 6;
            const page = 1;
            const skip = (page - 1) * limit;
            const at = new Date();
            at.setDate(at.getDate() - 2);
            const match = {
                $or: [
                    { isMeetme: { $exists: false } },
                    { isMeetme: false },
                ],
                user: user._id
            };
            const rewardHashes = yield models_2.RewardHash.aggregate([
                { $match: match },
                { $sort: { at: -1 } },
                { $skip: skip },
                { $limit: limit },
                {
                    $lookup: {
                        from: 'rewards',
                        localField: 'reward',
                        foreignField: '_id',
                        as: 'reward'
                    }
                },
                { $unwind: { path: '$reward' } },
                { $project: { hash: 0 } }
            ]);
            const count = yield models_2.RewardHash.countDocuments(match);
            const rewardCoins = [];
            for (let i = 0; i < 7; i++) {
                if (i < rewardHashes.length) {
                    rewardCoins.push({ type: 'unlocked' });
                }
                else if (i === rewardHashes.length) {
                    rewardCoins.push({ type: 'pending' });
                }
                else {
                    rewardCoins.push({ type: 'locked' });
                }
            }
            return res.json({ rewardHashes, count, rewardCoins });
        }
        catch (error) {
            console.error(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postGenerateRewardHash(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const user = res.locals.user;
            const id = req.params.id;
            const reward = yield models_1.Reward.findById(id);
            if (!reward) {
                return res.status(404).json({ message: 'reward not found' });
            }
            if (!reward.isMeetme) {
                return res.status(403).json({ message: 'only applies to meet me reward' });
            }
            if (reward.remaining <= 0) {
                return res.status(410).json({ message: 'reward expired' });
            }
            if (reward.expiredAt && reward.expiredAt <= new Date()) {
                return res.status(410).json({ message: 'reward expired' });
            }
            let rewardHash = yield models_2.RewardHash.findOne({
                user: user._id,
                reward: reward._id
            });
            if (rewardHash) {
                return res.json({ hash: rewardHash._id });
            }
            rewardHash = yield models_2.RewardHash.create({
                user: user._id,
                reward: reward._id,
                hash: helpers_1.default.getHash(`${user._id}:${reward._id}`),
                isMeetme: true
            });
            return res.status(201).json({ hash: rewardHash._id });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postOpenedViewAll(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const user = res.locals.user;
            (() => __awaiter(this, void 0, void 0, function* () {
                try {
                    const score = yield services_1.default.getOrCreateTodayScore(user._id);
                    if (!score) {
                        return;
                    }
                    const action = score.social.actions.find(e => e.type === 'open-view-all-rewards');
                    if (!action || action.completed) {
                        return;
                    }
                    action.value = 1;
                    action.completed = true;
                    yield services_1.default.updateScore(score);
                }
                catch (error) {
                    console.log(error);
                }
            }))();
            return res.json({ message: 'done' });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
const controllers = {
    getMeetmeRewards,
    getProfileRewards,
    postGenerateRewardHash,
    postOpenedViewAll
};
exports.default = controllers;
