import prisma from '../config/database';

export interface CarrierInfo {
  name: string;
  slug: string;
  trackingUrlTemplate: string;
  supportPhone: string;
  supportEmail: string;
  averageDeliveryDays: string;
  logo: string;
}

export const SUPPORTED_CARRIERS: Record<string, CarrierInfo> = {
  delhivery: {
    name: 'Delhivery Surface & Express',
    slug: 'delhivery',
    trackingUrlTemplate: 'https://www.delhivery.com/track/package/{trackingNumber}',
    supportPhone: '+91 124 6719500',
    supportEmail: 'customer.support@delhivery.com',
    averageDeliveryDays: '2-4 business days across India',
    logo: 'https://images.unsplash.com/photo-1586528116311-ad8dd3c8310d?w=120&auto=format&fit=crop&q=80',
  },
  bluedart: {
    name: 'Blue Dart Express (DHL Network)',
    slug: 'bluedart',
    trackingUrlTemplate: 'https://www.bluedart.com/tracking/{trackingNumber}',
    supportPhone: '1860 233 1234',
    supportEmail: 'track@bluedart.com',
    averageDeliveryDays: '1-3 business days (Priority Air)',
    logo: 'https://images.unsplash.com/photo-1586528116311-ad8dd3c8310d?w=120&auto=format&fit=crop&q=80',
  },
  indiapost: {
    name: 'India Post (Speed Post / Regd. Book Post)',
    slug: 'indiapost',
    trackingUrlTemplate: 'https://www.indiapost.gov.in/_layouts/15/dpt.cpt.stats/etrac/ek.aspx?ArticleId={trackingNumber}',
    supportPhone: '1800 266 6868',
    supportEmail: 'speedpost@indiapost.gov.in',
    averageDeliveryDays: '3-6 business days nationwide',
    logo: 'https://images.unsplash.com/photo-1586528116311-ad8dd3c8310d?w=120&auto=format&fit=crop&q=80',
  },
  dhl: {
    name: 'DHL Express Worldwide (International)',
    slug: 'dhl',
    trackingUrlTemplate: 'https://www.dhl.com/in-en/home/tracking/tracking-express.html?submit=1&tracking-id={trackingNumber}',
    supportPhone: '1800 111 345 / 1800 200 1345',
    supportEmail: 'international.support@dhl.com',
    averageDeliveryDays: '3-7 business days global air cargo',
    logo: 'https://images.unsplash.com/photo-1586528116311-ad8dd3c8310d?w=120&auto=format&fit=crop&q=80',
  },
  dtdc: {
    name: 'DTDC Courier & Cargo',
    slug: 'dtdc',
    trackingUrlTemplate: 'https://www.dtdc.in/tracking/shipment-tracking.asp?trkid={trackingNumber}',
    supportPhone: '+91 73057 70577',
    supportEmail: 'customersupport@dtdc.com',
    averageDeliveryDays: '2-5 business days',
    logo: 'https://images.unsplash.com/photo-1586528116311-ad8dd3c8310d?w=120&auto=format&fit=crop&q=80',
  },
  fedex: {
    name: 'FedEx Express India',
    slug: 'fedex',
    trackingUrlTemplate: 'https://www.fedex.com/fedextrack/?trknbr={trackingNumber}',
    supportPhone: '1800 209 6161',
    supportEmail: 'india@fedex.com',
    averageDeliveryDays: '2-4 business days',
    logo: 'https://images.unsplash.com/photo-1586528116311-ad8dd3c8310d?w=120&auto=format&fit=crop&q=80',
  },
};

