const express = require('express');
const router = express.Router();
const stripe = require('stripe');
const config = require('../config');

module.exports = (pool, query, authMiddleware) => {
  
  // Webhook to handle events from Stripe
  // before authmiddleware since stripe
  // and json processing to prevent express from processing buffer as json obj
  router.post('/webhook', express.raw({type: 'application/json'}), async (req, res) => {
    // This needs to be called with raw body data
    const payload = req.body;
    const sig = req.headers['stripe-signature'];
    
    let event;
    
    try {
      // Verify the webhook signature
      const webhookSecret = config.payment?.stripeWebhookSecret;
      if (!webhookSecret) {
        throw new Error('Stripe webhook secret is not configured');
      }
      
      event = stripeClient.webhooks.constructEvent(payload, sig, webhookSecret);
      
      // Handle the event
      switch (event.type) {
        case 'checkout.session.completed':
          const session = event.data.object;
          
          // Check if payment was successful
          if (session.payment_status === 'paid') {
            // Get metadata
            const { order_id, user_id } = session.metadata;
            
            if (order_id) {
              // Update order status in database
              await query(
                'UPDATE orders SET status = $1, payment_completed = true, payment_id = $2 WHERE id = $3',
                ['processing', session.id, order_id]
              );
              
              console.log(`Payment completed for order ${order_id}`);
            }
          }
          break;
          
        case 'payment_intent.payment_failed':
          const paymentIntent = event.data.object;
          console.log(`Payment failed: ${paymentIntent.last_payment_error?.message}`);
          
          // Handle failed payment
          if (paymentIntent.metadata?.order_id) {
            await query(
              'UPDATE orders SET status = $1, payment_notes = $2 WHERE id = $3',
              ['payment_failed', 'Payment attempt failed', paymentIntent.metadata.order_id]
            );
          }
          break;
          
        default:
          console.log(`Unhandled event type ${event.type}`);
      }
      
      // Return a 200 success response
      res.status(200).send();
    } catch (err) {
      console.error(`Webhook Error: ${err.message}`);
      return res.status(400).send(`Webhook Error: ${err.message}`);
    }
  });
  router.use(express.json());

  // Apply authentication middleware to all routes
  router.use(authMiddleware);
  
  // Initialize Stripe with the secret key from config
  const stripeClient = stripe(config.payment?.stripeSecretKey);

  // Create checkout session
  router.post('/create-checkout-session', async (req, res, next) => {
    try {
      const { cartItems, shippingAddress, userId, orderId, shippingDetails } = req.body;
      
      if (!cartItems || cartItems.length === 0) {
        return res.status(400).json({
          error: true,
          message: 'Cart items are required'
        });
      }
      
      // Verify user has access to this cart
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only checkout your own cart'
        });
      }
      
      // Format line items for Stripe
      const lineItems = cartItems.map(item => {
        return {
          price_data: {
            currency: 'usd',
            product_data: {
              name: item.name,
              description: item.description ? item.description.substring(0, 500) : undefined,
              images: item.primary_image ? [
                `${config.site.protocol}://${config.site.apiDomain}${item.primary_image.path}`
              ] : undefined,
            },
            unit_amount: Math.round(parseFloat(item.price) * 100), // Convert to cents
          },
          quantity: item.quantity,
        };
      });
      
      // Create metadata with shipping info and order reference
      const metadata = {
        order_id: orderId,
        user_id: userId,
        shipping_address: JSON.stringify(shippingAddress),
      };
      
      // Add tracking information to metadata if available
      if (shippingDetails && shippingDetails.tracking_code) {
        metadata.tracking_code = shippingDetails.tracking_code;
        metadata.shipping_carrier = shippingDetails.shipping_method || 'Standard Shipping';
      }
  
      // Create Stripe checkout session
      const session = await stripeClient.checkout.sessions.create({
        payment_method_types: ['card'],
        line_items: lineItems,
        mode: 'payment',
        success_url: `${config.site.protocol}://${config.site.domain}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
        cancel_url: `${config.site.protocol}://${config.site.domain}/checkout/cancel`,
        metadata: metadata,
        shipping_options: [
          {
            shipping_rate_data: {
              type: 'fixed_amount',
              fixed_amount: {
                amount: shippingDetails && shippingDetails.shipping_cost ? 
                  Math.round(parseFloat(shippingDetails.shipping_cost) * 100) : 0,
                currency: 'usd',
              },
              display_name: shippingDetails && shippingDetails.shipping_method ? 
                shippingDetails.shipping_method : 'Standard Shipping',
              delivery_estimate: {
                minimum: {
                  unit: 'business_day',
                  value: 2,
                },
                maximum: {
                  unit: 'business_day',
                  value: 7,
                },
              },
            },
          },
        ],
      });
      
      // Return the session ID to the client
      res.json({
        success: true,
        sessionId: session.id,
        url: session.url
      });
    } catch (error) {
      console.error('Stripe checkout error:', error);
      next(error);
    }
  });
  
  // Verify payment status
  router.get('/session-status/:sessionId', async (req, res, next) => {
    try {
      const { sessionId } = req.params;
      
      // Retrieve the session from Stripe
      const session = await stripeClient.checkout.sessions.retrieve(sessionId);
      
      res.json({
        success: true,
        status: session.payment_status,
        metadata: session.metadata
      });
    } catch (error) {
      console.error('Error checking session status:', error);
      next(error);
    }
  });
  router.get('/config', async (req, res, next) => {
    try {
      res.json({
        stripePublicKey: config.payment?.stripePublicKey || '',
        stripeEnabled: config.payment?.stripeEnabled || false
      });
    } catch (error) {
      next(error);
    }
  });
  return router;
};