import asyncHandler from "#middlewares/asyncHandler";
import { Referral, validateUserReferral } from "#models/referral_model";
import { UserWallet, validateUserWallet } from "#models/user_wallet_model";
import { Task } from "#models/task_model";
import { TransactionHistory } from "#models/transaction_history_model";
import mongoose from "mongoose";

// // @desc   Create Referral
// // @route   PUT /user/createReferral
// // @access  Public
// const createReferral = asyncHandler(async (req, res) => {
//     const { referred_user, referring_by } = req.body;

//     // Self-referral validation
//     if (referred_user === referring_by) {
//         return res.status(400).json({
//             status: false,
//             message: "You are not allowed to refer yourself"
//         });
//     }

//     const referringBy = await UserWallet.findOne({ userTelId: referring_by });
//     const referredUser = await UserWallet.findOne({ userTelId: referred_user });

//     // Validations for users
//     if (!referringBy) {
//         return res.status(404).json({
//             status: false,
//             message: "Referring user not found"
//         });
//     }
//     if (!referredUser) {
//         return res.status(404).json({
//             status: false,
//             message: "Referred user not found"
//         });
//     }

//     // Check if the user is already referred
//     const checkIsReferred = await Referral.findOne({ referred_user: referredUser._id });

//     if (checkIsReferred) {
//         return res.status(200).json({
//             status: true,
//             message: "You are already referred"
//         });
//     }

//     // Fetch all referral tasks sorted by referral target (ascending)
//     const referralTasks = await Task.find({ type: "Referral" }).sort({ referralTarget: 1 });

//     if (referralTasks.length > 0) {

//         // Fetch transaction history of the referring user
//         const transactionHistories = await TransactionHistory.find({
//             userId: referringBy._id,
//             taskType: "Referral"
//         });

//         // Arrays to store ongoing, completed, and remaining tasks
//         let ongoingTask = null;
//         let remainingTasks = [];

//         // Categorize tasks into ongoing and remaining
//         for (const task of referralTasks) {
//             const transactionHistory = transactionHistories.find(history => history.taskId.equals(task._id));

//             if (transactionHistory && transactionHistory.status === "ongoing") {
//                 ongoingTask = task; // Get the first ongoing task
//                 break;
//             } else if (!transactionHistory) {
//                 remainingTasks.push(task); // Task not yet started, push to remaining
//             }
//         }

//         let currentTask;
//         let newReferralCount;

//         // Check if an ongoing task is available
//         if (ongoingTask) {
//             currentTask = ongoingTask;
//             const transactionHistory = await TransactionHistory.findOne({
//                 userId: referringBy._id,
//                 taskId: currentTask._id,
//                 taskType: "Referral"
//             });

//             newReferralCount = transactionHistory.referralCount + 1;

//             // Check if the referral count meets the target of the current task
//             if (newReferralCount >= currentTask.referralTarget) {
//                 // Mark task as completed
//                 await TransactionHistory.findOneAndUpdate(
//                     { _id: transactionHistory._id },
//                     {
//                         referralCount: newReferralCount,
//                         rewardAmount: currentTask.reward_amount,
//                         referrerRewardAmount: referringBy.isPremiumUser
//                             ? currentTask.reward_amount * 0.08
//                             : currentTask.reward_amount * 0.04,
//                         status: "completed",
//                         isReferralCompleted: true
//                     },
//                     { new: true }
//                 );
//                 console.log(`Task ${currentTask._id} completed`);
//             } else {
//                 // Increment referral count for the ongoing task
//                 await TransactionHistory.findOneAndUpdate(
//                     { _id: transactionHistory._id },
//                     {
//                         referralCount: newReferralCount,
//                         referrerRewardAmount: 0,
//                         status: "ongoing"
//                     },
//                     { new: true }
//                 );
//                 console.log("Referral count incremented for ongoing task");
//             }

//         } else if (remainingTasks.length > 0) {
//             // If no ongoing task, start with the first remaining task
//             currentTask = remainingTasks[0];
//             newReferralCount = 1;

//             const referral = await Referral.findOne({ referred_user: referringBy?._id }); 
//             // Create a new transaction for the new task
//             const newTransaction = new TransactionHistory({
//                 taskId: currentTask._id,
//                 userId: referringBy._id,
//                 referrerId: referral?.referring_by || null,
//                 rewardAmount: 0,
//                 referrerRewardAmount: 0,
//                 taskType: "Referral",
//                 referralCount: newReferralCount,
//                 status: "ongoing"
//             });
//             await newTransaction.save();
//             console.log("New transaction created for new task");
//         } else {
//             // If no tasks are remaining or ongoing, all tasks are completed
//             return res.status(200).json({
//                 status: true,
//                 message: "All referral tasks are completed!"
//             });
//         }
//     }

