import { BN, fromUnitToToken } from '@ocap/util';
import { Op } from 'sequelize';

import pick from 'lodash/pick';
import {
  Coupon,
  Customer,
  Discount,
  PromotionCode,
  Subscription,
  CheckoutSession,
  PaymentCurrency,
} from '../../store/models';
import type { TLineItemExpanded } from '../../store/models';
import logger from '../logger';
import { emitAsync } from '../event';
import { formatNumber } from '../util';

export function validCoupon(coupon: Coupon, lineItems?: TLineItemExpanded[]) {
  if (!coupon.valid) {
    return { valid: false, reason: 'This coupon is no longer available' };
  }
  if (coupon.redeem_by && Math.floor(Date.now() / 1000) > coupon.redeem_by) {
    return { valid: false, reason: 'This coupon has expired and cannot be used' };
  }
  if (coupon.max_redemptions && (coupon.times_redeemed ?? 0) >= coupon.max_redemptions) {
    return { valid: false, reason: 'This coupon has been fully redeemed and is no longer available' };
  }
  if (lineItems && lineItems.length > 0 && coupon.applies_to?.products) {
    const applicableProducts = coupon.applies_to?.products;
    if (applicableProducts && applicableProducts.length > 0) {
      const hasApplicableProduct = lineItems.some((item) => applicableProducts.includes(item.price?.product_id));
      if (!hasApplicableProduct) {
        return { valid: false, reason: 'This coupon cannot be applied to the items in your cart' };
      }
    }
  }
  return { valid: true };
}

export async function validPromotionCode(
  promotionCode: PromotionCode,
  {
    customerId,
    amount,
    currencyId,
    checkoutSessionId,
  }: {
    customerId?: string;
    amount?: string;
    currencyId?: string;
    checkoutSessionId?: string;
  }
) {
  if (!promotionCode.active) {
    return { valid: false, reason: 'This promotion code is no longer available' };
  }
  if (promotionCode.expires_at && Math.floor(Date.now() / 1000) > promotionCode.expires_at) {
    return { valid: false, reason: 'This promotion code has expired and cannot be used' };
  }
  if (promotionCode.max_redemptions && (promotionCode.times_redeemed ?? 0) >= promotionCode.max_redemptions) {
    return { valid: false, reason: 'This promotion code has been fully redeemed and is no longer available' };
  }
  if (customerId) {
    const customer = await Customer.findByPkOrDid(customerId);
    // For user_restricted promo codes, check DID against allowed list
    // customer?.did works when Customer record exists; customerId itself may be a DID for new users
    const customerDid = customer?.did || customerId;
    if (promotionCode.verification_type === 'user_restricted' && customerDid) {
      if (!promotionCode.customer_dids?.includes(customerDid)) {
        return { valid: false, reason: 'This promotion code is not available for your account' };
      }
    }
    if (promotionCode.restrictions?.first_time_transaction) {
      const whereClause: any = { customer_id: customerId, coupon_id: promotionCode.coupon_id };
      // Exclude discount records from the current checkout session (re-submit scenario)
      if (checkoutSessionId) {
        whereClause.checkout_session_id = { [Op.ne]: checkoutSessionId };
      }
      const previousDiscounts = await Discount.count({ where: whereClause });
      if (previousDiscounts > 0) {
        return { valid: false, reason: 'This promotion is only available for first-time purchases' };
      }
    }
  }
  if (
    amount &&
    currencyId &&
    (promotionCode.restrictions?.minimum_amount || promotionCode.restrictions?.currency_options?.[currencyId])
  ) {
    const minimumAmount =
      currencyId === promotionCode.restrictions?.minimum_amount_currency
        ? promotionCode.restrictions?.minimum_amount
        : promotionCode.restrictions?.currency_options?.[currencyId]?.minimum_amount;

    const currency = await PaymentCurrency.findByPk(currencyId);
    if (minimumAmount) {
      const amountBN = new BN(amount);
      const minimumBN = new BN(minimumAmount);
      if (amountBN.lt(minimumBN)) {
        if (!currency) {
          return {
            valid: false,
            reason: 'This promotion requires a minimum purchase amount. Please add more items to your cart.',
          };
        }
        return {
          valid: false,
          reason: `This promotion requires a minimum purchase amount of ${formatNumber(fromUnitToToken(minimumBN, currency?.decimal || 2))} ${currency?.symbol}. Please add more items to your cart.`,
        };
      }
    }
  }
  return { valid: true };
}