export class TrackingService {
  /**
   * Public Order & Shipment Tracker
   * Searches by trackingNumber (e.g. DELHIVERY-89210) OR orderNumber (e.g. IBW-98201)
   */
  static async trackPublic(query: string) {
    const cleanQuery = query.trim();

    // 1. Search directly in Shipments table by trackingNumber
    let shipment = await prisma.shipment.findFirst({
      where: {
        OR: [
          { trackingNumber: { equals: cleanQuery } },
          { order: { orderNumber: { equals: cleanQuery } } },
          { orderId: { equals: cleanQuery } },
        ],
      },
      include: {
        events: {
          orderBy: { timestamp: 'desc' },
        },
        order: {
          include: {
            shippingAddress: true,
            items: {
              include: {
                book: {
                  select: {
                    id: true,
                    title: true,
                    slug: true,
                    coverImage: true,
                    binding: true,
                  },
                },
                variant: {
                  select: {
                    id: true,
                    title: true,
                    format: true,
                    sku: true,
                  },
                },
              },
            },
          },
        },
      },
    });

    // 2. If no shipment record exists yet, check if order exists
    if (!shipment) {
      const order = await prisma.order.findFirst({
        where: {
          OR: [
            { orderNumber: { equals: cleanQuery } },
            { id: { equals: cleanQuery } },
          ],
        },
        include: {
          shippingAddress: true,
          items: {
            include: {
              book: {
                select: {
                  id: true,
                  title: true,
                  slug: true,
                  coverImage: true,
                  binding: true,
                },
              },
              variant: {
                select: {
                  id: true,
                  title: true,
                  format: true,
                  sku: true,
                },
              },
            },
          },
        },
      });

      if (!order) {
        throw new Error(`No shipment or order found matching “${cleanQuery}”. Please check your tracking number or Order ID.`);
      }

      // Synthesize order tracking representation for an order awaiting courier pickup
      const carrierInfo = SUPPORTED_CARRIERS.delhivery;
      const orderDate = order.createdAt;
      const estimatedDelivery = new Date(orderDate.getTime() + 4 * 24 * 60 * 60 * 1000);

      return {
        orderNumber: order.orderNumber,
        trackingNumber: `IBW-TRK-${order.orderNumber.replace(/[^0-9]/g, '') || '001'}`,
        carrier: carrierInfo.name,
        carrierSlug: carrierInfo.slug,
        carrierTrackingUrl: carrierInfo.trackingUrlTemplate.replace('{trackingNumber}', order.orderNumber),
        carrierInfo,
        status: order.status === 'PROCESSING' ? 'PROCESSING' : order.status === 'CONFIRMED' ? 'CONFIRMED' : 'ORDER_PLACED',
        statusLabel: order.status === 'PROCESSING' ? 'Packed & Ready for Courier Dispatch' : 'Order Confirmed & Allocated',
        currentLocation: 'New Delhi Central Vedic Fulfillment Center',
        orderDate: order.createdAt,
        estimatedDelivery,
        destinationCity: order.shippingAddress.city,
        destinationState: order.shippingAddress.state,
        destinationPostalCode: order.shippingAddress.postalCode,
        destinationCountry: order.shippingAddress.country,
        maskedRecipient: `${order.shippingAddress.fullName.slice(0, 2)}**** ${order.shippingAddress.fullName.split(' ').slice(-1)[0] || ''}`,
        items: order.items.map((item) => ({
          title: item.variant?.title || item.book.title,
          format: item.variant?.format || item.book.binding || 'Book',
          quantity: item.quantity,
          coverImage: item.book.coverImage,
        })),
        timeline: [
          {
            status: 'ORDER_PLACED',
            title: 'Order Confirmed & Payment Verified',
            description: `Payment secured for Order ${order.orderNumber}. Order routed to fulfillment.`,
            location: 'New Delhi E-Commerce Hub',
            timestamp: order.createdAt,
            source: 'SYSTEM',
          },
          ...(order.status === 'PROCESSING'
            ? [
                {
                  status: 'PROCESSING',
                  title: 'Archival Inspection & Protective Packaging',
                  description: 'Items inspected for print quality and packed with moisture-resistant protective layers.',
                  location: 'New Delhi Fulfillment Center',
                  timestamp: new Date(order.createdAt.getTime() + 2 * 60 * 60 * 1000),
                  source: 'SYSTEM',
                },
              ]
            : []),
        ],
      };
    }

    // 3. Return full shipment data
    const carrierSlug = shipment.carrierSlug.toLowerCase();
    const carrierInfo = SUPPORTED_CARRIERS[carrierSlug] || {
      name: shipment.carrier,
      slug: carrierSlug,
      trackingUrlTemplate: shipment.carrierTrackingUrl || '',
      supportPhone: '+91 11 2345 6789',
      supportEmail: 'support@indianbooksworldwide.com',
      averageDeliveryDays: '2-4 business days',
      logo: 'https://images.unsplash.com/photo-1586528116311-ad8dd3c8310d?w=120&auto=format&fit=crop&q=80',
    };

    const trackingUrl = shipment.carrierTrackingUrl || carrierInfo.trackingUrlTemplate.replace('{trackingNumber}', shipment.trackingNumber);

    return {
      orderNumber: shipment.order.orderNumber,
      trackingNumber: shipment.trackingNumber,
      carrier: shipment.carrier,
      carrierSlug: shipment.carrierSlug,
      carrierTrackingUrl: trackingUrl,
      carrierInfo,
      status: shipment.status,
      statusLabel: getStatusLabel(shipment.status),
      currentLocation: shipment.currentLocation || 'In Transit',
      orderDate: shipment.order.createdAt,
      shippedAt: shipment.shippedAt,
      deliveredAt: shipment.deliveredAt,
      estimatedDelivery: shipment.estimatedDelivery || new Date(shipment.createdAt.getTime() + 3 * 24 * 60 * 60 * 1000),
      signedBy: shipment.signedBy,
      destinationCity: shipment.order.shippingAddress.city,
      destinationState: shipment.order.shippingAddress.state,
      destinationPostalCode: shipment.order.shippingAddress.postalCode,
      destinationCountry: shipment.order.shippingAddress.country,
      maskedRecipient: `${shipment.order.shippingAddress.fullName.slice(0, 2)}**** ${shipment.order.shippingAddress.fullName.split(' ').slice(-1)[0] || ''}`,
      items: shipment.order.items.map((item) => ({
        title: item.variant?.title || item.book.title,
        format: item.variant?.format || item.book.binding || 'Book',
        quantity: item.quantity,
        coverImage: item.book.coverImage,
      })),
      timeline: shipment.events.map((ev) => ({
        id: ev.id,
        status: ev.status,
        title: ev.title,
        description: ev.description,
        location: ev.location,
        timestamp: ev.timestamp,
        source: ev.source,
      })),
    };
  }

