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

// Constants for date calculations
export const MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
export const DAYS_IN_YEAR = 365;
export const UPCOMING_THRESHOLD_DAYS = 30; // Trigger reminders 1 month before yearly due date

/**
 * Calculate days between two dates
 */
export 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
 * Used consistently across all dues components
 */
export function isInGracePeriod(member: Member): boolean {
  if (!member.payment_due_date) return false;
  
  try {
    const dueDate = new Date(member.payment_due_date);
    const today = new Date();
    return dueDate > today;
  } catch {
    return false;
  }
}

/**
 * Check if a member's last payment is over 1 year old
 * Used consistently across all dues components
 */
export function isPaymentOverOneYear(member: Member): 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);
    const today = new Date();
    
    return today > oneYearFromPayment;
  } catch {
    return false;
  }
}

/**
 * Check if dues are actually current
 * Used consistently across all dues components
 * This is the main logic used throughout the system
 */
export function isDuesActuallyCurrent(member: Member): boolean {
  const paymentTooOld = isPaymentOverOneYear(member);
  const duesCurrentlyPaid = member.current_year_dues_paid === 'true';
  const gracePeriod = isInGracePeriod(member);
  
  // Member is NOT overdue if they're in grace period OR (dues paid AND payment not too old)
  const isOverdue = paymentTooOld || (!duesCurrentlyPaid && !gracePeriod);
  
  return !isOverdue;
}

/**
 * Calculate overdue days for a member
 */
export function calculateOverdueDays(member: Member): number {
  const today = new Date();
  const paymentTooOld = isPaymentOverOneYear(member);
  
  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
 */
export function calculateDaysUntilDue(member: Member): { daysUntilDue: number; nextDueDate: string } | null {
  const today = new Date();
  
  // 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;
}

/**
 * Get the next dues date for a member
 * Used for display purposes
 */
export function getNextDuesDate(member: Member): string {
  // If dues are paid, calculate 1 year from payment date
  if (member.current_year_dues_paid === 'true' && member.membership_date_paid) {
    try {
      const lastPaidDate = new Date(member.membership_date_paid);
      const nextDue = new Date(lastPaidDate);
      nextDue.setFullYear(nextDue.getFullYear() + 1);
      return nextDue.toISOString().split('T')[0];
    } catch {
      // Fall through
    }
  }
  
  // If not paid but has a due date, use that
  if (member.payment_due_date) {
    return member.payment_due_date;
  }
  
  // Fallback: 1 year from member since date
  if (member.member_since) {
    try {
      const memberSince = new Date(member.member_since);
      const nextDue = new Date(memberSince);
      nextDue.setFullYear(nextDue.getFullYear() + 1);
      return nextDue.toISOString().split('T')[0];
    } catch {
      // Ignore invalid dates
    }
  }
  
  return '';
}

/**
 * Get days remaining until due date
 */
export function getDaysRemaining(member: Member): number {
  if (!member.payment_due_date) return 0;
  
  try {
    const dueDate = new Date(member.payment_due_date);
    const today = new Date();
    const diffTime = dueDate.getTime() - today.getTime();
    const diffDays = Math.ceil(diffTime / MILLISECONDS_PER_DAY);
    
    return Math.max(0, diffDays);
  } catch {
    return 0;
  }
}

/**
 * Get a human-readable payment message for a member
 */
export function getPaymentMessage(member: Member, membershipFee: number = 50): string {
  const daysRemaining = getDaysRemaining(member);
  
  if (daysRemaining > 30) {
    return `Your annual membership dues of €${membershipFee} are due in ${daysRemaining} days.`;
  } else if (daysRemaining > 0) {
    return `Your annual membership dues of €${membershipFee} are due in ${daysRemaining} days. Please pay soon to avoid account suspension.`;
  } else {
    return `Your annual membership dues of €${membershipFee} are overdue. Your account may be suspended soon.`;
  }
}

/**
 * Export all utilities as a single object
 * This matches the DuesCalculationUtils interface
 */
export const duesCalculationUtils: DuesCalculationUtils = {
  isInGracePeriod,
  isPaymentOverOneYear,
  isDuesActuallyCurrent,
  calculateOverdueDays,
  calculateDaysUntilDue
};

/**
 * Default export for easy importing
 */
export default {
  // Core logic functions
  isInGracePeriod,
  isPaymentOverOneYear,
  isDuesActuallyCurrent,
  calculateOverdueDays,
  calculateDaysUntilDue,
  
  // Utility functions
  calculateDaysDifference,
  getNextDuesDate,
  getDaysRemaining,
  getPaymentMessage,
  
  // Constants
  MILLISECONDS_PER_DAY,
  DAYS_IN_YEAR,
  UPCOMING_THRESHOLD_DAYS
};