// Calculate actual discount amount (not the remaining amount after discount)
export function calculateDiscountAmount(
  coupon: Coupon,
  amount: string,
  currency: { id: string; decimal: number; symbol: string }
): string {
  if (coupon.percent_off > 0) {
    // Calculate percentage discount
    const discountAmount = new BN(amount).mul(new BN(coupon.percent_off)).div(new BN(100));
    return discountAmount.toString();
  }

  if (coupon.amount_off) {
    // Calculate fixed amount discount
    const amountOff =
      coupon.currency_id === currency.id ? coupon.amount_off : coupon.currency_options?.[currency.id]?.amount_off;

    if (amountOff) {
      // Return the smaller of discount amount or total amount
      const discountBN = new BN(amountOff);
      const totalBN = new BN(amount);
      return BN.min(discountBN, totalBN).toString();
    }
  }

  return '0';
}

/**
 * Lock coupon and promotion code when discount is created/applied
 */
export async function lockDiscountResources(couponId: string, promotionCodeId?: string): Promise<void> {
  try {
    // Lock the coupon
    if (couponId) {
      const coupon = await Coupon.findByPk(couponId);
      if (coupon && !coupon.locked) {
        await coupon.update({ locked: true });
        logger.info('Locked coupon when creating discount', {
          couponId,
        });
      }
    }

    // Lock the promotion code if it exists
    if (promotionCodeId) {
      const promotionCode = await PromotionCode.findByPk(promotionCodeId);
      if (promotionCode && !promotionCode.locked) {
        await promotionCode.update({ locked: true });
        logger.info('Locked promotion code when creating discount', {
          promotionCodeId,
        });
      }
    }
  } catch (error) {
    logger.error('Error locking discount resources', {
      couponId,
      promotionCodeId,
      error: error.message,
    });
  }
}

/**
 * Get discount records for a checkout session
 * Used when creating invoices/subscriptions to include discount information
 */
export async function getDiscountRecordsForCheckout({
  checkoutSessionId,
  customerId,
}: {
  checkoutSessionId: string;
  customerId: string;
}): Promise<{
  discountRecords: any[];
  appliedDiscounts: string[];
  discountBreakdown: Array<{ amount: string; discount: string }>;
}> {
  const discountRecords = await Discount.findAll({
    where: {
      customer_id: customerId,
      checkout_session_id: checkoutSessionId,
    },
    include: [
      { model: Coupon, as: 'coupon' },
      { model: PromotionCode, as: 'promotionCode', required: false },
    ],
  });

  if (discountRecords.length === 0) {
    return {
      discountRecords: [],
      appliedDiscounts: [],
      discountBreakdown: [],
    };
  }

  const appliedDiscounts = discountRecords.map((d) => d.id);
  const discountBreakdown = discountRecords.map((d) => ({
    amount: d.metadata?.discount_amount || '0',
    discount: d.id,
  }));

  logger.info('Retrieved discount records for checkout session', {
    checkoutSessionId,
    customerId,
    recordCount: discountRecords.length,
  });

  return {
    discountRecords,
    appliedDiscounts,
    discountBreakdown,
  };
}

/**
 * Get existing discount records for a checkout session
 */
async function getExistingDiscountRecords(customerId: string, checkoutSessionId: string) {
  try {
    const existingDiscounts = await Discount.findAll({
      where: {
        customer_id: customerId,
        checkout_session_id: checkoutSessionId,
      },
    });

    const existingDiscountMap = new Map();
    existingDiscounts.forEach((discount) => {
      const key = discount.subscription_id || 'no_subscription';
      existingDiscountMap.set(key, discount);
    });

    return existingDiscountMap;
  } catch (error) {
    logger.error('Error fetching existing discount records', {
      customerId,
      checkoutSessionId,
      error: error.message,
    });
    throw new Error(`Failed to fetch existing discount records: ${error.message}`);
  }
}