//     // Create a new referral entry
//     const referral = new Referral({
//         referred_user: referredUser._id,
//         referring_by: referringBy._id
//     });
//     await referral.save();

//     return res.status(200).json({
//         status: true,
//         message: `Congratulations! You have successfully referred a user.`
//     });
// });




// @desc   Create Referral
// @route   PUT /user/createReferral
// @access  Public
const createReferral = asyncHandler(async (req, res) => {
    const { referred_user, referring_by } = req.body;

    // Self-referral validation
    if (referred_user === referring_by) {
        return res.status(400).json({
            status: false,
            message: "You are not allowed to refer yourself"
        });
    }

    const referringBy = await UserWallet.findOne({ userTelId: referring_by });
    const referredUser = await UserWallet.findOne({ userTelId: referred_user });

    // Validations for users
    if (!referringBy) {
        return res.status(404).json({
            status: false,
            message: "Referring user not found"
        });
    }
    if (!referredUser) {
        return res.status(404).json({
            status: false,
            message: "Referred user not found"
        });
    }

    // Check if the user is already referred
    const checkIsReferred = await Referral.findOne({ referred_user: referredUser._id });

    if (checkIsReferred) {
        return res.status(200).json({
            status: true,
            message: "You are already referred"
        });
    }

    // Check if the referring user has connected their Twitter account
    if (!referringBy.isTwitterConnected) {
        return res.status(400).json({
            status: false,
            message: "You must connect your Twitter account to earn rewards."
        });
    }

    // Reward amounts
    const normalUserReward = 5;
    const premiumUserReward = 25;
    let rewardAmount = referredUser.isPremiumUser ? premiumUserReward : normalUserReward;

    // Create a new referral entry
    const referral = new Referral({
        referred_user: referredUser._id,
        referring_by: referringBy._id
    });
    await referral.save();

    // Update the referring user's balance for the referral
    referringBy.userBalance += rewardAmount;
    await referringBy.save();

    // Increment referral count and check for targets
    const totalReferrals = await Referral.countDocuments({ referring_by: referringBy._id });
    let rewardForTargets = 0;

    // Determine rewards based on targets achieved
    if (totalReferrals >= referringBy.referral_target) {

        rewardForTargets += referringBy.referral_target * 2; // Increment reward by 10 coins for each additional set of 5 referrals
    }

    // Update user balance if any target rewards are achieved
    if (rewardForTargets > 0) {
        referringBy.userBalance += rewardForTargets;
        referringBy.referral_target += referringBy.referral_target;
        await referringBy.save();
        console.log(`Reward of ${rewardForTargets} coins added for reaching ${totalReferrals} referrals.`);
    }

    return res.status(200).json({
        status: true,
        message: `Congratulations! You have successfully referred a user and earned ${rewardAmount} coins.`
    });
});




const getAllReferralRecords = async (req, res) => {
    try {
        // Find all referrals by the given user ID and populate referred user details
        const referrals = await Referral.find({ referring_by: req.params.id })
            .populate({
                path: 'referred_user', // Assuming 'referred_user' is the reference field in Referral model
                model: 'UserWallet', // Specify the model to populate from
                select: '-_id', // Only select userBalance or other relevant fields
            });

        console.log(referrals, "referrals");

        // Manually sort referred users by userBalance in descending order
        const sortedReferredUsers = referrals
            .map(referral => referral.referred_user)
            .filter(user => user) // Filter out null or undefined users (if any)
            .sort((a, b) => b.userBalance - a.userBalance); // Sort by userBalance in descending order

        res.status(200).json({
            success: true,
            users: sortedReferredUsers,
        });
    } catch (error) {
        console.error('Error fetching referred users:', error);
        res.status(500).json({
            success: false,
            message: 'Error fetching referred users',
        });
    }
}

const getReferralByTaskId = async (req, res) => {
    try {
        const referral = await Referral.find({ taskId: req.params.id });
        if (!referral)
            return res
                .status(404)
                .json({ status: true, message: "Referral not found" });
        return res
            .status(200)
            .json({ status: true, message: "Successfully Get Referral By TaskId!" });
    } catch (err) {
        return res.status(500).json({ status: true, message: "Referral Error" });
    }
};

const getAllReferrals = async (req, res) => {
    try {
        const referral = await Referral.find({});
        if (!referral)
            return res
                .status(404)
                .json({ status: true, message: "Referral not found" });
        return res
            .status(200)
            .json({ status: true, message: "Successfully Get Referral!", referral });
    } catch (err) {
        return res.status(500).json({ status: true, message: "Referral Error" });
    }
};

export { createReferral, getAllReferralRecords, getReferralByTaskId, getAllReferrals };
