// @ts-nocheck
import { Request, Response } from 'express';
import Stripe from 'stripe';

import { v4 as uuidv4 } from 'uuid';
import prisma from '../DB/db';
import asyncHandler from '../utils/asyncHandler';
import crypto from 'crypto';
import ApiResponse from '../utils/apiResponse';
import ApiError from '../utils/apiError';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2025-12-15.clover',
});

// --- Create Stripe Checkout Session ---
export const createStripeSession = asyncHandler(async (req: Request, res: Response) => {
  const userId = req.user?.id || req.body.userId; 

  if (!userId) {
    throw new ApiError(401, "Unauthorized request");
  }

  // 1. Fetch Cart Items
  const cart = await prisma.cart.findUnique({
    where: { userId },
    include: {
      items: {
        include: {
          product: true,
          productVariant: true,
        },
      },
    },
  });

  if (!cart || cart.items.length === 0) {
    throw new ApiError(400, "Cart is empty");
  }

  // 2. Prepare Line Items for Stripe
  const line_items = cart.items.map((item) => {
    const basePrice = Number(item.product.price);
    const variantDiff = Number(item.productVariant?.priceDiff || 0);
    const unitAmount = Math.round((basePrice + variantDiff) * 100); // Stripe expects amounts in cents (paise)

    // Build description
    const description = item.productVariant 
      ? `Size: ${item.productVariant.size}, Color: ${item.productVariant.color}`
      : "Standard";

    return {
      price_data: {
        currency: "usd", // Change to "inr" for Rupees
        product_data: {
          name: item.product.name,
          description: description,
          images: item.product.images ? [item.product.images[0]] : [],
        },
        unit_amount: unitAmount,
      },
      quantity: item.quantity,
    };
  });

  // 3. Calculate Totals for Shipping/Tax Logic (Optional but good for metadata)
  const subtotal = cart.items.reduce((sum, item) => {
    const p = Number(item.product.price) + Number(item.productVariant?.priceDiff || 0);
    return sum + p * item.quantity;
  }, 0);

  // Add Shipping Line Item (Free if > 100)
  const shippingCost = subtotal > 100 ? 0 : 20;
  if (shippingCost > 0) {
    line_items.push({
      price_data: {
        currency: "usd",
        product_data: {
          name: "Standard Shipping",
        },
        unit_amount: shippingCost * 100,
      },
      quantity: 1,
    });
  }

  // Add Tax Line Item (18%)
  const taxAmount = Math.round(subtotal * 0.18 * 100); 
  if (taxAmount > 0) {
     line_items.push({
      price_data: {
        currency: "usd",
        product_data: {
          name: "GST / Tax (18%)",
        },
        unit_amount: taxAmount,
      },
      quantity: 1,
    });
  }

  // 4. Create Session
  const session = await stripe.checkout.sessions.create({
    payment_method_types: ["card"],
    line_items,
    mode: "payment",
    success_url: `${process.env.FRONTEND_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.FRONTEND_URL}/checkout`,
    customer_email: req.user?.email, // Pre-fill email if available
    metadata: {
      userId: userId,
      cartId: cart.id,
      source: "SSBN_Web",
    },
  });

  return res.status(200).json(new ApiResponse(200, { url: session.url, sessionId: session.id }, "Stripe session created"));
});

// ----------------------------
// Create an Order & Payment
// ----------------------------
export const createOrder = async (req: Request, res: Response) => {
  try {
    const { userId, addressId, paymentMethod } = req.body;

    if (!userId) return res.status(400).json({ message: 'User ID required' });

    // 1️⃣ Fetch user's cart
    const cart = await prisma.cart.findUnique({
      where: { userId },
      include: { items: { include: { product: true, variant: true } } },
    });

    if (!cart || cart.items.length === 0) return res.status(400).json({ message: 'Cart is empty' });

    // 2️⃣ Calculate totals
    const subtotal = cart.items.reduce((sum, item) => {
      const price = item.variant?.priceDiff
        ? item.product.price + item.variant.priceDiff
        : item.product.price;
      return sum + Number(price) * item.quantity;
    }, 0);
    const shippingCost = 0;
    const tax = subtotal * 0.05; // 5% tax example
    const total = subtotal + shippingCost + tax;

    // 3️⃣ Create order
    const orderNumber = `SSBN-${Math.floor(100000 + Math.random() * 900000)}`;

    const order = await prisma.order.create({
      data: {
        userId,
        orderNumber,
        subtotal,
        shippingCost,
        tax,
        total,
        addressId,
        items: {
          create: cart.items.map((item) => ({
            productId: item.product.id,
            productName: item.product.name,
            productImage: item.product.images[0],
            sku: item.variant?.sku,
            size: item.variant?.size,
            color: item.variant?.color,
            price: item.variant?.priceDiff
              ? item.product.price + item.variant.priceDiff
              : item.product.price,
            quantity: item.quantity,
            variantId: item.variantId,
          })),
        },
      },
    });

    // 4️⃣ Handle Payment Intent if Stripe
    if (paymentMethod === 'STRIPE') {
      const paymentIntent = await stripe.paymentIntents.create({
        amount: Math.round(total * 100), // in paise
        currency: 'USD',
        metadata: { orderId: order.id },
      });

      // Create payment record
      await prisma.payment.create({
        data: {
          orderId: order.id,
          provider: 'STRIPE',
          status: 'PENDING',
          amount: total,
          transactionId: paymentIntent.id,
        },
      });

      return res.json({
        success: true,
        clientSecret: paymentIntent.client_secret,
        orderId: order.id,
      });
    } else if (paymentMethod === 'COD') {
      // Cash on Delivery
      await prisma.payment.create({
        data: {
          orderId: order.id,
          provider: 'COD',
          status: 'PENDING',
          amount: total,
        },
      });

      return res.json({ success: true, orderId: order.id });
    }

    return res.status(400).json({ message: 'Invalid payment method' });
  } catch (err: any) {
    console.error(err);
    return res.status(500).json({ message: err.message });
  }
};