/**
 * Build base discount data from checkout session and coupon info
 */
function buildBaseDiscountData({
  checkoutSession,
  customerId,
  coupon,
  promotionCode,
  discountAmount,
  verificationData,
}: {
  checkoutSession: CheckoutSession;
  customerId: string;
  coupon: Coupon;
  promotionCode?: PromotionCode;
  discountAmount: string;
  verificationData?: any;
}) {
  const now = Math.floor(Date.now() / 1000);
  let endTime: number | undefined;

  if (coupon.duration === 'once') {
    endTime = now + 60;
  } else if (coupon.duration === 'repeating' && coupon.duration_in_months) {
    const endDate = new Date();
    endDate.setMonth(endDate.getMonth() + coupon.duration_in_months);
    endTime = Math.floor(endDate.getTime() / 1000);
  }

  return {
    livemode: coupon.livemode,
    coupon_id: coupon.id,
    promotion_code_id: promotionCode?.id,
    customer_id: customerId,
    checkout_session_id: checkoutSession.id,
    start: now,
    end: endTime,
    verification_method: promotionCode?.verification_type,
    verification_data: verificationData || checkoutSession.metadata?.verification_data,
    metadata: {
      discount_amount: discountAmount,
      original_amount: checkoutSession.amount_subtotal,
      final_amount: checkoutSession.amount_total,
      currency_id: checkoutSession.currency_id,
      applied_at: new Date().toISOString(),
    },
  };
}

/**
 * Process discount record for a single subscription
 */
async function processSubscriptionDiscount({
  subscriptionId,
  baseDiscountData,
  existingDiscountMap,
  checkoutSessionId,
}: {
  subscriptionId: string;
  baseDiscountData: any;
  existingDiscountMap: Map<string, any>;
  checkoutSessionId: string;
}): Promise<{ discountRecord: Discount; shouldUpdateUsage: boolean }> {
  try {
    const existingDiscount = existingDiscountMap.get(subscriptionId);

    if (existingDiscount) {
      const couponChanged = existingDiscount.coupon_id !== baseDiscountData.coupon_id;
      const promoChanged = existingDiscount.promotion_code_id !== baseDiscountData.promotion_code_id;

      const updated = await existingDiscount.update({
        ...baseDiscountData,
        subscription_id: subscriptionId,
      });

      logger.info('Upserted discount record for subscription', {
        checkoutSessionId,
        subscriptionId,
        discountId: updated.id,
        couponChanged,
        promoChanged,
      });

      return { discountRecord: updated, shouldUpdateUsage: couponChanged || promoChanged };
    }

    // Create new discount record
    const newDiscount = await Discount.create({
      ...baseDiscountData,
      subscription_id: subscriptionId,
      confirmed: false,
      metadata: {
        ...baseDiscountData.metadata,
        subscription_id: subscriptionId,
      },
    });

    // Lock coupon and promotion code when discount is created
    await lockDiscountResources(baseDiscountData.coupon_id, baseDiscountData.promotion_code_id);

    logger.info('Created new discount record for subscription', {
      checkoutSessionId,
      subscriptionId,
      discountId: newDiscount.id,
    });

    return { discountRecord: newDiscount, shouldUpdateUsage: true };
  } catch (error) {
    logger.error('Error processing subscription discount', {
      subscriptionId,
      checkoutSessionId,
      error: error.message,
    });
    throw new Error(`Failed to process subscription discount: ${error.message}`);
  }
}

/**
 * Process discount record for non-subscription case
 */
