/**
 * @license
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * Adapters that turn raw Fiesta REST rows into the display shapes the existing
 * views already render (ProductMatrixItem, InventoryItem, CustomerOrder). Keeping
 * the mapping here lets several views (Inventory, Operations, Reports, Orders)
 * share one source of truth and keeps the components focused on presentation.
 */

import { ProductMatrixItem, InventoryItem, CustomerOrder } from '../types';
import { num, str, Row } from './fiestaApi';

/** Best-effort category label from the numeric category id Fiesta returns. */
export function categoryName(categoryid: number): string {
  const map: Record<number, string> = {
    1: 'Food & Dining',
    2: 'Grocery & Daily',
    3: 'Pharmacy',
    4: 'Retail',
  };
  return map[categoryid] || `Category ${categoryid}`;
}

const PLACEHOLDER_IMG =
  'https://images.unsplash.com/photo-1542838132-92c53300491e?auto=format&fit=crop&q=80&w=200';

/** Derive a healthy/low/critical status from a closing balance. */
function stockStatus(closing: number): InventoryItem['status'] {
  if (closing <= 0) return 'Critical';
  if (closing < 25) return 'Critical';
  if (closing < 120) return 'Low Stock';
  return 'Optimal';
}

/** stock-statement row -> catalog card. */
export function stockRowToProduct(row: Row): ProductMatrixItem {
  const closing = num(row.closing);
  const cost = num(row.productcost);
  const retail = num(row.retailprice) || cost;
  const sold = Math.max(0, num(row.debit));
  const status = stockStatus(closing);
  return {
    id: str(row.productid) || str(row.productname),
    name: str(row.productname) || 'Unnamed product',
    sku: `SKU-${str(row.productid)}`,
    unitsSold: sold,
    revenue: Math.round(sold * retail),
    stockStatus: status === 'Optimal' ? 'Healthy' : status,
    trend: num(row.credit) > num(row.debit) ? 'up' : num(row.debit) > 0 ? 'down' : 'flat',
    image: str(row.productimage) || PLACEHOLDER_IMG,
    category: categoryName(num(row.categoryid)),
    exposure: `${str(row.productunit) || 'unit'} · ${str(row.unitvalue) || '1'}`,
    verified: num(row.retailprice) > 0,
  };
}

/** stock-statement row -> hub balance ledger entry. */
export function stockRowToInventory(row: Row, locationName: string): InventoryItem {
  const closing = num(row.closing);
  const opening = num(row.opening);
  return {
    sku: `SKU-${str(row.productid)}`,
    name: str(row.productname) || 'Unnamed product',
    warehouse: locationName || `Location ${str(row.locationid)}`,
    stockLevel: closing,
    maxCapacity: Math.max(opening, closing, 100),
    status: stockStatus(closing),
    region: categoryName(num(row.categoryid)),
  };
}

const ORDER_STATUS_MAP: Record<string, CustomerOrder['status']> = {
  delivered: 'DELIVERED',
  picked: 'OUT_FOR_DELIVERY',
  active: 'OUT_FOR_DELIVERY',
  arrived: 'OUT_FOR_DELIVERY',
  accepted: 'CONFIRMED',
  assigned: 'CONFIRMED',
  ready: 'CONFIRMED',
  created: 'PROCESSING',
  pending: 'PROCESSING',
  processing: 'PROCESSING',
};

/** Map a Fiesta delivery/order status string onto the view's status union. */
export function mapOrderStatus(raw: string): CustomerOrder['status'] {
  return ORDER_STATUS_MAP[str(raw).toLowerCase()] || 'PROCESSING';
}

/** Format a Fiesta timestamp (ISO or "YYYY-MM-DD HH:mm:ss") into a short time label. */
export function shortTime(raw: unknown): string {
  const s = str(raw);
  if (!s) return '—';
  const m = s.match(/(\d{1,2}):(\d{2})/);
  if (m) return `${m[1]}:${m[2]}`;
  return s.slice(0, 16).replace('T', ' ');
}

