import { Request, Response } from 'express';
import { PaginationHelper } from '../helpers/paginate';
import db from '../models'; // Adjust the path to your models folder if necessary
const FollowUpModel = db.FollowUp;
const FollowUpLogModel = db.FollowUpLog;
const UserModel = db.User;
import { Op } from 'sequelize';
import { UserData } from '../helpers/userToken';

//Create Follow Up API
export const createFollowUp = async (req: Request, res: Response): Promise<void> => {
    try {
        const { id, title, with_whom, assigned_to, followup_date, followup_notes, type } = req.body;

        // Get the user data from request
        const userData = (req as any).user as UserData;
        let user_id = req.user.user_data.id;
        let followUp;


        if(type === 'delete'){
            if (!id) {
                res.status(404).json({ success: false, message: "ID is required for deletion." });
                return;
            }

            const followUpDelete = await FollowUpModel.findOne({
                where: { id }
            });

            if (!followUpDelete) {
                res.status(404).json({ success: false, message: "Follow Up Not Found" });
                return;
            }

            await FollowUpLogModel.destroy({
                where: { follow_up_id: id}
            })

            await FollowUpModel.destroy({
                where: { id }
            });

        } else if(id) {
            followUp = await FollowUpModel.findOne({ where: { id } });
            if(!followUp) {
                res.status(404).json({ success: false, message: "Follow Up Not Found"});
                return;
            }

            const oldFollowUpDate = followUp.followup_date;

            await followUp.update({
                title,
                with_whom,
                assigned_to,
                followup_date,
                followup_notes,
            },
            {
                where: { id }
            }
            );

            const oldDate = new Date(oldFollowUpDate).getTime();
            const newDate = new Date(followup_date).getTime();

            if (oldDate !== newDate) {
                await FollowUpLogModel.create({
                    follow_up_id: id,
                    current_follow_up_date: oldFollowUpDate,
                    new_follow_up: followup_date,
                    status: "pending",
                    user_id,
                    transaction_type: 'edit_followup',
                    date_time: new Date()
                });
            }

        } else{
            // Create a new follow-up
            followUp = await FollowUpModel.create({
                title,
                with_whom,
                assigned_to,
                followup_date,
                followup_notes,
                status: 'pending',  // Default status as pending
                created_by: user_id,
                reschedule_count: 0
            });


            await FollowUpLogModel.create({
                follow_up_id: followUp.id,
                current_follow_up_date: followup_date,
                status: 'pending',
                user_id,
                transaction_type: 'create_followup',
                date_time: new Date()
            });
        }
    
        res.status(200).json({
            success: true,
            message: type === 'delete' ? 'Follow-up removed. Keeping your attention where it counts' : id ? 'Follow-up refined. The details make the difference.' : 'Follow-up planted. Your future self sends thanks',
            data: followUp
          });
    }catch (error) {
        console.error('Error creating follow up:', error);
        res.status(500).json({
            success: false,
            message: "We hit a snag! Our team is looking into it.",
            error: error instanceof Error ? error.message : 'Unknown error'
        });
    }
}