async function processNonSubscriptionDiscount(
  baseDiscountData: any,
  existingDiscountMap: Map<string, any>,
  checkoutSessionId: string
): Promise<{ discountRecord: Discount; shouldUpdateUsage: boolean }> {
  try {
    const existingDiscount = existingDiscountMap.get('no_subscription');

    if (existingDiscount) {
      const couponChanged = existingDiscount.coupon_id !== baseDiscountData.coupon_id;
      const promoChanged = existingDiscount.promotion_code_id !== baseDiscountData.promotion_code_id;

      const updated = await existingDiscount.update({
        ...baseDiscountData,
      });

      logger.info('Upserted single discount record', {
        checkoutSessionId,
        discountId: updated.id,
        couponChanged,
        promoChanged,
      });

      return { discountRecord: updated, shouldUpdateUsage: couponChanged || promoChanged };
    }

    // Create new discount record
    const newDiscount = await Discount.create({
      ...baseDiscountData,
      confirmed: false,
    });

    // Lock coupon and promotion code when discount is created
    await lockDiscountResources(baseDiscountData.coupon_id, baseDiscountData.promotion_code_id);

    logger.info('Created new single discount record', {
      checkoutSessionId,
      discountId: newDiscount.id,
    });

    return { discountRecord: newDiscount, shouldUpdateUsage: true };
  } catch (error) {
    logger.error('Error processing non-subscription discount', {
      checkoutSessionId,
      error: error.message,
    });
    throw new Error(`Failed to process non-subscription discount: ${error.message}`);
  }
}

/**
 * Update usage counts for coupons and promotion codes
 * Uses checkout session ID to prevent duplicate counting when multiple subscriptions are created
 */
async function updateUsageCounts({
  coupon,
  promotionCode,
  updatedCoupons,
  updatedPromotionCodes,
  checkoutSessionId,
}: {
  coupon: Coupon;
  promotionCode?: PromotionCode;
  updatedCoupons: Set<string>;
  updatedPromotionCodes: Set<string>;
  checkoutSessionId: string;
}): Promise<void> {
  try {
    const updatePromises = [] as Array<Promise<any>>;

    // Create unique keys based on checkout session to prevent duplicate counting
    const couponSessionKey = `${coupon.id}-${checkoutSessionId}`;
    const promotionCodeSessionKey = promotionCode ? `${promotionCode.id}-${checkoutSessionId}` : '';

    if (!updatedCoupons.has(couponSessionKey)) {
      updatedCoupons.add(couponSessionKey);
      updatePromises.push(
        coupon.update({
          times_redeemed: (coupon.times_redeemed || 0) + 1,
        })
      );
    }

    if (promotionCode && promotionCodeSessionKey && !updatedPromotionCodes.has(promotionCodeSessionKey)) {
      updatedPromotionCodes.add(promotionCodeSessionKey);
      updatePromises.push(
        promotionCode.update({
          times_redeemed: (promotionCode.times_redeemed || 0) + 1,
        })
      );
    }

    await Promise.all(updatePromises);
    emitAsync('discount-status.queued', coupon, 'coupon', true);
    if (promotionCode) {
      emitAsync('discount-status.queued', promotionCode, 'promotion-code', true);
    }

    logger.debug('Updated coupon and promotion code usage counts', {
      checkoutSessionId,
      couponId: coupon.id,
      promotionCodeId: promotionCode?.id,
    });
  } catch (error) {
    logger.error('Error updating usage counts', {
      checkoutSessionId,
      couponId: coupon.id,
      promotionCodeId: promotionCode?.id,
      error: error.message,
    });
    throw new Error(`Failed to update usage counts: ${error.message}`);
  }
}

/**
 * Update subscription discount_id references after discount records are created/updated
 */
export async function updateSubscriptionDiscountReferences({
  discountRecords,
  subscriptionsUpdated,
}: {
  discountRecords: any[];
  subscriptionsUpdated: string[];
}): Promise<{ updatedSubscriptions: string[] }> {
  if (subscriptionsUpdated.length === 0) {
    return { updatedSubscriptions: [] };
  }

  const updatedSubscriptions: string[] = [];

  try {
    logger.info('Updating subscription discount_id references', {
      subscriptionsToUpdate: subscriptionsUpdated.length,
    });

    const subscriptionUpdatePromises = subscriptionsUpdated.map(async (subscriptionId) => {
      try {
        // Find the discount record for this subscription
        const discountRecord = discountRecords.find((d) => d.subscription_id === subscriptionId);
        if (!discountRecord) {
          logger.warn('No discount record found for subscription', { subscriptionId });
          return null;
        }

        // Update subscription with discount_id
        const [updateCount] = await Subscription.update(
          { discount_id: discountRecord.id },
          { where: { id: subscriptionId } }
        );

        if (updateCount > 0) {
          logger.debug('Updated subscription discount_id', {
            subscriptionId,
            discountId: discountRecord.id,
          });
          return subscriptionId;
        }

        logger.warn('Subscription not found for discount_id update', { subscriptionId });
        return null;
      } catch (error) {
        logger.error('Failed to update subscription discount_id', {
          subscriptionId,
          error: error.message,
        });
        return null;
      }
    });

    const updateResults = await Promise.all(subscriptionUpdatePromises);
    updatedSubscriptions.push(...updateResults.filter((id) => id !== null));

    logger.info('Completed subscription discount_id reference updates', {
      requestedUpdates: subscriptionsUpdated.length,
      successfulUpdates: updatedSubscriptions.length,
    });

    return { updatedSubscriptions };
  } catch (error) {
    logger.error('Error updating subscription discount references', {
      subscriptionsUpdated,
      error: error.message,
    });
    throw new Error(`Failed to update subscription discount references: ${error.message}`);
  }
}

