// ============================================================
//  levelIncomeHelper.js  –  7-Level Plan-Based Income Engine
// ============================================================
//
//  Plan Structure:
//  Plan 1 → ₹1,500   Plan 2 → ₹3,000   Plan 3 → ₹6,000
//  Plan 4 → ₹12,000  Plan 5 → ₹24,000  Plan 6 → ₹48,000
//  Plan 7 → ₹96,000
//
//  Level Income %:
//  L1 → 20%  |  L2 → 10%  |  L3 → 5%  |  L4 → 3%  |  L5 → 1%  |  L6 → 0.5%  |  L7 → 0.5%
//
//  TWO Triggers:
//  1. distributeLevelIncome(newMemberId)
//     → Jab naya member approve ho
//     → Upline ko min(upline_plan, buyer_plan) tak ke SAARE slabs ka income
//
//  2. distributeUpgradeIncome(upgradedMemberId, newPlanAmount)
//     → Jab Star Club mein plan upgrade ho
//     → Upline ko SIRF naye slab (newPlanAmount) ka income
//     → min(upline_plan_index, newSlabIndex) check hoga
// ============================================================

import db from '../config/database.js';

// ─────────────────────────────────────────────
//  Constants
// ─────────────────────────────────────────────

/** Plan slabs in ascending order (₹) */
const PLAN_SLABS = [1500, 3000, 6000, 12000, 24000, 48000, 96000];

/** Level-wise income percentage (index 0 = Level 1)
 *  L1=20%  L2=10%  L3=5%  L4=3%  L5=1%  L6=0.5%  L7=0.5% */
const LEVEL_PERCENT = [0.20, 0.10, 0.05, 0.03, 0.01, 0.005, 0.005];

/** Maximum depth of upline chain to pay */
const MAX_LEVELS = 7;

// ─────────────────────────────────────────────
//  Helper: Get plan index (0-based) from plan amount
//  Returns -1 if plan amount not found
// ─────────────────────────────────────────────
const getPlanIndex = (planAmount) => {
  const amount = parseFloat(planAmount);
  return PLAN_SLABS.indexOf(amount);
};

// ─────────────────────────────────────────────
//  Helper: Credit level income to one upline member
// ─────────────────────────────────────────────
const creditLevelIncome = async ({
  memberUUID,
  memberCode,
  amount,
  buyerCode,
  level,
  orderId,
  description,
}) => {
  // Update wallet + level_income + total_income
  await db.query(
    `UPDATE members
        SET wallet_balance = wallet_balance + ?,
            level_income   = level_income   + ?,
            total_income   = total_income   + ?,
            updated_at     = NOW()
      WHERE id = ?`,
    [amount, amount, amount, memberUUID]
  );

  // Insert transaction record
  await db.query(
    `INSERT INTO transactions
       (user_type, user_id, user_member_id, transaction_type,
        amount, description, order_id, created_at)
     VALUES ('member', ?, ?, 'LEVEL_INCOME', ?, ?, ?, NOW())`,
    [memberUUID, memberCode, amount, description, orderId ?? null]
  );

  console.log(
    `✅ [LEVEL_INCOME L${level}] ₹${amount.toLocaleString('en-IN')} → ${memberCode} | from ${buyerCode}`
  );
};

