import type { Member } from '~/utils/types';

interface DuesMemberWithStatus extends Member {
  overdueDays?: number;
  overdueReason?: string;
  daysUntilDue?: number;
  nextDueDate?: string;
}

interface DuesStatusResponse {
  success: boolean;
  data: {
    overdue: DuesMemberWithStatus[];
    upcoming: DuesMemberWithStatus[];
    autoUpdated: number;
  };
}

// Constants for date calculations
const MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
const DAYS_IN_YEAR = 365;
const UPCOMING_THRESHOLD_DAYS = 30;

/**
 * Calculate days between two dates
 */
function calculateDaysDifference(date1: Date, date2: Date): number {
  return Math.floor((date1.getTime() - date2.getTime()) / MILLISECONDS_PER_DAY);
}

/**
 * Check if a member is in their grace period
 */
function isInGracePeriod(member: Member, today: Date): boolean {
  if (!member.payment_due_date) return false;
  
  try {
    const dueDate = new Date(member.payment_due_date);
    return dueDate > today;
  } catch {
    return false;
  }
}

/**
 * Check if a member's last payment is over 1 year old
 */
function isPaymentOverOneYear(member: Member, today: Date): boolean {
  if (!member.membership_date_paid) return false;
  
  try {
    const lastPaidDate = new Date(member.membership_date_paid);
    const oneYearFromPayment = new Date(lastPaidDate);
    oneYearFromPayment.setFullYear(oneYearFromPayment.getFullYear() + 1);
    
    return today > oneYearFromPayment;
  } catch {
    return false;
  }
}

/**
 * Calculate overdue days for a member
 */
function calculateOverdueDays(member: Member, today: Date, paymentTooOld: boolean): number {
  if (paymentTooOld && member.membership_date_paid) {
    try {
      const lastPaidDate = new Date(member.membership_date_paid);
      return calculateDaysDifference(today, lastPaidDate) - DAYS_IN_YEAR;
    } catch {
      return 0;
    }
  }
  
  if (member.payment_due_date) {
    try {
      const dueDate = new Date(member.payment_due_date);
      return calculateDaysDifference(today, dueDate);
    } catch {
      return 0;
    }
  }
  
  return 0;
}

/**
 * Calculate days until due for upcoming members
 */
function calculateDaysUntilDue(member: Member, today: Date): { daysUntilDue: number; nextDueDate: string } | null {
  // First try membership_date_paid (existing members)
  if (member.membership_date_paid) {
    try {
      const lastPaidDate = new Date(member.membership_date_paid);
      const nextDueDate = new Date(lastPaidDate);
      nextDueDate.setFullYear(nextDueDate.getFullYear() + 1);
      
      const daysUntilDue = calculateDaysDifference(nextDueDate, today);
      
      if (daysUntilDue <= UPCOMING_THRESHOLD_DAYS && daysUntilDue > 0) {
        return {
          daysUntilDue,
          nextDueDate: nextDueDate.toISOString().split('T')[0]
        };
      }
    } catch {
      // Fall through to payment_due_date check
    }
  }
  
  // Try payment_due_date (new members in grace period)
  if (member.payment_due_date) {
    try {
      const dueDate = new Date(member.payment_due_date);
      const daysUntilDue = calculateDaysDifference(dueDate, today);
      
      if (daysUntilDue <= UPCOMING_THRESHOLD_DAYS && daysUntilDue > 0) {
        return {
          daysUntilDue,
          nextDueDate: member.payment_due_date
        };
      }
    } catch {
      // Ignore invalid dates
    }
  }
  
  return null;
}

export default defineEventHandler(async (event): Promise<DuesStatusResponse> => {
  try {
    const { getMembers, updateMember } = await import('~/server/utils/nocodb');

    // Get all members
    const allMembers = await getMembers();
    
    if (!allMembers?.list?.length) {
      return {
        success: true,
        data: {
          overdue: [],
          upcoming: [],
          autoUpdated: 0
        }
      };
    }

    const today = new Date();
    const overdueMembers: DuesMemberWithStatus[] = [];
    const upcomingMembers: DuesMemberWithStatus[] = [];
    const membersToUpdate: Member[] = [];

    console.log(`[dues-status] Processing ${allMembers.list.length} members for dues status...`);

    for (const member of allMembers.list) {
      const memberName = `${member.first_name || ''} ${member.last_name || ''}`.trim() || `Member ${member.Id}`;
      
      // Check member status
      const gracePeriod = isInGracePeriod(member, today);
      const paymentTooOld = isPaymentOverOneYear(member, today);
      const duesCurrentlyPaid = member.current_year_dues_paid === 'true';
      
      // Determine if member is overdue
      const isOverdue = paymentTooOld || (!duesCurrentlyPaid && !gracePeriod);
      
      if (isOverdue) {
        // Handle overdue member
        if (paymentTooOld && member.membership_status !== 'Inactive') {
          console.log(`[dues-status] ${memberName}: Auto-updating to Inactive (payment over 1 year old)`);
          membersToUpdate.push(member);
        }
        
        const overdueDays = calculateOverdueDays(member, today, paymentTooOld);
        const overdueReason = paymentTooOld 
          ? `Payment from ${member.membership_date_paid} is over 1 year old`
          : 'Current year dues not paid';
        
        overdueMembers.push({
          ...member,
          overdueDays,
          overdueReason
        });
        
      } else if (duesCurrentlyPaid || gracePeriod) {
        // Check if member has upcoming dues
        const upcomingInfo = calculateDaysUntilDue(member, today);
        
        if (upcomingInfo) {
          upcomingMembers.push({
            ...member,
            ...upcomingInfo
          });
        }
      }
    }

    // Auto-update members who need status changes
    let autoUpdatedCount = 0;
    if (membersToUpdate.length > 0) {
      console.log(`[dues-status] Auto-updating ${membersToUpdate.length} members to Inactive status...`);
      
      for (const memberUpdate of membersToUpdate) {
        try {
          await updateMember(memberUpdate.Id, {
            membership_status: 'Inactive',
            current_year_dues_paid: 'false'
          });
          
          // Update the overdue member in our list to reflect the status change
          const overdueIndex = overdueMembers.findIndex(m => m.Id === memberUpdate.Id);
          if (overdueIndex !== -1) {
            overdueMembers[overdueIndex].membership_status = 'Inactive';
            overdueMembers[overdueIndex].current_year_dues_paid = 'false';
          }
          
          autoUpdatedCount++;
          console.log(`[dues-status] ✓ Updated ${memberUpdate.first_name} ${memberUpdate.last_name} to Inactive`);
        } catch (error: any) {
          console.error(`[dues-status] ✗ Failed to update member ${memberUpdate.Id}:`, error.message);
        }
      }
    }

    // Sort results
    overdueMembers.sort((a, b) => (b.overdueDays || 0) - (a.overdueDays || 0));
    upcomingMembers.sort((a, b) => (a.daysUntilDue || 999) - (b.daysUntilDue || 999));

    console.log(`[dues-status] ✓ Results: ${overdueMembers.length} overdue, ${upcomingMembers.length} upcoming, ${autoUpdatedCount} auto-updated`);

    return {
      success: true,
      data: {
        overdue: overdueMembers,
        upcoming: upcomingMembers,
        autoUpdated: autoUpdatedCount
      }
    };

  } catch (error: any) {
    console.error('[dues-status] ✗ Error processing dues status:', error);
    
    throw createError({
      statusCode: error.statusCode || 500,
      statusMessage: error.message || 'Failed to process dues status'
    });
  }
});