/**
 * Create or update discount records for a completed checkout session
 * This creates/updates the actual discount records and manages usage counts
 * For subscriptions, creates separate discount records for each subscription
 * Handles deduplication and updates when coupon/promotion code changes
 */
export async function createDiscountRecordsForCheckout({
  checkoutSession,
  customerId,
  subscriptionIds = [],
}: {
  checkoutSession: any; // CheckoutSession type
  customerId: string;
  subscriptionIds?: string[];
}): Promise<{
  discountRecords: any[];
  updatedCoupons: string[];
  updatedPromotionCodes: string[];
  subscriptionsUpdated: string[];
}> {
  if (!checkoutSession.discounts?.length) {
    return { discountRecords: [], updatedCoupons: [], updatedPromotionCodes: [], subscriptionsUpdated: [] };
  }

  logger.info('Creating/updating discount records for checkout session', {
    checkoutSessionId: checkoutSession.id,
    customerId,
    subscriptionIds,
  });

  try {
    // Get existing discount records
    const existingDiscountMap = await getExistingDiscountRecords(customerId, checkoutSession.id);

    const updatedCoupons = new Set<string>();
    const updatedPromotionCodes = new Set<string>();
    const allDiscountRecords: any[] = [];
    const subscriptionsUpdated: string[] = [];

    // Process each discount configuration
    const discountProcessingPromises = checkoutSession.discounts.map(async (discount: any) => {
      const { promotion_code: promotionCodeId, coupon: couponId, discount_amount: discountAmount } = discount;

      if (!couponId) {
        logger.warn('Incomplete discount configuration, skipping', {
          checkoutSessionId: checkoutSession.id,
          hasCoupon: !!couponId,
        });
        return null;
      }

      try {
        // Fetch coupon and promotion code
        const [coupon, promotionCode] = await Promise.all([
          Coupon.findByPk(couponId),
          promotionCodeId ? PromotionCode.findByPk(promotionCodeId) : Promise.resolve(null),
        ]);

        if (!coupon) {
          logger.warn('Coupon not found, skipping discount', {
            couponId,
            checkoutSessionId: checkoutSession.id,
          });
          return null;
        }

        // Build base discount data
        const baseDiscountData = buildBaseDiscountData({
          checkoutSession,
          customerId,
          coupon,
          promotionCode: promotionCode || undefined,
          discountAmount,
          verificationData: discount.verification_data,
        });

        const discountRecords: any[] = [];
        let shouldUpdateUsageCount = false;
        const currentSubscriptionsUpdated: string[] = [];

        // Process subscriptions
        if (subscriptionIds.length > 0) {
          const subscriptionProcessingPromises = subscriptionIds.map(async (subscriptionId) => {
            try {
              const result = await processSubscriptionDiscount({
                subscriptionId,
                baseDiscountData,
                existingDiscountMap,
                checkoutSessionId: checkoutSession.id,
              });

              if (result.shouldUpdateUsage) {
                currentSubscriptionsUpdated.push(subscriptionId);
              }

              return result.discountRecord;
            } catch (error) {
              logger.error('Failed to process subscription discount, continuing with others', {
                subscriptionId,
                error: error.message,
              });
              return null;
            }
          });

          const subscriptionResults = await Promise.all(subscriptionProcessingPromises);
          discountRecords.push(...subscriptionResults.filter((record) => record !== null));

          if (currentSubscriptionsUpdated.length > 0) {
            shouldUpdateUsageCount = true;
          }
        } else {
          // Process non-subscription case
          try {
            const result = await processNonSubscriptionDiscount(
              baseDiscountData,
              existingDiscountMap,
              checkoutSession.id
            );

            discountRecords.push(result.discountRecord);
            shouldUpdateUsageCount = result.shouldUpdateUsage;
          } catch (error) {
            logger.error('Failed to process non-subscription discount', {
              checkoutSessionId: checkoutSession.id,
              error: error.message,
            });
            throw error;
          }
        }

        // Update usage counts if needed
        if (shouldUpdateUsageCount) {
          try {
            await updateUsageCounts({
              coupon,
              promotionCode: promotionCode || undefined,
              updatedCoupons,
              updatedPromotionCodes,
              checkoutSessionId: checkoutSession.id,
            });
            await Promise.all(
              discountRecords.map(async (discountRecord) => {
                await discountRecord.update({
                  confirmed: true,
                });
              })
            );
          } catch (error) {
            logger.error('Failed to update usage counts, but continuing', {
              couponId: coupon.id,
              promotionCodeId: promotionCode?.id,
              error: error.message,
            });
          }
        }

        return {
          discountRecords,
          subscriptionsUpdated: currentSubscriptionsUpdated,
        };
      } catch (error) {
        logger.error('Error processing discount configuration, skipping', {
          couponId,
          promotionCodeId,
          checkoutSessionId: checkoutSession.id,
          error: error.message,
        });
        return null;
      }
    });

    const processingResults = await Promise.all(discountProcessingPromises);

    // Aggregate results
    processingResults.forEach((result) => {
      if (result) {
        allDiscountRecords.push(...result.discountRecords);
        subscriptionsUpdated.push(...result.subscriptionsUpdated);
      }
    });

    logger.info('All discount records processed successfully', {
      checkoutSessionId: checkoutSession.id,
      customerId,
      totalRecords: allDiscountRecords.length,
      subscriptionCount: subscriptionIds.length,
      subscriptionsUpdated: subscriptionsUpdated.length,
      updatedCouponsCount: updatedCoupons.size,
      updatedPromotionCodesCount: updatedPromotionCodes.size,
    });

    return {
      discountRecords: allDiscountRecords,
      updatedCoupons: Array.from(updatedCoupons),
      updatedPromotionCodes: Array.from(updatedPromotionCodes),
      subscriptionsUpdated,
    };
  } catch (error) {
    logger.error('Critical error processing discount records for checkout', {
      checkoutSessionId: checkoutSession.id,
      customerId,
      subscriptionIds,
      error: error.message,
    });
    throw new Error(`Failed to process discount records: ${error.message}`);
  }
}