// ─────────────────────────────────────────────
//  Main Export: Called from approveMember
//
//  @param newMemberId  – UUID (id) of the newly approved member
//  @param orderId      – order ID if available (optional)
// ─────────────────────────────────────────────
export const distributeLevelIncome = async (newMemberId, orderId = null) => {
  try {
    // ── Step 1: Fetch newly approved member ──────────────────
    const [buyerRows] = await db.query(
      `SELECT id, member_id, sponsor_id, plan
         FROM members WHERE id = ?`,
      [newMemberId]
    );
    if (!buyerRows?.length) {
      console.warn(`⚠️ [LEVEL_INCOME] Member not found: ${newMemberId}`);
      return;
    }

    const buyer         = buyerRows[0];
    const buyerPlanIdx  = getPlanIndex(buyer.plan);

    if (buyerPlanIdx === -1) {
      console.warn(`⚠️ [LEVEL_INCOME] Unknown plan amount for ${buyer.member_id}: ${buyer.plan}`);
      return;
    }

    if (!buyer.sponsor_id) {
      console.log(`ℹ️ [LEVEL_INCOME] ${buyer.member_id} has no sponsor. Skipping.`);
      return;
    }

    // ── Step 2: Walk upline chain up to MAX_LEVELS ───────────
    const visited    = new Set();
    let currentCode  = buyer.sponsor_id;  // start from direct sponsor (L1)
    let level        = 1;

    while (currentCode && !visited.has(currentCode) && level <= MAX_LEVELS) {
      visited.add(currentCode);

      // Fetch this upline member
      const [uplineRows] = await db.query(
        `SELECT id, member_id, sponsor_id, plan
           FROM members WHERE member_id = ?`,
        [currentCode]
      );

      if (!uplineRows?.length) {
        console.warn(`⚠️ [LEVEL_INCOME] Upline member not found: ${currentCode}`);
        break;
      }

      const upline        = uplineRows[0];
      const uplinePlanIdx = getPlanIndex(upline.plan);

      if (uplinePlanIdx === -1) {
        console.warn(`⚠️ [LEVEL_INCOME] Unknown plan for upline ${upline.member_id}: ${upline.plan}`);
        // Still continue chain, just skip income for this one
        currentCode = upline.sponsor_id;
        level++;
        continue;
      }

      // ── Step 3: Calculate income for this upline ───────────
      // Eligible slabs = min(upline plan index, buyer plan index)
      // e.g. buyer plan = ₹3000 (idx 1), upline plan = ₹6000 (idx 2)
      //   → eligible up to idx 1 → slabs [1500, 3000]
      const eligibleUpToIdx = Math.min(uplinePlanIdx, buyerPlanIdx);
      const levelPercent    = LEVEL_PERCENT[level - 1]; // 0-based array

      // Sum income across all eligible slabs
      let totalIncomeForLevel = 0;
      const slabBreakdown     = [];

      for (let slabIdx = 0; slabIdx <= eligibleUpToIdx; slabIdx++) {
        const slabAmount  = PLAN_SLABS[slabIdx];
        const slabIncome  = slabAmount * levelPercent;
        totalIncomeForLevel += slabIncome;
        slabBreakdown.push(`₹${slabAmount}×${levelPercent * 100}%=₹${slabIncome}`);
      }

      if (totalIncomeForLevel > 0) {
        const description =
          `L${level} Income from ${buyer.member_id} | Slabs: ${slabBreakdown.join(', ')}`;

        await creditLevelIncome({
          memberUUID: upline.id,
          memberCode: upline.member_id,
          amount:     totalIncomeForLevel,
          buyerCode:  buyer.member_id,
          level,
          orderId,
          description,
        });
      }

      // Move up the chain
      currentCode = upline.sponsor_id;
      level++;
    }

    console.log(`🎉 [LEVEL_INCOME] Distribution complete for new member ${buyer.member_id}`);

  } catch (error) {
    // Income failure should NOT block member approval
    console.error('❌ distributeLevelIncome error:', error.message);
  }
};