//Get Follow Up Api
export const getFollowUps = async (req: Request, res: Response): Promise<void> => {
    try {
        const { page, per_page, type, search  } = req.query;

        const userId = (req.user as UserData).user_data.id;

        // const selectedDate = followup_date ? new Date(followup_date as string) : new Date();
        
        // // Get today's date at start and end
        // const startOfDay = new Date(selectedDate);
        // startOfDay.setHours(0, 0, 0, 0);

        // const endOfDay = new Date(selectedDate);
        // endOfDay.setHours(23, 59, 59, 999);

        const whereClause: any = {
            is_active: true,
            // followup_date: {
            //     [Op.between]: [startOfDay, endOfDay]
            // }  
        };

        // Get paginated plans list (existing functionality)
        const { limit, offset } = PaginationHelper.getPaginationParams(
            page as string | number | undefined, 
            per_page as string | number | undefined
        );

        let result;

        if(type === 'user_list') {
            whereClause.assigned_to = userId;

            // Add search condition if search parameter exists
            if (search && typeof search === 'string') {
                whereClause.title = {
                    [Op.iLike]: `%${search}%`
                };
            }

            result = await FollowUpModel.findAll({
                where: whereClause,
                include: [
                    {
                        model: UserModel,
                        as: 'assignee',
                        required: false,
                        attributes: { exclude: ['createdAt', 'updatedAt', 'token'] }
                    },
                    {
                        model: UserModel,
                        as: 'creator',
                        required: false,
                        attributes: { exclude: ['createdAt', 'updatedAt', 'token'] }
                    }
                ],
                order: [['followup_date', 'DESC']],
                distinct: true
            });
            
        } else {
            
            // Add search condition if search parameter exists
            if (search && typeof search === 'string') {
                whereClause.title = {
                    [Op.iLike]: `%${search}%`
                };
            }
            result = await FollowUpModel.findAll({
                where: whereClause,
                include: [
                    {
                        model: UserModel,
                        as: 'assignee',
                        required: false,
                        attributes: { exclude: ['createdAt', 'updatedAt', 'token'] }
                    },
                    {
                        model: UserModel,
                        as: 'creator',
                        required: false,
                        attributes: { exclude: ['createdAt', 'updatedAt', 'token'] }
                    }
                ],
                order: [['followup_date', 'DESC']],
                distinct: true
            });
        }



        const paginatedResult = PaginationHelper.paginate({
            data: result.rows,
            count: result.count,
            per_page: limit,
            page: page as string
        });
      
        res.status(200).json({
            success: true,
            message: type === 'user_list' ? 'Your follow-ups' : 'All team follow-ups',
            data: result,
            pagination: paginatedResult.pagination
        });

    }catch (error) {
        console.error('Error fetching follow ups:', error);
        res.status(500).json({
            success: false,
            message: "We hit a snag! Our team is looking into it.",
            error: error instanceof Error ? error.message : 'Unknown error'
        });
    }
}


//Reschedule Follow Up Api
export const rescheduleFollowUp = async (req: Request, res: Response): Promise<void> => {
    try {
        const { id, current_follow_up_date, new_follow_up_date, reschedule_reason } = req.body;

        const followUp = await FollowUpModel.findOne({ where: { id } });
        if(!followUp) {
            res.status(404).json({ success: false, message: "Follow Up not found" });
            return;
        }

        const userId = (req as any).user.user_data.id;

        await followUp.update({
            followup_date: new_follow_up_date,
            reschedule_reason,
            reschedule_count: followUp.reschedule_count + 1,
        })

        await FollowUpLogModel.create({
            follow_up_id: followUp.id,
            current_follow_up_date,
            new_follow_up: new_follow_up_date,
            status: "pending",
            reason: reschedule_reason,
            user_id: userId,
            transaction_type: 'reschedule_followup',
            date_time: new Date()
        });

        res.status(200).json({
            success: true,
            message: 'Follow-up rescheduled. Perfect timing is everything'
        });
    }catch (error) {
        console.error('Error rescheduling follow up:', error);
        res.status(500).json({
            success: false,
            message: "We hit a snag! Our team is looking into it.",
            error: error instanceof Error ? error.message : 'Unknown error'
        });
    }
}