  /**
   * Create or update a shipment for an Order (Admin / System)
   */
  static async createOrUpdateShipment(data: {
    orderId: string;
    trackingNumber: string;
    carrier: string;
    carrierSlug?: string;
    carrierTrackingUrl?: string;
    status?: string;
    currentLocation?: string;
    estimatedDelivery?: Date;
    shippedAt?: Date;
  }) {
    const slug = (data.carrierSlug || data.carrier.toLowerCase().replace(/[^a-z0-9]/g, '')).toLowerCase();
    const carrierData = SUPPORTED_CARRIERS[slug];
    const carrierTrackingUrl = data.carrierTrackingUrl || (carrierData ? carrierData.trackingUrlTemplate.replace('{trackingNumber}', data.trackingNumber) : undefined);

    const shipment = await prisma.shipment.upsert({
      where: { orderId: data.orderId },
      create: {
        orderId: data.orderId,
        trackingNumber: data.trackingNumber,
        carrier: data.carrier,
        carrierSlug: slug,
        carrierTrackingUrl,
        status: data.status || 'DISPATCHED',
        currentLocation: data.currentLocation || 'Main Logistics Hub',
        estimatedDelivery: data.estimatedDelivery,
        shippedAt: data.shippedAt || new Date(),
        events: {
          create: {
            status: data.status || 'DISPATCHED',
            title: `Package Dispatched with ${data.carrier}`,
            description: `AWB ${data.trackingNumber} generated and package handed over to carrier.`,
            location: data.currentLocation || 'Fulfillment Center, New Delhi',
            source: 'ADMIN',
          },
        },
      },
      update: {
        trackingNumber: data.trackingNumber,
        carrier: data.carrier,
        carrierSlug: slug,
        carrierTrackingUrl,
        status: data.status || undefined,
        currentLocation: data.currentLocation || undefined,
        estimatedDelivery: data.estimatedDelivery || undefined,
        shippedAt: data.shippedAt || undefined,
      },
      include: { events: true },
    });

    // Sync Order Status
    if (data.status === 'DELIVERED') {
      await prisma.order.update({
        where: { id: data.orderId },
        data: { status: 'DELIVERED' },
      });
    } else if (data.status === 'DISPATCHED' || data.status === 'IN_TRANSIT') {
      await prisma.order.update({
        where: { id: data.orderId },
        data: { status: 'SHIPPED' },
      });
    }

    return shipment;
  }

  /**
   * Append a real-time tracking event to a shipment
   */
  static async addTrackingEvent(data: {
    shipmentId: string;
    status: string;
    title: string;
    description?: string;
    location?: string;
    timestamp?: Date;
    source?: string;
  }) {
    const event = await prisma.trackingEvent.create({
      data: {
        shipmentId: data.shipmentId,
        status: data.status,
        title: data.title,
        description: data.description,
        location: data.location,
        timestamp: data.timestamp || new Date(),
        source: data.source || 'SYSTEM',
      },
    });

    // Update shipment current status and location
    await prisma.shipment.update({
      where: { id: data.shipmentId },
      data: {
        status: data.status,
        currentLocation: data.location || undefined,
        deliveredAt: data.status === 'DELIVERED' ? new Date() : undefined,
      },
    });

    return event;
  }

