import { Request, Response } from 'express';
import { OrderFulfillmentService, OrderFulfillmentContext, OrderFulfillmentStatus } from '../../services/order/OrderFulfillmentService';
import { logger } from '../../utils/logger';

export class OrderFulfillmentController {
  static async initTables(req: Request, res: Response): Promise<void> {
    try {
      await OrderFulfillmentService.initTables();
      res.json({ success: true, message: 'Order fulfillment tables initialized' });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Init tables failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async pullOrder(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const { businessType, ...orderData } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: businessType || 'TOC'
      };

      const result = await OrderFulfillmentService.pullOrder(context, orderData);
      res.json({ success: result.success, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Pull order failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async reviewOrder(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const id = req.params.id as string;
      const { approved, reason, note } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.reviewOrder(context, id, {
        approved,
        reason,
        note
      });
      res.json({ success: result.success, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Review order failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async allocateWarehouse(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const id = req.params.id as string;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.allocateWarehouse(context, id);
      res.json({ success: result.success, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Allocate warehouse failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async prepareShipment(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const id = req.params.id as string;
      const { logisticsOption } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.prepareShipment(context, id, logisticsOption);
      res.json({ success: result.success, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Prepare shipment failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async shipOrder(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const id = req.params.id as string;
      const { trackingNumber, carrier, estimatedDelivery } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.shipOrder(context, id, {
        trackingNumber,
        carrier,
        estimatedDelivery: estimatedDelivery ? new Date(estimatedDelivery) : undefined
      });
      res.json({ success: result.success, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Ship order failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async confirmDelivery(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const id = req.params.id as string;
      const { deliveredAt, signature } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.confirmDelivery(context, id, {
        deliveredAt: deliveredAt ? new Date(deliveredAt) : undefined,
        signature
      });
      res.json({ success: result.success, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Confirm delivery failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async markAsException(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const id = req.params.id as string;
      const { reason } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.markAsException(context, id, reason);
      res.json({ success: result.success, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Mark as exception failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async cancelOrder(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const id = req.params.id as string;
      const { reason } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.cancelOrder(context, id, reason);
      res.json({ success: result.success, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Cancel order failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async getOrder(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId } = (req as any).traceContext;
      const id = req.params.id as string;

      const order = await OrderFulfillmentService.getOrderById(tenantId, id);
      if (!order) {
        res.status(404).json({ success: false, error: 'Order not found' });
        return;
      }
      res.json({ success: true, data: order });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Get order failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async getOrders(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId } = (req as any).traceContext;
      const { status, shopId, startDate, endDate, page, pageSize } = req.query;

      const result = await OrderFulfillmentService.getOrders(tenantId, {
        status: status as OrderFulfillmentStatus,
        shopId: shopId as string,
        startDate: startDate ? new Date(startDate as string) : undefined,
        endDate: endDate ? new Date(endDate as string) : undefined,
        page: page ? parseInt(page as string) : 1,
        pageSize: pageSize ? parseInt(pageSize as string) : 20
      });
      res.json({ success: true, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Get orders failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async batchReview(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const { orderIds } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.batchReview(context, orderIds);
      res.json({ success: true, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Batch review failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async batchAllocate(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const { orderIds } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.batchAllocate(context, orderIds);
      res.json({ success: true, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Batch allocate failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }

  static async batchShip(req: Request, res: Response): Promise<void> {
    try {
      const { tenantId, shopId, traceId } = (req as any).traceContext;
      const { shipments } = req.body;

      const context: OrderFulfillmentContext = {
        tenantId,
        shopId,
        taskId: `TASK-${Date.now()}`,
        traceId,
        businessType: 'TOC'
      };

      const result = await OrderFulfillmentService.batchShip(context, shipments);
      res.json({ success: true, data: result });
    } catch (error: any) {
      logger.error(`[OrderFulfillmentController] Batch ship failed: ${error.message}`);
      res.status(500).json({ success: false, error: error.message });
    }
  }
}