//Mark as done Follow Up Api
export const completedFollowUp = async (req: Request, res: Response): Promise<void> => {
    try {
        const { id, followup_outcome } = req.body;

        const followUp = await FollowUpModel.findOne({ where: { id } });
        if(!followUp) {
            res.status(404).json({ success: false, message: "Follow Up not found" });
            return;
        }

        const userId = (req as any).user.user_data.id;

        await followUp.update({
            followup_outcome,
            status: "completed"
        })

        await FollowUpLogModel.create({
            follow_up_id: followUp.id,
            current_follow_up_date: followUp.followup_date,
            status: "completed",
            user_id: userId,
            transaction_type: 'complete_followup',
            date_time: new Date()

        });

        res.status(200).json({
            success: true,
            message: 'Follow-up closed. One fewer loose end to manage'
        });
    }catch (error) {
        console.error('Error completing follow up:', error);
        res.status(500).json({
            success: false,
            message: "We hit a snag! Our team is looking into it.",
            error: error instanceof Error ? error.message : 'Unknown error'
        });
    }
}

//Categorised Follow Up API
export const getFollowUpsByCategory = async (req: Request, res: Response): Promise<void> => {
    try {
        const { followup_date, type } = req.query;
        const userId = (req.user as UserData).user_data.id;

        // Set up base date from query param or default to today
        const baseDate = followup_date ? new Date(followup_date as string) : new Date();
        baseDate.setHours(0, 0, 0, 0);

        // Function to get next N business days
        const getNextBusinessDays = (startDate: Date, numberOfDays: number): Date[] => {
            const businessDays: Date[] = [];
            const currentDate = new Date(startDate);
            
            while (businessDays.length < numberOfDays) {
                currentDate.setDate(currentDate.getDate() + 1);
                
                // Skip weekends (6 = Saturday, 0 = Sunday)
                if (currentDate.getDay() !== 6 && currentDate.getDay() !== 0) {
                    businessDays.push(new Date(currentDate));
                }
            }
            
            return businessDays;
        };

        // Get next 3 business days
        const upcomingDays = getNextBusinessDays(baseDate, 3);

        // Base where clause
        let whereClause: any = {
            is_active: true,
            // status: { [Op.ne]: 'completed' } // Exclude completed follow-ups
        };

        // Add user filter if type is 'me'
        if (type === 'me') {
            whereClause.assigned_to = userId;
        }

        // Get all follow-ups
        const allFollowUps: Array<{ followup_date: string; status: string; [key: string]: any }> = await FollowUpModel.findAll({
            where: whereClause,
            include: [
                {
                    model: UserModel,
                    as: 'assignee',
                    attributes: ['first_name', 'last_name']
                },
                {
                    model: UserModel,
                    as: 'creator',
                    attributes: ['first_name', 'last_name']
                }
            ],
            order: [['followup_date', 'ASC']],
        });

        // Categorize follow-ups
        const categorizedFollowUps = {
            overdue: allFollowUps.filter((followUp: { followup_date: string; status: string }) => {
                const followupDate = new Date(followUp.followup_date);
                followupDate.setHours(0, 0, 0, 0);
                return followupDate < baseDate && followUp.status !== 'completed';
            }),
            today: allFollowUps.filter(followUp => {
                const followupDate = new Date(followUp.followup_date);
                return followupDate.toDateString() === baseDate.toDateString();
            }),
            upcoming: allFollowUps.filter(followUp => {
                const followupDate = new Date(followUp.followup_date);
                followupDate.setHours(0, 0, 0, 0);
                return upcomingDays.some(date => 
                    date.toDateString() === followupDate.toDateString()
                ) && followUp.status !== 'completed';
            })
        };

        const statistics = {
            total: allFollowUps.length,
            overdue: categorizedFollowUps.overdue.length,
            today: categorizedFollowUps.today.length,
            upcoming: categorizedFollowUps.upcoming.length
        };

        res.status(200).json({
            success: true,
            message: type === 'me' ? 'Your follow-ups by category' : 'All follow-ups by category',
            statistics,
            data: categorizedFollowUps
        });

    } catch (error) {
        console.error('Error fetching categorized follow-ups:', error);
        res.status(500).json({
            success: false,
            message: "We hit a snag! Our team is looking into it.",
            error: error instanceof Error ? error.message : 'Unknown error'
        });
    }
};