// ─────────────────────────────────────────────
//  Export 2: Star Club Plan Upgrade Income
//
//  Jab Star Club mein kisi member ka plan upgrade ho,
//  uske upline chain ko SIRF us naye slab (newPlanAmount) ka income milega.
//
//  Rule:
//  - Upline ka plan >= newPlanAmount  → income milegi (full new slab %)
//  - Upline ka plan <  newPlanAmount  → income milegi upline ke plan tak
//    (kyunki upline khud us slab par nahi hai)
//    Actually: min(upline_plan_index, newSlabIndex) — same logic as registration
//    BUT sirf newSlab ki percentage calculate hogi, sab slabs nahi.
//
//  Example:
//    Member 1500→3000 upgrade hua
//    L1 upline ka plan = 6000 → sirf 3000 slab ka income = 3000 × 20% = ₹600
//    L1 upline ka plan = 1500 → upline khud 3000 par nahi → skip (0 income)
//
//  @param upgradedMemberId  – UUID (id) of the member whose plan upgraded
//  @param oldPlanAmount     – plan amount BEFORE upgrade (e.g. 1500)
//  @param newPlanAmount     – plan amount AFTER  upgrade (e.g. 3000)
// ─────────────────────────────────────────────
export const distributeUpgradeIncome = async (upgradedMemberId, oldPlanAmount, newPlanAmount) => {
  try {
    const newSlabIdx = getPlanIndex(newPlanAmount);
    const oldSlabIdx = getPlanIndex(oldPlanAmount);

    if (newSlabIdx === -1) {
      console.warn(`⚠️ [UPGRADE_INCOME] Unknown new plan amount: ${newPlanAmount}`);
      return;
    }
    if (newSlabIdx <= oldSlabIdx) {
      console.log(`ℹ️ [UPGRADE_INCOME] No upgrade detected (old: ${oldPlanAmount}, new: ${newPlanAmount}). Skipping.`);
      return;
    }

    // Fetch upgraded member to get sponsor chain start
    const [memberRows] = await db.query(
      `SELECT id, member_id, sponsor_id FROM members WHERE id = ?`,
      [upgradedMemberId]
    );
    if (!memberRows?.length) {
      console.warn(`⚠️ [UPGRADE_INCOME] Member not found: ${upgradedMemberId}`);
      return;
    }

    const upgradedMember = memberRows[0];

    if (!upgradedMember.sponsor_id) {
      console.log(`ℹ️ [UPGRADE_INCOME] No sponsor for ${upgradedMember.member_id}. Skipping.`);
      return;
    }

    // Walk upline chain up to MAX_LEVELS
    const visited   = new Set();
    let currentCode = upgradedMember.sponsor_id;   // L1 = direct sponsor
    let level       = 1;

    while (currentCode && !visited.has(currentCode) && level <= MAX_LEVELS) {
      visited.add(currentCode);

      const [uplineRows] = await db.query(
        `SELECT id, member_id, sponsor_id, plan FROM members WHERE member_id = ?`,
        [currentCode]
      );

      if (!uplineRows?.length) {
        console.warn(`⚠️ [UPGRADE_INCOME] Upline not found: ${currentCode}`);
        break;
      }

      const upline        = uplineRows[0];
      const uplinePlanIdx = getPlanIndex(upline.plan);

      if (uplinePlanIdx === -1) {
        console.warn(`⚠️ [UPGRADE_INCOME] Unknown plan for upline ${upline.member_id}: ${upline.plan}`);
        currentCode = upline.sponsor_id;
        level++;
        continue;
      }

      // Upline must be at least on the new slab to earn income for it
      // If upline plan < newPlanAmount → upline not eligible for this slab
      if (uplinePlanIdx < newSlabIdx) {
        console.log(
          `⏭️ [UPGRADE_INCOME L${level}] ${upline.member_id} plan ₹${upline.plan} < new slab ₹${newPlanAmount} → skipped`
        );
        currentCode = upline.sponsor_id;
        level++;
        continue;
      }

      // Upline is eligible — income = newPlanAmount × levelPercent ONLY
      const levelPercent = LEVEL_PERCENT[level - 1];
      const incomeAmount = newPlanAmount * levelPercent;

      const description =
        `L${level} Upgrade Income | ${upgradedMember.member_id} upgraded ₹${oldPlanAmount}→₹${newPlanAmount} | ` +
        `₹${newPlanAmount}×${levelPercent * 100}%=₹${incomeAmount}`;

      await creditLevelIncome({
        memberUUID: upline.id,
        memberCode: upline.member_id,
        amount:     incomeAmount,
        buyerCode:  upgradedMember.member_id,
        level,
        orderId:    null,
        description,
      });

      currentCode = upline.sponsor_id;
      level++;
    }

    console.log(
      `🎉 [UPGRADE_INCOME] Distribution complete for upgrade ${upgradedMember.member_id} ` +
      `₹${oldPlanAmount}→₹${newPlanAmount}`
    );

  } catch (error) {
    console.error('❌ distributeUpgradeIncome error:', error.message);
  }
};