/** deliveries-board row -> dispatch order card. */
export function deliveryRowToOrder(row: Row): CustomerOrder {
  const amount = num(row.deliveryamt) || num(row.orderamount);
  const rider = str(row.ridername) || str(row.deliveryusername) || str(row.username);
  return {
    id: str(row.orderid) || `DLV-${str(row.deliveryid)}`,
    customerName: str(row.deliverycustomer) || str(row.customername) || 'Customer',
    phone: str(row.deliverycontactno) || str(row.contactno) || '—',
    address:
      str(row.deliveryaddress) ||
      str(row.Pickupaddress) ||
      str(row.pickupaddress) ||
      'Address unavailable',
    items: [],
    amount,
    time: shortTime(row.assigntime || row.deliverydate),
    status: mapOrderStatus(str(row.orderstatus)),
    assignedRider: rider || 'Pending Assignment',
    hub: str(row.pickupcustomer) || str(row.pickuplocation) || `Location ${str(row.locationid)}`,
    itemCount: num(row.itemcount),
    locationid: num(row.locationid)
  };
}

/**
 * orders-board row (from /orders/getorders) -> CustomerOrder card.
 * The orders API uses different field names than the deliveries board.
 */
export function orderRowToOrder(row: Row): CustomerOrder {
  // Amount: orders API returns orderamount / ordervalue / collectionamt
  const amount = num(row.ordervalue) || num(row.orderamount) || num(row.collectionamt);
  // Rider: may come from the linked delivery record
  const rider = str(row.ridername) || str(row.ridernames) || '';
  // Customer: orders use different field names
  const customerName =
    str(row.deliverycustomer) ||
    str(row.customername) ||
    str(row.firstname) + (str(row.lastname) ? ` ${str(row.lastname)}` : '') ||
    'Customer';
  // Address: drop address (where order is delivered)
  const address =
    str(row.deliveryaddress) ||
    str(row.deliverysuburb) ||
    str(row.pickupaddress) ||
    'Address unavailable';
  // Hub: store that fulfilled the order
  const hub =
    str(row.locationname) ||
    str(row.pickupcustomer) ||
    str(row.tenantname) ||
    `Location ${str(row.locationid)}`;

  return {
    id: str(row.orderid) || `ORD-${str(row.orderheaderid)}`,
    customerName: customerName.trim() || 'Customer',
    phone: str(row.contactno) || str(row.deliverycontactno) || '—',
    address,
    items: [],
    amount,
    time: shortTime(row.orderdate || row.deliverytime || row.createdat),
    status: mapOrderStatus(str(row.orderstatus)),
    assignedRider: rider || 'Pending Assignment',
    hub,
    itemCount: num(row.itemcount) || num(row.quantity),
    locationid: num(row.locationid),
  };
}

/** 
 * Map a Global Catalogue product row (from /catalogue/getproducts) to ProductMatrixItem.
 */
export function globalRowToProduct(row: Row): ProductMatrixItem {
  // Extract base price from price_range if possible, else 0
  const priceRange = str(row.price_range) || '';
  const priceMatch = priceRange.match(/\d+/);
  const basePrice = priceMatch ? parseInt(priceMatch[0], 10) : 0;

  return {
    id: str(row.id),
    name: str(row.product_name) || str(row.title) || 'Unnamed product',
    sku: str(row.product_sku) || str(row.variant_key) || `SKU-${str(row.id)}`,
    unitsSold: 0,
    revenue: basePrice,
    stockStatus: 'Healthy',
    trend: 'flat',
    image: (Array.isArray(row.images) && row.images.length > 0) ? str(row.images[0]) : str(row.image) || str(row.image_url) || (str(row.image_id) ? `https://fiesta.nearle.app/images/${str(row.image_id)}.jpg` : PLACEHOLDER_IMG),
    category: str(row.category) || 'Uncategorized',
    exposure: str(row.size) || '1 unit',
    verified: true,
    description: str(row.description) || undefined,
    fssaiLicense: str(row.fssai_license) || undefined,
    highlights: Array.isArray(row.highlights) ? row.highlights : [],
    nutrients: Array.isArray(row.nutrients) ? row.nutrients : [],
    providers: Array.isArray(row.providers) ? row.providers : [],
    brand: str(row.brand) || undefined,
    priceRange: str(row.price_range) || undefined,
  };
}
