const cron = require('node-cron');
const moment = require('moment-timezone');
const { ChitGroup, GroupMember, Payment, Notification, User } = require('../models');
const WhatsAppHelper = require('../utils/whatsapp-helper');
const { Op } = require('sequelize');

/**
 * Payment Reminder Service
 * Automatically sends payment reminders based on due dates
 */
class ReminderService {
  /**
   * Start the payment reminder scheduler
   * Runs every day at 9:00 AM IST
   */
  static startScheduler() {
    // Run every day at 9:00 AM IST
    cron.schedule('0 9 * * *', async () => {
      console.log(`[${new Date().toISOString()}] Running scheduled payment reminders...`);
      try {
        await this.sendPaymentReminders();
        console.log('Payment reminders completed successfully');
      } catch (error) {
        console.error('Error in payment reminders:', error);
      }
    }, {
      timezone: "Asia/Kolkata"
    });

    console.log('Payment reminder scheduler started (9:00 AM IST daily)');
    
    // Optional: Also run immediately on server start for testing
    // Uncomment the next line to test reminders on startup
    // this.sendPaymentReminders();
  }

  /**
   * Main function to process and send payment reminders
   */
  static async sendPaymentReminders() {
    const today = moment().tz('Asia/Kolkata').startOf('day');
    console.log(`Processing reminders for date: ${today.format('YYYY-MM-DD')}`);
    
    try {
      // Get all active groups
      const activeGroups = await ChitGroup.findAll({ where: { status: 'active' } });
      console.log(`Found ${activeGroups.length} active groups`);
      
      let totalReminders = 0;
      
      for (const group of activeGroups) {
        try {
          const remindersSent = await this.processGroupReminders(group, today);
          totalReminders += remindersSent;
        } catch (error) {
          console.error(`Error processing group ${group.name}:`, error);
        }
      }
      
      console.log(`Total reminders processed: ${totalReminders}`);
      return totalReminders;
    } catch (error) {
      console.error('Error in sendPaymentReminders:', error);
      throw error;
    }
  }

  /**
   * Process reminders for a specific group
   */
  static async processGroupReminders(group, today) {
    const currentMonth = this.getCurrentMonthNumber(group);
    const dueDate = this.calculateDueDate(group, currentMonth);
    const daysUntilDue = dueDate.diff(today, 'days');
    
    console.log(`Group: ${group.name}, Month: ${currentMonth}, Due: ${dueDate.format('YYYY-MM-DD')}, Days until due: ${daysUntilDue}`);
    
    let remindersSent = 0;
    
    // Send reminders on specific days before due date
    const reminderDays = [7, 3, 1, 0]; // 7 days, 3 days, 1 day, and on due date
    
    if (reminderDays.includes(daysUntilDue)) {
      remindersSent = await this.sendRemindersForGroup(group, dueDate, daysUntilDue, currentMonth);
    }
    
    // Check for overdue payments
    if (daysUntilDue < 0) {
      const daysOverdue = Math.abs(daysUntilDue);
      
      // Send overdue reminders on days 1, 3, 7, 14, 30
      if ([1, 3, 7, 14, 30].includes(daysOverdue)) {
        remindersSent = await this.sendOverdueReminders(group, daysOverdue, currentMonth);
      }
    }
    
    return remindersSent;
  }

  /**
   * Send reminders to unpaid members of a group
   */
  static async sendRemindersForGroup(group, dueDate, daysLeft, month) {
    // Get all active members
    const members = await GroupMember.findAll({
      where: {
        group_id: group.id,
        status: 'active'
      },
      include: [{ model: User, as: 'user' }]
    });
    
    console.log(`  Processing ${members.length} members`);
    
    let sent = 0;
    
    for (const member of members) {
      try {
        // Check if payment already made for this month
        const existingPayment = await Payment.findOne({
          where: {
            group_id: group.id,
            user_id: member.user.id,
            month: month,
            year: new Date().getFullYear(),
            status: 'success'
          }
        });
        
        if (!existingPayment) {
          // Member hasn't paid yet - send reminder
          await this.sendReminder(
            member.user,
            group,
            dueDate.toDate(),
            group.monthly_installment,
            daysLeft,
            month
          );
          sent++;
        }
      } catch (error) {
        console.error(`Error sending reminder to ${member.user?.full_name || 'member'}:`, error);
      }
    }
    
    console.log(`  Sent ${sent} reminders`);
    return sent;
  }

  /**
   * Send overdue payment reminders
   */
  static async sendOverdueReminders(group, daysOverdue, month) {
    const members = await GroupMember.findAll({
      where: {
        group_id: group.id,
        status: 'active'
      },
      include: [{ model: User }]
    });
    
    let sent = 0;
    
    for (const member of members) {
      try {
        // Check if payment is actually overdue
        const existingPayment = await Payment.findOne({
          where: {
            group_id: group.id,
            user_id: member.user.id,
            month: month,
            year: new Date().getFullYear(),
            status: 'success'
          }
        });
        
        if (!existingPayment) {
          // Payment is overdue - send urgent reminder
          await this.sendOverdueReminder(
            member.user,
            group,
            this.calculateDueDate(group, month).toDate(),
            group.monthly_installment,
            daysOverdue,
            month
          );
          sent++;
        }
      } catch (error) {
        console.error(`Error sending overdue reminder to ${member.user?.full_name || 'member'}:`, error);
      }
    }
    
    console.log(`  Sent ${sent} overdue reminders`);
    return sent;
  }

