/**
 * Dues Calculator Utility Service
 * 
 * Provides centralized dues calculation and tracking logic
 * Replaces hardcoded "1 year from member_since" fallback logic with proper data-driven calculations
 */

export interface DuesStatus {
  isDue: boolean;
  isOverdue: boolean;
  dueDate: Date | null;
  paidUntil: Date | null;
  daysUntilDue: number | null;
  daysOverdue: number | null;
  amount: number;
  currency: string;
  source: 'database' | 'calculated' | 'fallback';
  confidence: 'high' | 'medium' | 'low';
}

export interface DuesPayment {
  memberId: string;
  amount: number;
  currency: string;
  paymentDate: Date;
  paidUntil: Date;
  paymentMethod?: string;
  transactionId?: string;
  notes?: string;
}

/**
 * Calculate dues status for a member
 * Uses actual payment_due_date field from database when available
 */
export async function calculateDuesStatus(member: any): Promise<DuesStatus> {
  const now = new Date();
  
  // First check if member has payment_due_date field
  if (member.payment_due_date) {
    const paidUntil = new Date(member.payment_due_date);
    const isDue = paidUntil < now;
    const daysUntilDue = isDue ? null : Math.floor((paidUntil.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
    const daysOverdue = isDue ? Math.floor((now.getTime() - paidUntil.getTime()) / (1000 * 60 * 60 * 24)) : null;
    
    return {
      isDue,
      isOverdue: isDue && daysOverdue !== null && daysOverdue > 30, // Consider overdue after 30 days
      dueDate: paidUntil,
      paidUntil,
      daysUntilDue,
      daysOverdue,
      amount: await getDuesAmount(member),
      currency: 'EUR',
      source: 'database',
      confidence: 'high'
    };
  }
  
  // Check if member has last_dues_paid field and calculate from there
  if (member.last_dues_paid) {
    const lastPaid = new Date(member.last_dues_paid);
    const paidUntil = new Date(lastPaid);
    paidUntil.setFullYear(paidUntil.getFullYear() + 1); // Assume annual dues
    
    const isDue = paidUntil < now;
    const daysUntilDue = isDue ? null : Math.floor((paidUntil.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
    const daysOverdue = isDue ? Math.floor((now.getTime() - paidUntil.getTime()) / (1000 * 60 * 60 * 24)) : null;
    
    return {
      isDue,
      isOverdue: isDue && daysOverdue !== null && daysOverdue > 30,
      dueDate: paidUntil,
      paidUntil,
      daysUntilDue,
      daysOverdue,
      amount: await getDuesAmount(member),
      currency: 'EUR',
      source: 'calculated',
      confidence: 'medium'
    };
  }
  
  // Check membership_start_date or member_since as last resort
  const startDate = member.membership_start_date || member.member_since;
  if (startDate) {
    const memberSince = new Date(startDate);
    
    // For new members (joined within last year), calculate from join date
    const oneYearAgo = new Date();
    oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
    
    if (memberSince > oneYearAgo) {
      // New member - first year dues
      const paidUntil = new Date(memberSince);
      paidUntil.setFullYear(paidUntil.getFullYear() + 1);
      
      const isDue = paidUntil < now;
      const daysUntilDue = isDue ? null : Math.floor((paidUntil.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
      const daysOverdue = isDue ? Math.floor((now.getTime() - paidUntil.getTime()) / (1000 * 60 * 60 * 24)) : null;
      
      return {
        isDue,
        isOverdue: isDue && daysOverdue !== null && daysOverdue > 30,
        dueDate: paidUntil,
        paidUntil,
        daysUntilDue,
        daysOverdue,
        amount: await getDuesAmount(member),
        currency: 'EUR',
        source: 'calculated',
        confidence: 'low'
      };
    }
  }
  
  // No dues information available - return null values instead of guessing
  console.warn(`[dues-calculator] No dues information available for member ${member.Id || member.email}`);
  return {
    isDue: false,
    isOverdue: false,
    dueDate: null,
    paidUntil: null,
    daysUntilDue: null,
    daysOverdue: null,
    amount: await getDuesAmount(member),
    currency: 'EUR',
    source: 'fallback',
    confidence: 'low'
  };
}

/**
 * Get dues amount for a member based on their membership type
 */
async function getDuesAmount(member: any): Promise<number> {
  // Check if member has a specific dues amount set
  if (member.dues_amount) {
    return parseFloat(member.dues_amount);
  }
  
  // Check membership type for different rates
  const membershipType = member.membership_type?.toLowerCase() || 'regular';
  
  // These should come from configuration, not hardcoded
  const duesRates: Record<string, number> = {
    'regular': 50,
    'student': 25,
    'senior': 35,
    'family': 75,
    'corporate': 200,
    'lifetime': 0, // Lifetime members don't pay dues
    'honorary': 0  // Honorary members don't pay dues
  };
  
  // Find matching rate or use default
  for (const [type, amount] of Object.entries(duesRates)) {
    if (membershipType.includes(type)) {
      return amount;
    }
  }
  
  // Default dues amount
  return 50;
}

/**
 * Record a dues payment for a member
 */
export async function recordDuesPayment(payment: DuesPayment): Promise<{ success: boolean; message: string }> {
  try {
    const { updateMember } = await import('~/server/utils/nocodb');
    
    // Update member record with payment information
    await updateMember(payment.memberId, {
      last_dues_paid: payment.paymentDate.toISOString(),
      payment_due_date: payment.paidUntil.toISOString(),
      dues_amount: payment.amount,
      last_payment_method: payment.paymentMethod,
      last_transaction_id: payment.transactionId
    });
    
    // TODO: Also record in a payments history table when available
    
    console.log(`[dues-calculator] Recorded dues payment for member ${payment.memberId}: €${payment.amount} until ${payment.paidUntil.toISOString()}`);
    
    return {
      success: true,
      message: 'Dues payment recorded successfully'
    };
  } catch (error: any) {
    console.error('[dues-calculator] Error recording dues payment:', error);
    return {
      success: false,
      message: error.message || 'Failed to record dues payment'
    };
  }
}

/**
 * Calculate next dues date based on payment date and membership type
 */
export function calculateNextDuesDate(
  paymentDate: Date, 
  membershipType: string = 'regular'
): Date {
  const nextDue = new Date(paymentDate);
  
  // Check for special membership types
  const type = membershipType.toLowerCase();
  
  if (type.includes('lifetime') || type.includes('honorary')) {
    // Set to far future date for lifetime/honorary members
    nextDue.setFullYear(nextDue.getFullYear() + 100);
  } else if (type.includes('quarterly')) {
    // Quarterly dues
    nextDue.setMonth(nextDue.getMonth() + 3);
  } else if (type.includes('monthly')) {
    // Monthly dues
    nextDue.setMonth(nextDue.getMonth() + 1);
  } else {
    // Default to annual dues
    nextDue.setFullYear(nextDue.getFullYear() + 1);
  }
  
  return nextDue;
}

/**
 * Get all members with overdue dues
 */
export async function getOverdueMembers(daysOverdue: number = 0): Promise<any[]> {
  try {
    const { getMembers } = await import('~/server/utils/nocodb');
    const allMembers = await getMembers();
    
    if (!allMembers?.list) {
      return [];
    }
    
    const now = new Date();
    const overdueMembers = [];
    
    for (const member of allMembers.list) {
      const status = await calculateDuesStatus(member);
      
      if (status.isOverdue && status.daysOverdue !== null && status.daysOverdue >= daysOverdue) {
        overdueMembers.push({
          ...member,
          duesStatus: status
        });
      }
    }
    
    return overdueMembers;
  } catch (error) {
    console.error('[dues-calculator] Error getting overdue members:', error);
    return [];
  }
}

/**
 * Get members with dues coming due soon
 */
export async function getMembersDueSoon(daysAhead: number = 30): Promise<any[]> {
  try {
    const { getMembers } = await import('~/server/utils/nocodb');
    const allMembers = await getMembers();
    
    if (!allMembers?.list) {
      return [];
    }
    
    const dueSoonMembers = [];
    
    for (const member of allMembers.list) {
      const status = await calculateDuesStatus(member);
      
      if (!status.isDue && status.daysUntilDue !== null && status.daysUntilDue <= daysAhead) {
        dueSoonMembers.push({
          ...member,
          duesStatus: status
        });
      }
    }
    
    return dueSoonMembers;
  } catch (error) {
    console.error('[dues-calculator] Error getting members due soon:', error);
    return [];
  }
}

/**
 * Bulk update dues dates (for admin use)
 */
export async function bulkUpdateDuesDates(
  memberIds: string[], 
  paidUntil: Date
): Promise<{ success: number; failed: number; errors: string[] }> {
  const results = {
    success: 0,
    failed: 0,
    errors: [] as string[]
  };
  
  const { updateMember } = await import('~/server/utils/nocodb');
  
  for (const memberId of memberIds) {
    try {
      await updateMember(memberId, {
        payment_due_date: paidUntil.toISOString()
      });
      results.success++;
    } catch (error: any) {
      results.failed++;
      results.errors.push(`Failed to update member ${memberId}: ${error.message}`);
    }
  }
  
  return results;
}

/**
 * Generate dues reminder data for email templates
 */
export function generateDuesReminderData(member: any, status: DuesStatus): any {
  return {
    memberName: `${member.first_name} ${member.last_name}`,
    email: member.email,
    dueDate: status.dueDate ? status.dueDate.toLocaleDateString() : 'Not set',
    daysOverdue: status.daysOverdue,
    daysUntilDue: status.daysUntilDue,
    amount: status.amount,
    currency: status.currency,
    isOverdue: status.isOverdue,
    memberSince: member.member_since ? new Date(member.member_since).toLocaleDateString() : 'Unknown',
    membershipType: member.membership_type || 'Regular'
  };
}