// Unified promotion code eligibility check
export async function checkPromotionCodeEligibility({
  promotionCode,
  couponId,
  customerId,
  amount,
  currencyId,
  lineItems = [],
  checkoutSessionId,
}: {
  promotionCode: PromotionCode;
  couponId: string;
  customerId: string;
  amount: string;
  currencyId: string;
  lineItems?: TLineItemExpanded[];
  checkoutSessionId?: string;
}): Promise<{ eligible: boolean; reason?: string }> {
  // When re-submitting (e.g. user closed Stripe modal and retries), the current checkout session
  // may already have confirmed Discount records that incremented times_redeemed.
  // We need to exclude the current session's usage from max_redemptions checks to avoid
  // falsely rejecting the promo code that this session itself already consumed.
  let currentSessionUsage = 0;
  if (checkoutSessionId) {
    currentSessionUsage = await Discount.count({
      where: {
        checkout_session_id: checkoutSessionId,
        promotion_code_id: promotionCode.id,
        confirmed: true,
      },
    });
  }

  // Basic promotion code checks
  // When re-submitting, the discount-status queue may have already deactivated the promo code
  // because this session's own usage pushed it past max_redemptions. Skip active check in that case.
  if (!promotionCode.active && currentSessionUsage === 0) {
    return { eligible: false, reason: 'This promotion code is no longer available' };
  }

  if (promotionCode.expires_at && Math.floor(Date.now() / 1000) > promotionCode.expires_at) {
    return { eligible: false, reason: 'This promotion code has expired and cannot be used' };
  }

  if (promotionCode.max_redemptions) {
    const effectiveRedeemed = (promotionCode.times_redeemed ?? 0) - currentSessionUsage;
    if (effectiveRedeemed >= promotionCode.max_redemptions) {
      return { eligible: false, reason: 'This promotion code has been fully redeemed and is no longer available' };
    }
  }

  // Get associated coupon and validate
  const coupon = await Coupon.findByPk(couponId);
  if (!coupon) {
    return { eligible: false, reason: 'This promotion is no longer available' };
  }

  // Coupon validity check — adjust temporarily to exclude current session's usage
  const originalCouponValid = coupon.valid;
  if (currentSessionUsage > 0) {
    if (!coupon.valid) coupon.valid = true;
    if (coupon.times_redeemed && coupon.times_redeemed > 0) {
      coupon.times_redeemed -= currentSessionUsage;
    }
  }
  const couponValidation = validCoupon(coupon, lineItems);
  if (currentSessionUsage > 0) {
    coupon.valid = originalCouponValid;
    if (coupon.times_redeemed != null) {
      coupon.times_redeemed += currentSessionUsage;
    }
  }
  if (!couponValidation.valid) {
    return { eligible: false, reason: couponValidation.reason };
  }

  // Adjust promotionCode temporarily for validPromotionCode's checks
  // Re-submit scenario: restore active + adjust times_redeemed to exclude current session's usage
  const originalActive = promotionCode.active;
  if (currentSessionUsage > 0) {
    if (!promotionCode.active) promotionCode.active = true;
    if (promotionCode.times_redeemed && promotionCode.times_redeemed > 0) {
      promotionCode.times_redeemed -= currentSessionUsage;
    }
  }
  const promotionValidation = await validPromotionCode(promotionCode, {
    customerId,
    amount,
    currencyId,
    checkoutSessionId,
  });
  if (currentSessionUsage > 0) {
    promotionCode.active = originalActive;
    if (promotionCode.times_redeemed != null) {
      promotionCode.times_redeemed += currentSessionUsage;
    }
  }
  if (!promotionValidation.valid) {
    return { eligible: false, reason: promotionValidation.reason };
  }
  return { eligible: true };
}