  /**
   * Send a single payment reminder
   */
  static async sendReminder(user, group, dueDate, amount, daysLeft, month) {
    const message = WhatsAppHelper.generatePaymentReminder(
      user,
      group,
      dueDate,
      amount,
      daysLeft
    );
    
    // Create notification record
    const notification = await Notification.create({
      type: 'payment_reminder',
      user_id: user.id,
      group_id: group.id,
      channel: 'whatsapp',
      message: message,
      days_before_due: daysLeft,
      metadata: {
        month: month,
        amount: amount,
        due_date: dueDate
      }
    });
    
    // For WhatsApp Click-to-Chat, we just log the reminder
    // The user will manually use the share feature in the app
    console.log(`    ✓ Reminder created for ${user.full_name} (${daysLeft} days)`);
    
    // Mark as sent (even though it's pending manual sharing)
    await notification.markAsSent();
    
    // TODO: If WhatsApp Business API is integrated, send automatically here
    // await this.sendWhatsAppMessage(user.mobile_number, message);
    
    return notification;
  }

  /**
   * Send overdue payment reminder
   */
  static async sendOverdueReminder(user, group, dueDate, amount, daysOverdue, month) {
    const message = WhatsAppHelper.generateOverdueReminder(
      user,
      group,
      dueDate,
      amount,
      daysOverdue
    );
    
    // Create notification record with higher priority
    const notification = await Notification.create({
      type: 'payment_overdue',
      user_id: user.id,
      group_id: group.id,
      channel: 'whatsapp',
      message: message,
      priority: 'urgent',
      days_before_due: -daysOverdue,
      metadata: {
        month: month,
        amount: amount,
        due_date: dueDate,
        days_overdue: daysOverdue
      }
    });
    
    console.log(`    ⚠️  Overdue reminder created for ${user.full_name} (${daysOverdue} days overdue)`);
    
    await notification.markAsSent();
    
    return notification;
  }

  /**
   * Get current month number for a group
   */
  static getCurrentMonthNumber(group) {
    const startDate = moment(group.start_date).tz('Asia/Kolkata');
    const now = moment().tz('Asia/Kolkata');
    
    // Calculate months elapsed since start
    const monthsElapsed = now.diff(startDate, 'months');
    
    // Current month is 1-indexed
    return Math.max(1, monthsElapsed + 1);
  }

  /**
   * Calculate due date for a specific month
   */
  static calculateDueDate(group, monthNumber) {
    return WhatsAppHelper.calculateDueDate(group, monthNumber);
  }

  /**
   * Manual trigger for testing
   */
  static async triggerManualReminders() {
    console.log('Manually triggering payment reminders...');
    return await this.sendPaymentReminders();
  }

  /**
   * Get reminder statistics
   */
  static async getReminderStats(groupId = null, days = 30) {
    const dateFrom = moment().subtract(days, 'days').toDate();
    
    const where = {
      type: ['payment_reminder', 'payment_overdue'],
      createdAt: { [Op.gte]: dateFrom }
    };
    
    if (groupId) {
      where.group_id = groupId;
    }
    
    const totalReminders = await Notification.count({ where });
    const sentReminders = await Notification.count({ 
      where: { ...where, status: 'sent' } 
    });
    const failedReminders = await Notification.count({ 
      where: { ...where, status: 'failed' } 
    });
    
    return {
      total: totalReminders,
      sent: sentReminders,
      failed: failedReminders,
      success_rate: totalReminders > 0 ? ((sentReminders / totalReminders) * 100).toFixed(2) : 0
    };
  }

  /**
   * Get upcoming reminders (for preview)
   */
  static async getUpcomingReminders(groupId) {
    const group = await ChitGroup.findByPk(groupId);
    if (!group) {
      throw new Error('Group not found');
    }
    
    const today = moment().tz('Asia/Kolkata').startOf('day');
    const currentMonth = this.getCurrentMonthNumber(group);
    const dueDate = this.calculateDueDate(group, currentMonth);
    const daysUntilDue = dueDate.diff(today, 'days');
    
    // Get unpaid members
    const members = await GroupMember.findAll({
      where: {
        group_id: group.id,
        status: 'active'
      },
      include: [{ model: User }]
    });
    
    const unpaidMembers = [];
    
    for (const member of members) {
      const payment = await Payment.findOne({
        where: {
          group_id: group.id,
          user_id: member.user.id,
          month: currentMonth,
          year: new Date().getFullYear(),
          status: 'success'
        }
      });
      
      if (!payment) {
        unpaidMembers.push({
          name: member.user.full_name,
          mobile: member.user.mobile_number
        });
      }
    }
    
    return {
      group_name: group.name,
      current_month: currentMonth,
      due_date: dueDate.format('DD MMM YYYY'),
      days_until_due: daysUntilDue,
      unpaid_members: unpaidMembers.length,
      unpaid_member_list: unpaidMembers
    };
  }
}

module.exports = ReminderService;

