import Stripe from "stripe";
import axios from "axios";

// Types
export interface Event {
  price: number;
  startDate: string;
  endDate: string;
  advert_type: string;
  location: string;
  title: string;
  eventImageUrl: string;
}

export interface WalletData {
  balance: string;
  [key: string]: any;
}

export interface DiscountCalculation {
  totalAmount: number;
  discountAmount: number;
  finalAmount: number;
}

export interface CreateIntentParams {
  stripe_customer_id?: string;
  amount: number;
  metadata?: {
    user_id?: string;
    event_count?: string;
  };
  successUrl?: string;
  cancelUrl?: string;
  selectedEvents: Event[];
  customerEmail?: string;
  token?: string;
}

/**
 * Validates the payment amount
 */
export function validateAmount(amount: number): {
  valid: boolean;
  error?: string;
} {
  if (!amount || amount < 0) {
    return { valid: false, error: "Invalid amount" };
  }
  return { valid: true };
}

/**
 * Fetches user wallet balance from the API
 */
export async function fetchWalletBalance(
  userId: string,
  token: string,
  apiUrl: string
): Promise<{ walletBalance: number; walletData: WalletData | null }> {
  try {
    const walletResponse = await axios.get(
      `${apiUrl}/user-wallets/user/${userId}`,
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
      }
    );

    if (
      walletResponse.data &&
      Array.isArray(walletResponse.data) &&
      walletResponse.data.length > 0
    ) {
      const walletData = walletResponse.data[0];
      const walletBalance = parseFloat(walletData.balance || "0");
      return { walletBalance, walletData };
    }

    return { walletBalance: 0, walletData: null };
  } catch (error: any) {
    console.error("Error fetching wallet balance:", error.message);
    // Return zero balance if fetch fails
    return { walletBalance: 0, walletData: null };
  }
}

/**
 * Calculates total amount, discount, and final amount
 */
export function calculateDiscount(
  selectedEvents: Event[],
  walletBalance: number
): DiscountCalculation {
  const totalAmount = selectedEvents.reduce(
    (sum: number, event: Event) => sum + event.price,
    0
  );
  const discountAmount = Math.min(walletBalance, totalAmount);
  const finalAmount = Math.max(0, totalAmount - discountAmount);

  return {
    totalAmount,
    discountAmount,
    finalAmount,
  };
}

/**
 * Calculates the number of days between start and end date
 */
function calculateDaysDifference(startDate: string, endDate: string): number {
  const start = new Date(startDate);
  const end = new Date(endDate);
  const differenceMs = end.getTime() - start.getTime();
  return Math.floor(differenceMs / (1000 * 60 * 60 * 24));
}

/**
 * Creates Stripe line items with discount applied proportionally
 */
export function createLineItems(
  selectedEvents: Event[],
  totalAmount: number,
  discountAmount: number
): Stripe.Checkout.SessionCreateParams.LineItem[] {
  const lineItems: Stripe.Checkout.SessionCreateParams.LineItem[] =
    selectedEvents.map((event: Event) => {
      const differenceDays = calculateDaysDifference(
        event.startDate,
        event.endDate
      );

      return {
        price_data: {
          currency: "eur",
          product_data: {
            name: `${event.advert_type.toUpperCase()} Grand Pub à ${
              event.location
            }`,
            description: `${event.title} - ${differenceDays} jours`,
            images: event.eventImageUrl ? [event.eventImageUrl] : undefined,
          },
          unit_amount: Math.round(event.price * 100), // Actual price in cents
        },
        quantity: 1,
      };
    });

  return lineItems;
}

/**
 * Creates metadata object for Stripe session
 */
export function createSessionMetadata(
  metadata: CreateIntentParams["metadata"],
  walletBalance: number,
  discountAmount: number,
  totalAmount: number,
  finalAmount: number
): Record<string, string> {
  return {
    user_id: metadata?.user_id || "",
    event_count: metadata?.event_count || "",
    wallet_balance: walletBalance.toString(),
    discount_applied: discountAmount.toString(),
    original_amount: totalAmount.toString(),
    final_amount: finalAmount.toString(),
  };
}

/**
 * Creates a discount coupon for wallet payment
 */
export async function createWalletDiscountCoupon(
  stripe: Stripe,
  discountAmount: number
): Promise<Stripe.Coupon | null> {
  if (discountAmount <= 0) {
    return null;
  }

  try {
    // Create a unique coupon ID based on the discount amount and timestamp
    const couponId = `wallet_discount_${Math.round(
      discountAmount * 100
    )}_${Date.now()}`;

    // Create the coupon with the wallet discount amount
    const coupon = await stripe.coupons.create({
      id: couponId,
      amount_off: Math.round(discountAmount * 100), // Convert to cents
      currency: "eur",
      duration: "once",
      name: "Remise - Beta Test",
    });

    return coupon;
  } catch (error: any) {
    // If coupon creation fails, log error but don't fail the session
    console.error("Error creating wallet discount coupon:", error.message);
    return null;
  }
}

/**
 * Creates Stripe checkout session
 */
export async function createCheckoutSession(
  stripe: Stripe,
  lineItems: Stripe.Checkout.SessionCreateParams.LineItem[],
  sessionMetadata: Record<string, string>,
  origin: string,
  customerEmail?: string,
  discountAmount?: number
): Promise<Stripe.Checkout.Session> {
  const sessionConfig: Stripe.Checkout.SessionCreateParams = {
    payment_method_types: ["card"],
    line_items: lineItems,
    mode: "payment",
    success_url: `${origin}/campaigns/createSepCampaigns?payment_success=true&session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${origin}/campaigns/createSepCampaigns?payment_cancelled=true`,
    metadata: sessionMetadata,
    locale: "fr",
    // allow_promotion_codes: true, // Allow users to enter promo codes at checkout
  };

  // Apply wallet discount as a coupon if applicable
  if (discountAmount !== undefined && discountAmount > 0) {
    const walletCoupon = await createWalletDiscountCoupon(
      stripe,
      discountAmount
    );
    if (walletCoupon) {
      sessionConfig.discounts = [
        {
          coupon: walletCoupon.id,
        },
      ];
    }
  }

  if (customerEmail) {
    sessionConfig.customer_email = customerEmail;
  }

  return await stripe.checkout.sessions.create(sessionConfig);
}
