<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfheader name="Cache-Control" value="no-store">

<cfscript>
/**
 * Order History API
 * Returns list of completed/submitted orders for the authenticated user
 *
 * GET: ?limit=20&offset=0
 */

function apiAbort(required struct payload) {
  writeOutput(serializeJSON(payload));
  abort;
}

// Helper to get header value - use servlet request object (CGI scope doesn't expose custom HTTP headers in Lucee)
function getHeader(name) {
  try {
    req = getPageContext().getRequest();
    val = req.getHeader(arguments.name);
    if (!isNull(val)) return trim(val);
  } catch (any e) {
    // Fall back to CGI scope
    k = "HTTP_" & ucase(reReplace(arguments.name, "[^A-Za-z0-9]", "_", "all"));
    if (structKeyExists(cgi, k)) return trim(cgi[k]);
  }
  return "";
}

// Get authenticated user - try request scope first, then do token lookup
userId = 0;
if (structKeyExists(request, "UserID") && isNumeric(request.UserID) && request.UserID > 0) {
  userId = request.UserID;
} else {
  userToken = getHeader("X-User-Token");
  if (len(userToken)) {
    try {
      qTok = queryTimed(
        "SELECT UserID FROM UserTokens WHERE Token = ? LIMIT 1",
        [ { value = userToken, cfsqltype = "cf_sql_varchar" } ],
        { datasource = "payfrit" }
      );
      if (qTok.recordCount EQ 1) {
        userId = qTok.UserID;
      }
    } catch (any e) { /* ignore */ }
  }
}

if (userId <= 0) {
  apiAbort({ "OK": false, "ERROR": "not_logged_in", "MESSAGE": "Authentication required" });
}

// Parse params
limit = val(url.limit ?: 20);
offset = val(url.offset ?: 0);
if (limit < 1) limit = 20;
if (limit > 100) limit = 100;
if (offset < 0) offset = 0;

try {
  // Get orders for this user (exclude carts - status 0)
  qOrders = queryTimed("
    SELECT
      o.ID,
      o.UUID,
      o.BusinessID,
      o.StatusID,
      o.OrderTypeID,
      o.AddedOn,
      o.LastEditedOn,
      b.Name AS BusinessName,
      CASE o.OrderTypeID
        WHEN 0 THEN 'Undecided'
        WHEN 1 THEN 'Dine-In'
        WHEN 2 THEN 'Takeaway'
        WHEN 3 THEN 'Delivery'
        ELSE 'Unknown'
      END AS OrderTypeName
    FROM Orders o
    LEFT JOIN Businesses b ON b.ID = o.BusinessID
    WHERE o.UserID = :userId
      AND o.StatusID > 0
    ORDER BY o.AddedOn DESC
    LIMIT :limit OFFSET :offset
  ", {
    userId: { value = userId, cfsqltype = "cf_sql_integer" },
    limit: { value = limit, cfsqltype = "cf_sql_integer" },
    offset: { value = offset, cfsqltype = "cf_sql_integer" }
  });

  // Get total count
  qCount = queryTimed("
    SELECT COUNT(*) as TotalCount
    FROM Orders
    WHERE UserID = :userId
      AND StatusID > 0
  ", { userId: { value = userId, cfsqltype = "cf_sql_integer" } });

  // Build orders array with item counts and totals
  orders = [];
  for (row in qOrders) {
    // Get line item count and calculate total
    qItems = queryTimed("
      SELECT
        COUNT(*) as ItemCount,
        SUM(Quantity * Price) as Subtotal
      FROM OrderLineItems
      WHERE OrderID = :orderId
        AND ParentOrderLineItemID = 0
        AND (IsDeleted = 0 OR IsDeleted IS NULL)
    ", { orderId: { value = row.ID, cfsqltype = "cf_sql_integer" } });

    itemCount = val(qItems.ItemCount);
    subtotal = val(qItems.Subtotal);
    tax = subtotal * 0.0875;
    total = subtotal + tax;

    // Get status text
    statusText = "";
    switch (row.StatusID) {
      case 1: statusText = "Submitted"; break;
      case 2: statusText = "In Progress"; break;
      case 3: statusText = "Ready"; break;
      case 4: statusText = "Completed"; break;
      case 5: statusText = "Cancelled"; break;
      default: statusText = "Unknown";
    }

    // Safely format dates
    createdAt = "";
    try {
      if (!isNull(row.AddedOn) && len(trim(row.AddedOn))) {
        createdAt = dateTimeFormat(row.AddedOn, "yyyy-mm-dd'T'HH:nn:ss");
      }
    } catch (any de) { createdAt = ""; }

    completedAt = "";
    try {
      if (row.StatusID >= 4 && !isNull(row.LastEditedOn) && len(trim(row.LastEditedOn))) {
        completedAt = dateTimeFormat(row.LastEditedOn, "yyyy-mm-dd'T'HH:nn:ss");
      }
    } catch (any de) { completedAt = ""; }

    arrayAppend(orders, {
      "OrderID": val(row.ID),
      "OrderUUID": row.UUID ?: "",
      "BusinessID": val(row.BusinessID),
      "BusinessName": row.BusinessName ?: "Unknown",
      "OrderTotal": round(val(total) * 100) / 100,
      "OrderStatusID": val(row.StatusID),
      "StatusName": statusText,
      "OrderTypeID": val(row.OrderTypeID),
      "TypeName": row.OrderTypeName ?: "Unknown",
      "ItemCount": val(itemCount),
      "CreatedAt": createdAt,
      "CompletedAt": completedAt
    });
  }

  try{logPerf(0);}catch(any e){}
  writeOutput(serializeJSON({
    "OK": true,
    "ORDERS": orders,
    "TOTAL_COUNT": qCount.TotalCount
  }));

} catch (any e) {
  apiAbort({
    "OK": false,
    "ERROR": "server_error",
    "MESSAGE": "Failed to load order history",
    "DETAIL": e.message,
    "DEBUG_LINE": e.tagContext[1].line ?: 0,
    "DEBUG_TEMPLATE": e.tagContext[1].template ?: ""
  });
}
</cfscript>
