/**
 * Churn Prediction — Weighted RFM Model
 * Recency 30%, Frequency 25%, Monetary 20%, Velocity 15%, Engagement 10%
 */

const WEIGHTS = {
  recency: 0.30,
  frequency: 0.25,
  monetary: 0.20,
  velocity: 0.15,
  engagement: 0.10
};

/**
 * Score a single dimension 0-100 (higher = healthier / lower risk)
 */
function scoreRecency(daysInactive) {
  if (daysInactive === null || daysInactive === undefined) return 0;
  if (daysInactive <= 3) return 100;
  if (daysInactive <= 7) return 90;
  if (daysInactive <= 14) return 75;
  if (daysInactive <= 30) return 55;
  if (daysInactive <= 60) return 35;
  if (daysInactive <= 90) return 15;
  return 5;
}

function scoreFrequency(opsPerMonth) {
  if (!opsPerMonth || opsPerMonth <= 0) return 0;
  if (opsPerMonth >= 20) return 100;
  if (opsPerMonth >= 10) return 85;
  if (opsPerMonth >= 5) return 70;
  if (opsPerMonth >= 2) return 50;
  if (opsPerMonth >= 1) return 30;
  return 10;
}

function scoreMonetary(avgMonthlyVol) {
  if (!avgMonthlyVol || avgMonthlyVol <= 0) return 0;
  if (avgMonthlyVol >= 100000) return 100;
  if (avgMonthlyVol >= 50000) return 85;
  if (avgMonthlyVol >= 20000) return 70;
  if (avgMonthlyVol >= 5000) return 50;
  if (avgMonthlyVol >= 1000) return 30;
  return 10;
}

function scoreVelocity(currPeriodOps, prevPeriodOps) {
  if (!prevPeriodOps || prevPeriodOps <= 0) {
    return currPeriodOps > 0 ? 60 : 0; // New client or dormant
  }
  const ratio = currPeriodOps / prevPeriodOps;
  if (ratio >= 1.5) return 100;  // Strong growth
  if (ratio >= 1.1) return 85;   // Growth
  if (ratio >= 0.9) return 70;   // Stable
  if (ratio >= 0.7) return 40;   // Declining
  if (ratio >= 0.5) return 20;   // Significant decline
  return 5;                       // Severe decline
}

function scoreEngagement(monthsActive, productCount) {
  // Product count: 1 = single flow, 2 = both BRL→USD and USD→BRL, 3 = includes checkout
  const tenurePts = Math.min(monthsActive || 0, 24) / 24 * 50;
  const productPts = Math.min(productCount || 1, 3) / 3 * 50;
  return Math.round(tenurePts + productPts);
}

/**
 * Predict churn risk for a client
 * @param {Object} clientData - Client profile data
 * @param {number} clientData.days_inactive - Days since last transaction
 * @param {number} clientData.avg_monthly_ops - Average operations per month
 * @param {number} clientData.avg_monthly_vol - Average monthly volume in USD
 * @param {number} clientData.months_active - Total months with activity
 * @param {number} [clientData.curr_ops] - Current period operations
 * @param {number} [clientData.prev_ops] - Previous period operations
 * @param {number} [clientData.product_count] - Number of products used (1-3)
 * @returns {{ score: number, risk: string, factors: Object[] }}
 */
function predictChurnRisk(clientData) {
  const scores = {
    recency: scoreRecency(clientData.days_inactive),
    frequency: scoreFrequency(clientData.avg_monthly_ops),
    monetary: scoreMonetary(clientData.avg_monthly_vol),
    velocity: scoreVelocity(clientData.curr_ops || 0, clientData.prev_ops || 0),
    engagement: scoreEngagement(clientData.months_active, clientData.product_count || 1)
  };

  // Weighted score (0-100, higher = healthier)
  const healthScore = Math.round(
    scores.recency * WEIGHTS.recency +
    scores.frequency * WEIGHTS.frequency +
    scores.monetary * WEIGHTS.monetary +
    scores.velocity * WEIGHTS.velocity +
    scores.engagement * WEIGHTS.engagement
  );

  // Invert to churn risk (0-100, higher = more likely to churn)
  const churnScore = 100 - healthScore;

  let risk;
  if (churnScore >= 75) risk = 'critical';
  else if (churnScore >= 50) risk = 'high';
  else if (churnScore >= 25) risk = 'medium';
  else risk = 'low';

  // Identify key risk factors
  const factors = Object.entries(scores)
    .map(([name, score]) => ({
      name,
      score,
      weight: WEIGHTS[name],
      contribution: Math.round((100 - score) * WEIGHTS[name]),
      status: score >= 70 ? 'good' : score >= 40 ? 'warning' : 'critical'
    }))
    .sort((a, b) => b.contribution - a.contribution);

  return {
    score: churnScore,
    health_score: healthScore,
    risk,
    factors
  };
}

module.exports = { predictChurnRisk };