// Validate discount for billing cycles (subscription invoices)
export async function validateDiscountForBilling({
  discount,
}: {
  discount: Discount;
  subscriptionId?: string;
}): Promise<{ valid: boolean; reason?: string; shouldRemove?: boolean }> {
  const coupon = await Coupon.findByPk(discount.coupon_id);
  if (!coupon) {
    return {
      valid: false,
      reason: 'This discount is no longer available',
      shouldRemove: true,
    };
  }

  const now = Math.floor(Date.now() / 1000);

  // Check discount duration logic
  switch (coupon.duration) {
    case 'once':
      // One-time discounts should not apply to recurring billing
      return {
        valid: false,
        reason: 'One-time discount cannot be applied to subscription billing',
        shouldRemove: true,
      };

    case 'repeating':
      if (!discount.end) {
        return {
          valid: false,
          reason: 'Repeating discount missing end date',
          shouldRemove: true,
        };
      }

      if (now > Number(discount.end)) {
        return {
          valid: false,
          reason: 'Repeating discount has expired',
          shouldRemove: true,
        };
      }
      break;

    case 'forever':
      // Forever discounts are always valid
      break;

    default:
      return {
        valid: false,
        reason: `Unknown coupon duration: ${coupon.duration}`,
        shouldRemove: true,
      };
  }

  return { valid: true };
}

