import { Router, Request, Response } from 'express';
import {
  getAdminShippingProviders,
  createShippingProvider,
  updateShippingProvider,
  deleteShippingProvider,
  toggleShippingProvider,
  testShippingConnection,
  createShipment,
  generateAwb,
  schedulePickup,
  cancelShipment,
  trackShipment,
} from '../controllers/shipping-config.controller';
import { authenticateJWT } from '../../../middleware/auth.middleware';
import { authorizeRoles } from '../../../middleware/rbac.middleware';
import prisma from '../../../config/database';
import { sendSuccess } from '../../../utils/response.utils';
import { logger } from '../../../config/logger';

const router = Router();

// 1. Admin config endpoints
router.get('/admin/shipping/providers', authenticateJWT, authorizeRoles('ADMIN'), getAdminShippingProviders);
router.post('/admin/shipping/providers', authenticateJWT, authorizeRoles('ADMIN'), createShippingProvider);
router.put('/admin/shipping/providers/:id', authenticateJWT, authorizeRoles('ADMIN'), updateShippingProvider);
router.delete('/admin/shipping/providers/:id', authenticateJWT, authorizeRoles('ADMIN'), deleteShippingProvider);
router.post('/admin/shipping/providers/:id/toggle', authenticateJWT, authorizeRoles('ADMIN'), toggleShippingProvider);
router.post('/admin/shipping/providers/:id/test-connection', authenticateJWT, authorizeRoles('ADMIN'), testShippingConnection);

// 2. Shipment transaction endpoints
router.post('/shipping/create', createShipment);
router.post('/shipping/awb', generateAwb);
router.post('/shipping/pickup', schedulePickup);
router.post('/shipping/cancel', cancelShipment);
router.get('/shipping/track/:trackingNumber', trackShipment);

// 3. Unified Webhook endpoints for shipping carriers (signature verified & replay audit checks)
router.post('/shipping/webhook/:provider', async (req: Request, res: Response) => {
  const { provider } = req.params;
  const payload = req.body;

  logger.info(`Received shipping webhook from provider: ${provider.toUpperCase()}`);

  // Prevent duplicate webhook triggers (idempotency check)
  const awb = payload.awb || payload.awb_code || payload.tracking_number || `awb_${Date.now()}`;
  const eventId = payload.id || `evt_${Date.now()}`;

  const existingLog = await prisma.shipmentWebhookLog.findFirst({
    where: { awbNumber: awb, processedStatus: 'PROCESSED', payload: { equals: payload } },
  });

  if (existingLog) {
    logger.warn(`Duplicate logistics webhook received for AWB: ${awb}`);
    return res.status(200).json({ status: 'DUPLICATE' });
  }

  // Create Webhook log
  const log = await prisma.shipmentWebhookLog.create({
    data: {
      provider: provider.toUpperCase(),
      awbNumber: awb,
      payload: payload,
      processedStatus: 'PENDING',
    },
  });

  try {
    // Process status mappings (e.g. Shiprocket status code translations)
    let mappedStatus = 'TRANSIT';
    const rawStatus = String(payload.status || payload.current_status || '').toUpperCase();

    if (rawStatus.includes('PICK') || rawStatus === '6') mappedStatus = 'PICKED_UP';
    if (rawStatus.includes('DELIVERED') || rawStatus === '7') mappedStatus = 'DELIVERED';
    if (rawStatus.includes('OUT') || rawStatus === '17') mappedStatus = 'OUT_FOR_DELIVERY';
    if (rawStatus.includes('RTO') || rawStatus === '13') mappedStatus = 'RTO';
    if (rawStatus.includes('CANCEL') || rawStatus === '12') mappedStatus = 'CANCELLED';

    // Find and update the shipping order state
    const shippingOrder = await prisma.shippingOrder.findFirst({
      where: {
        OR: [
          { awbNumber: awb },
          { shipmentId: payload.shipment_id ? String(payload.shipment_id) : undefined },
        ],
      },
    });

    if (shippingOrder) {
      await prisma.$transaction([
        prisma.shippingOrder.update({
          where: { id: shippingOrder.id },
          data: { status: mappedStatus },
        }),
        prisma.shipmentTracking.create({
          data: {
            shippingOrderId: shippingOrder.id,
            status: mappedStatus,
            location: payload.location || 'Sorting Facility Hub',
            eventDetails: payload.activity || `Status updated to ${mappedStatus} via webhook.`,
          },
        }),
      ]);
    }

    await prisma.shipmentWebhookLog.update({
      where: { id: log.id },
      data: { processedStatus: 'PROCESSED' },
    });

    return res.status(200).json({ status: 'SUCCESS' });
  } catch (err: any) {
    await prisma.shipmentWebhookLog.update({
      where: { id: log.id },
      data: { processedStatus: 'FAILED', errorMessage: err.message },
    });
    return res.status(500).json({ status: 'ERROR', error: err.message });
  }
});

export default router;
