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

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

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

export interface CreateCityHubIntentParams {
  stripe_customer_id?: string;
  amount: number;
  metadata?: {
    user_id?: string;
    city_hub_page_id?: string;
    duration?: string;
  };
  successUrl?: string;
  cancelUrl?: string;
  customerEmail?: string;
  token?: string;
  campaignType?: "cityhub";
}

/**
 * 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 for cityhub campaigns
 */
export function calculateDiscount(
  totalAmount: number,
  walletBalance: number
): DiscountCalculation {
  const discountAmount = Math.min(walletBalance, totalAmount);
  const finalAmount = Math.max(0, totalAmount - discountAmount);

  return {
    totalAmount,
    discountAmount,
    finalAmount,
  };
}

/**
 * Creates Stripe line items for cityhub campaign
 */
export function createLineItems(
  amount: number,
  duration: number,
  communeName?: string
): Stripe.Checkout.SessionCreateParams.LineItem[] {
  return [
    {
      price_data: {
        currency: "eur",
        product_data: {
          name: `City Hub Advert${communeName ? ` - ${communeName}` : ""}`,
          description: `Advertisement campaign for ${duration} days`,
        },
        unit_amount: Math.round(amount * 100), // Convert to cents - must be inside price_data
      },
      quantity: 1,
    },
  ];
}

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

/**
 * 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 for cityhub campaigns
 */
export async function createCheckoutSession(
  stripe: Stripe,
  lineItems: Stripe.Checkout.SessionCreateParams.LineItem[],
  sessionMetadata: Record<string, string>,
  origin: string,
  customerEmail?: string,
  discountAmount?: number,
  successUrl?: string,
  cancelUrl?: string
): Promise<Stripe.Checkout.Session> {
  console.log("================================================");
  console.log("CityHub payment intent - origin:", origin);
  console.log("CityHub payment intent - customerEmail:", customerEmail);
  console.log("CityHub payment intent - discountAmount:", discountAmount);
  console.log("CityHub payment intent - successUrl:", successUrl);
  console.log("CityHub payment intent - cancelUrl:", cancelUrl);

  const sessionConfig: Stripe.Checkout.SessionCreateParams = {
    payment_method_types: ["card"],
    line_items: lineItems,
    mode: "payment",
    success_url:
      successUrl ||
      `${origin}/campaigns/createHubPageAdvert?payment_success=true&session_id={CHECKOUT_SESSION_ID}`,
    cancel_url:
      cancelUrl ||
      `${origin}/campaigns/createHubPageAdvert?payment_cancelled=true`,
    metadata: sessionMetadata,
    locale: "fr",
  };

  // 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);
}