  /**
   * Process Carrier Webhooks (Delhivery, Shiprocket, BlueDart, DHL)
   */
  static async processCarrierWebhook(carrierSlug: string, payload: any) {
    const slug = carrierSlug.toLowerCase();
    let trackingNumber = '';
    let status = '';
    let eventTitle = '';
    let eventDesc = '';
    let location = '';
    let timestamp = new Date();

    // Universal normalization per courier format
    if (slug === 'delhivery') {
      trackingNumber = payload.waybill || payload.awb || payload.Shipment?.AWB || '';
      status = mapCarrierStatus(payload.Status?.Status || payload.status || '');
      eventTitle = payload.Status?.StatusType || payload.Status?.Status || 'Delhivery Status Update';
      eventDesc = payload.Status?.Instructions || payload.Status?.StatusLocation || '';
      location = payload.Status?.StatusLocation || payload.location || '';
      if (payload.Status?.StatusDateTime) timestamp = new Date(payload.Status.StatusDateTime);
    } else if (slug === 'shiprocket') {
      trackingNumber = payload.awb || payload.awb_code || '';
      status = mapCarrierStatus(payload.current_status || payload.status || '');
      eventTitle = payload.current_status || 'Shiprocket Transit Event';
      eventDesc = payload.activity || payload.scans?.[0]?.activity || '';
      location = payload.scans?.[0]?.location || '';
    } else if (slug === 'bluedart') {
      trackingNumber = payload.awbNo || payload.AWBNo || '';
      status = mapCarrierStatus(payload.status || '');
      eventTitle = payload.statusDesc || 'Blue Dart Status Update';
      location = payload.statusLocation || '';
    } else {
      // Generic Webhook format
      trackingNumber = payload.trackingNumber || payload.tracking_number || payload.awb || '';
      status = mapCarrierStatus(payload.status || payload.event || 'IN_TRANSIT');
      eventTitle = payload.title || payload.message || `Carrier Update (${slug})`;
      eventDesc = payload.description || payload.details || '';
      location = payload.location || payload.hub || '';
    }

    if (!trackingNumber) {
      throw new Error(`Webhook payload missing AWB / tracking number for carrier "${slug}".`);
    }

    const shipment = await prisma.shipment.findUnique({
      where: { trackingNumber },
    });

    if (!shipment) {
      throw new Error(`Shipment with AWB ${trackingNumber} not found.`);
    }

    // Add tracking event and update status
    const event = await this.addTrackingEvent({
      shipmentId: shipment.id,
      status,
      title: eventTitle,
      description: eventDesc,
      location,
      timestamp,
      source: 'CARRIER_WEBHOOK',
    });

    // Store raw webhook payload for audit logs
    await prisma.shipment.update({
      where: { id: shipment.id },
      data: {
        rawWebhookData: payload,
      },
    });

    return {
      success: true,
      trackingNumber,
      carrier: slug,
      status,
      eventId: event.id,
    };
  }

  /**
   * Get supported carriers list with metadata
   */
  static getSupportedCarriers() {
    return Object.values(SUPPORTED_CARRIERS);
  }
}

function mapCarrierStatus(raw: string): string {
  const norm = raw.toUpperCase().replace(/[^A-Z]/g, '_');
  if (norm.includes('DELIVERED') || norm.includes('DLVD')) return 'DELIVERED';
  if (norm.includes('OUT_FOR_DELIVERY') || norm.includes('OFD')) return 'OUT_FOR_DELIVERY';
  if (norm.includes('IN_TRANSIT') || norm.includes('TRANSIT') || norm.includes('DISPATCH')) return 'IN_TRANSIT';
  if (norm.includes('PICKED') || norm.includes('MANIFEST') || norm.includes('RTO_INITIATED')) return 'PROCESSING';
  if (norm.includes('FAILED') || norm.includes('UNDELIVERED') || norm.includes('EXCEPTION')) return 'EXCEPTION';
  return 'IN_TRANSIT';
}

function getStatusLabel(status: string): string {
  switch (status) {
    case 'ORDER_PLACED':
      return 'Order Placed & Confirmed';
    case 'PROCESSING':
      return 'Processing & Archival Packaging in Progress';
    case 'DISPATCHED':
      return 'Dispatched & Handed Over to Carrier';
    case 'IN_TRANSIT':
      return 'In Transit — Moving between Regional Hubs';
    case 'OUT_FOR_DELIVERY':
      return 'Out for Delivery — Expected Today';
    case 'DELIVERED':
      return 'Successfully Delivered';
    case 'EXCEPTION':
      return 'Delivery Attempt Exception / Re-route in Progress';
    default:
      return 'Shipment in Transit';
  }
}