// Get all valid discounts for a subscription's billing period
export async function getValidDiscountsForSubscriptionBilling({
  subscriptionId,
  customerId,
}: {
  subscriptionId: string;
  customerId: string;
}): Promise<{
  validDiscounts: Discount[];
  expiredDiscounts: Discount[];
}> {
  const discounts = await Discount.findAll({
    where: {
      customer_id: customerId,
      subscription_id: subscriptionId,
    },
    include: [
      { model: Coupon, as: 'coupon' },
      { model: PromotionCode, as: 'promotionCode' },
    ],
  });

  const validDiscounts: Discount[] = [];
  const expiredDiscounts: Discount[] = [];

  logger.info('Found discounts for subscription billing', {
    subscriptionId,
    discountCount: discounts.map((d) => d.id),
  });

  await Promise.all(
    discounts.map(async (discount) => {
      const validation = await validateDiscountForBilling({
        discount,
        subscriptionId,
      });

      if (validation.valid) {
        validDiscounts.push(discount);
      } else {
        expiredDiscounts.push(discount);
        logger.info('Expired discount for subscription billing', {
          subscriptionId,
          discountId: discount.id,
          reason: validation.reason,
        });
      }
    })
  );

  return { validDiscounts, expiredDiscounts };
}

/**
 * Expand line items with complete coupon information
 * Similar to Price.expand but for coupon information
 */
export async function expandLineItemsWithCouponInfo(
  lineItems: TLineItemExpanded[],
  sessionDiscounts?: any[],
  currencyId?: string
): Promise<TLineItemExpanded[]> {
  if (!sessionDiscounts?.length) {
    return lineItems;
  }

  const enhancedLineItems = await Promise.all(
    lineItems.map(async (item) => {
      if (!item.discount_amounts?.length) {
        return item;
      }

      const enhancedDiscountAmounts = await Promise.all(
        item.discount_amounts.map(async (discountAmount: any) => {
          let couponInfo = null;
          let promotionCodeInfo = null;

          // Find the discount in checkout session discounts to get IDs
          const sessionDiscount = sessionDiscounts.find((d: any) => d.coupon || d.promotion_code);
          if (sessionDiscount) {
            if (sessionDiscount.coupon) {
              const coupon = await Coupon.findByPk(sessionDiscount.coupon);
              if (coupon) {
                couponInfo = {
                  object: 'coupon',
                  id: coupon.id,
                  name: coupon.name,
                  amount_off: coupon.amount_off,
                  percent_off: coupon.percent_off,
                  currency: coupon.currency_id,
                  duration: coupon.duration,
                  duration_in_months: coupon.duration_in_months,
                  has_applies_to_products: true,
                };
              }
            }

            if (sessionDiscount.promotion_code) {
              const promotionCode = await PromotionCode.findByPk(sessionDiscount.promotion_code);
              if (promotionCode) {
                promotionCodeInfo = {
                  object: 'promotion_code',
                  id: promotionCode.id,
                  code: promotionCode.code,
                };
              }
            }
          }

          return {
            ...discountAmount,
            coupon: couponInfo,
            promotion_code: promotionCodeInfo,
            currency: currencyId,
          };
        })
      );

      return {
        ...item,
        discount_amounts: enhancedDiscountAmounts,
      };
    })
  );

  return enhancedLineItems;
}

/**
 * Expand discounts with complete coupon and promotion code information
 */
export async function expandDiscountsWithDetails(discounts?: any[]): Promise<any[]> {
  if (!discounts?.length) {
    return [];
  }

  const enhancedDiscounts = await Promise.all(
    discounts.map(async (discount) => {
      let couponInfo = null;
      let promotionCodeInfo = null;

      if (discount.coupon) {
        const coupon = await Coupon.findByPk(discount.coupon);
        if (coupon) {
          couponInfo = pick(coupon, [
            'id',
            'name',
            'percent_off',
            'amount_off',
            'valid',
            'duration',
            'duration_in_months',
            'currency_id',
            'currency_options',
          ]);
        }
      }

      if (discount.promotion_code) {
        const promotionCode = await PromotionCode.findByPk(discount.promotion_code);
        if (promotionCode) {
          promotionCodeInfo = pick(promotionCode, ['id', 'code']);
        }
      }

      return {
        ...discount,
        coupon_details: couponInfo,
        promotion_code_details: promotionCodeInfo,
      };
    })
  );

  return enhancedDiscounts;
}