// --- Webhook Handler ---
export const stripeWebhook = async (req: Request, res: Response) => {
  const sig = req.headers["stripe-signature"]!;
  let event: Stripe.Event;

  try {
    event = stripe.webhooks.constructEvent(
      req.body, // Raw buffer
      sig,
      process.env.STRIPE_WEBHOOK_SECRET!
    );
  } catch (err: any) {
    console.error(`Webhook signature verification failed: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  if (event.type === "checkout.session.completed") {
    const session = event.data.object as Stripe.Checkout.Session;
    
    // Retrieve metadata
    const userId = session.metadata?.userId;
    const addressId = session.metadata?.addressId;

    if (userId && addressId) {
      try {
        await fulfillOrder(userId, addressId, session);
        console.log("Order fulfilled successfully via Webhook");
      } catch (error) {
        console.error("Error fulfilling order:", error);
        return res.status(500).json({ error: "Failed to fulfill order" });
      }
    }
  }

  res.json({ received: true });
};

// --- Fulfill Order Helper ---
async function fulfillOrder(userId: string, addressId: string, session: Stripe.Checkout.Session) {
  // 1. Idempotency Check
  const existingOrder = await prisma.order.findFirst({
    where: { payment: { transactionId: session.id } }
  });

  if (existingOrder) return; 

  // 2. Fetch User's Cart
  const cart = await prisma.cart.findUnique({
    where: { userId },
    include: {
      items: {
        include: { product: true, productVariant: true },
      },
    },
  });

  if (!cart || cart.items.length === 0) {
    console.error(`Cart empty for user ${userId}`);
    return;
  }

  // 3. Transaction
  await prisma.$transaction(async (tx) => {
    
    // Prepare Order Items with Snapshot Data (Image, SKU, etc.)
    const orderItemsData = cart.items.map((item) => {
      const basePrice = Number(item.product.price);
      const diff = Number(item.productVariant?.priceDiff || 0);
      const price = basePrice + diff;

      return {
        // Relations
        productId: item.productId,
        variantId: item.variantId,

        // 🔥 SNAPSHOT DATA (Fixed to match COD Controller)
        productName: item.product.name,
        productImage: item.product.images?.[0] ?? null, // ✅ Image Added
        sku: item.productVariant?.sku ?? null,
        size: item.productVariant?.size ?? null,
        color: item.productVariant?.color ?? null,

        price,
        quantity: item.quantity,
      };
    });

    // Calculate Costs from Session
    const totalAmount = session.amount_total ? session.amount_total / 100 : 0;
    const subtotal = session.amount_subtotal ? session.amount_subtotal / 100 : 0;
    const shippingCost = session.total_details?.amount_shipping ? session.total_details.amount_shipping / 100 : 0;
    const tax = 0; // Or calculate manually if Stripe doesn't provide breakdown in metadata

    // Create Order
    await tx.order.create({
      data: {
        user: { connect: { id: userId } },
        shippingAddress: { connect: { id: addressId } },
        
        orderNumber: `SSBN-${crypto.randomInt(10001, 99999)}`,
        subtotal,
        shippingCost,
        tax,
        total: totalAmount,
        
        status: "PAID", 
        isPaid: true,

        // Payment Relation
        payment: {
          create: {
            provider: "STRIPE", // or "CARD"
            status: "PAID",
            amount: totalAmount,
            transactionId: session.id, 
          }
        },

        // Items Relation
        items: {
          create: orderItemsData,
        },
      },
    });

    // Decrement Stock
    for (const item of cart.items) {
      if (item.variantId) {
        await tx.productVariant.update({
          where: { id: item.variantId },
          data: { stock: { decrement: item.quantity } },
        });
      }
    }

    // Clear Cart
    await tx.cartItem.deleteMany({
      where: { cartId: cart.id },
    });
  });
}

// ----------------------------
// Get User Orders
// ----------------------------
export const getUserOrders = async (req: Request, res: Response) => {
  const { userId } = req.params;

  const orders = await prisma.order.findMany({
    where: { userId },
    include: { items: true, payment: true, shippingAddress: true },
    orderBy: { createdAt: 'desc' },
  });

  res.json({ success: true, orders });
};

// ----------------------------
// Add a new address
// ----------------------------
export const addAddress = async (req: Request, res: Response) => {
  const { userId, type, street, city, state, zipCode, country, phone, isDefault } = req.body;

  if (!userId || !street || !city || !state || !zipCode || !country || !phone) {
    return res.status(400).json({ message: 'All required fields must be filled' });
  }

  try {
    // If new address is default, reset existing default
    if (isDefault) {
      await prisma.address.updateMany({
        where: { userId, isDefault: true },
        data: { isDefault: false },
      });
    }

    const address = await prisma.address.create({
      data: {
        userId,
        type: type || 'HOME',
        street,
        city,
        state,
        zipCode,
        country,
        phone,
        isDefault: isDefault || false,
      },
    });

    res.json({ success: true, address });
  } catch (err: any) {
    console.error(err);
    res.status(500).json({ message: err.message });
  }
};



// --- Create COD Order ---
export const createCodOrder = asyncHandler(async (req: Request, res: Response) => {
  const { userId } = req.params;
  const { addressId } = req.body;

  if (!userId || !addressId) {
    throw new ApiError(false, 400, "User ID and Address ID are required");
  }

  const orderNumber = `SSBN-${crypto.randomInt(10001, 99999)}`;

  // 1. Fetch Cart
  const cart = await prisma.cart.findUnique({
    where: { userId },
    include: {
      items: {
        include: {
          product: true,
          productVariant: true,
        },
      },
    },
  });

  if (!cart || cart.items.length === 0) {
    throw new ApiError(false, 400, "Cart is empty");
  }

  // 2. Transaction
  const order = await prisma.$transaction(async (tx) => {
    let subtotal = 0;

    const orderItemsData = cart.items.map((item) => {
      const basePrice = Number(item.product.price);
      const diff = Number(item.productVariant?.priceDiff || 0);
      const price = basePrice + diff;
      const total = price * item.quantity;

      subtotal += total;

      return {
        // relations
        productId: item.productId,
        variantId: item.variantId,

        // 🔥 SNAPSHOT DATA
        productName: item.product.name,
        productImage: item.product.images?.[0] ?? null, // ✅ IMAGE FIX
        sku: item.productVariant?.sku ?? null,
        size: item.productVariant?.size ?? null,
        color: item.productVariant?.color ?? null,

        price,
        quantity: item.quantity,
      };
    });

    const shippingCost = subtotal > 100 ? 0 : 20;
    const tax = subtotal * 0.18;
    const totalAmount = subtotal + shippingCost + tax;

    const newOrder = await tx.order.create({
      data: {
        orderNumber,

        user: { connect: { id: userId } },
        shippingAddress: { connect: { id: addressId } },

        subtotal,
        shippingCost,
        tax,
        total: totalAmount,
        status: "PENDING",
        isPaid: false,

        payment: {
          create: {
            provider: "CASH_ON_DELIVERY",
            amount: totalAmount,
            status: "PENDING",
          },
        },

        items: {
          create: orderItemsData,
        },
      },
    });

    // 3. Decrement Stock
    for (const item of cart.items) {
      if (item.variantId) {
        await tx.productVariant.update({
          where: { id: item.variantId },
          data: { stock: { decrement: item.quantity } },
        });
      }
    }

    // 4. Clear Cart
    await tx.cartItem.deleteMany({
      where: { cartId: cart.id },
    });

    return newOrder;
  });

  // 5. Return Order with Items
  const orderWithItems = await prisma.order.findUnique({
    where: { id: order.id },
    include: {
      items: true,
      payment: true,
    },
  });

  return res.status(201).json(
    new ApiResponse(true, 201, "COD order placed successfully", {
      orderId: orderWithItems?.id,
      orderNumber: orderWithItems?.orderNumber,
      total: orderWithItems?.total,
      items: orderWithItems?.items.map((item) => ({
        name: item.productName,
        image: item.productImage, // ✅ IMAGE RETURNED
        sku: item.sku,
        price: Number(item.price),
        qty: item.quantity,
        total: Number(item.price) * item.quantity,
      })),
    })
  );
});
