<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<!--- Force recompile: 2026-01-09 --->
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfheader name="Cache-Control" value="no-store">

<cfscript>
/**
 * Get Order Detail
 * Returns full order info including line items and customer details
 *
 * GET: ?OrderID=123
 * POST: { OrderID: 123 }
 */

response = { "OK": false };

try {
    // Get OrderID from request
    orderID = 0;

    // Check URL params
    if (structKeyExists(url, "OrderID")) {
        orderID = val(url.OrderID);
    }

    // Check POST body
    if (orderID == 0) {
        requestBody = toString(getHttpRequestData().content);
        if (len(requestBody)) {
            requestData = deserializeJSON(requestBody);
            if (structKeyExists(requestData, "OrderID")) {
                orderID = val(requestData.OrderID);
            }
        }
    }

    if (orderID == 0) {
        response["ERROR"] = "missing_order_id";
        response["MESSAGE"] = "OrderID is required";
        writeOutput(serializeJSON(response));
        abort;
    }

    // Get order details
    qOrder = queryExecute("
        SELECT
            o.OrderID,
            o.OrderBusinessID,
            o.OrderUserID,
            o.OrderServicePointID,
            o.OrderStatusID,
            o.OrderTypeID,
            o.OrderRemarks,
            o.OrderAddedOn,
            o.OrderLastEditedOn,
            o.OrderSubmittedOn,
            u.UserFirstName,
            u.UserLastName,
            u.UserContactNumber,
            u.UserEmailAddress,
            sp.ServicePointName,
            sp.ServicePointTypeID,
            b.BusinessName
        FROM Orders o
        LEFT JOIN Users u ON u.UserID = o.OrderUserID
        LEFT JOIN ServicePoints sp ON sp.ServicePointID = o.OrderServicePointID
        LEFT JOIN Businesses b ON b.BusinessID = o.OrderBusinessID
        WHERE o.OrderID = :orderID
    ", { orderID: orderID });

    if (qOrder.recordCount == 0) {
        response["ERROR"] = "order_not_found";
        response["MESSAGE"] = "Order not found";
        writeOutput(serializeJSON(response));
        abort;
    }

    // Get line items (excluding deleted items)
    qItems = queryExecute("
        SELECT
            oli.OrderLineItemID,
            oli.OrderLineItemItemID,
            oli.OrderLineItemParentOrderLineItemID,
            oli.OrderLineItemQuantity,
            oli.OrderLineItemPrice,
            oli.OrderLineItemRemark,
            i.ItemName,
            i.ItemPrice,
            i.ItemIsCheckedByDefault
        FROM OrderLineItems oli
        INNER JOIN Items i ON i.ItemID = oli.OrderLineItemItemID
        WHERE oli.OrderLineItemOrderID = :orderID
          AND oli.OrderLineItemIsDeleted = 0
        ORDER BY oli.OrderLineItemID
    ", { orderID: orderID });

    // Build line items array with parent-child structure
    lineItems = [];
    itemsById = {};

    // First pass: create all items
    for (row in qItems) {
        item = {
            "LineItemID": row.OrderLineItemID,
            "ItemID": row.OrderLineItemItemID,
            "ParentLineItemID": row.OrderLineItemParentOrderLineItemID,
            "ItemName": row.ItemName,
            "Quantity": row.OrderLineItemQuantity,
            "UnitPrice": row.OrderLineItemPrice,
            "Remarks": row.OrderLineItemRemark,
            "IsDefault": (row.ItemIsCheckedByDefault == 1),
            "Modifiers": []
        };
        itemsById[row.OrderLineItemID] = item;
    }

    // Second pass: build hierarchy
    for (row in qItems) {
        item = itemsById[row.OrderLineItemID];
        parentID = row.OrderLineItemParentOrderLineItemID;

        if (parentID > 0 && structKeyExists(itemsById, parentID)) {
            // This is a modifier - add to parent
            arrayAppend(itemsById[parentID].Modifiers, item);
        } else {
            // This is a top-level item
            arrayAppend(lineItems, item);
        }
    }

    // Calculate subtotal from root line items
    subtotal = 0;
    for (item in lineItems) {
        itemTotal = item.UnitPrice * item.Quantity;
        // Add modifier prices
        for (mod in item.Modifiers) {
            itemTotal += mod.UnitPrice * mod.Quantity;
        }
        subtotal += itemTotal;
    }

    // Calculate tax (assume 8.75% if not stored)
    taxRate = 0.0875;
    tax = subtotal * taxRate;

    // Look up tip from Payments table if exists
    tip = 0;
    try {
        qPayment = queryExecute("
            SELECT PaymentTipAmount
            FROM Payments
            WHERE PaymentOrderID = :orderID
            LIMIT 1
        ", { orderID: orderID });
        if (qPayment.recordCount > 0 && !isNull(qPayment.PaymentTipAmount)) {
            tip = qPayment.PaymentTipAmount;
        }
    } catch (any e) {
        // Payments table may not exist or have this column, ignore
    }

    // Calculate total
    total = subtotal + tax + tip;

    // Build response
    order = {
        "OrderID": qOrder.OrderID,
        "BusinessID": qOrder.OrderBusinessID,
        "BusinessName": qOrder.BusinessName ?: "",
        "Status": qOrder.OrderStatusID,
        "StatusText": getStatusText(qOrder.OrderStatusID),
        "OrderTypeID": qOrder.OrderTypeID ?: 0,
        "OrderTypeName": getOrderTypeName(qOrder.OrderTypeID ?: 0),
        "Subtotal": subtotal,
        "Tax": tax,
        "Tip": tip,
        "Total": total,
        "Notes": qOrder.OrderRemarks,
        "CreatedOn": dateTimeFormat(qOrder.OrderAddedOn, "yyyy-mm-dd HH:nn:ss"),
        "SubmittedOn": len(qOrder.OrderSubmittedOn) ? dateTimeFormat(qOrder.OrderSubmittedOn, "yyyy-mm-dd HH:nn:ss") : "",
        "UpdatedOn": len(qOrder.OrderLastEditedOn) ? dateTimeFormat(qOrder.OrderLastEditedOn, "yyyy-mm-dd HH:nn:ss") : "",
        "Customer": {
            "UserID": qOrder.OrderUserID,
            "FirstName": qOrder.UserFirstName,
            "LastName": qOrder.UserLastName,
            "Phone": qOrder.UserContactNumber,
            "Email": qOrder.UserEmailAddress
        },
        "ServicePoint": {
            "ServicePointID": qOrder.OrderServicePointID,
            "Name": qOrder.ServicePointName,
            "TypeID": qOrder.ServicePointTypeID
        },
        "LineItems": lineItems
    };

    response["OK"] = true;
    response["ORDER"] = order;

} catch (any e) {
    response["ERROR"] = "server_error";
    response["MESSAGE"] = e.message;
}

writeOutput(serializeJSON(response));

// Helper functions
function getStatusText(status) {
    switch (status) {
        case 0: return "Cart";
        case 1: return "Submitted";
        case 2: return "In Progress";
        case 3: return "Ready";
        case 4: return "Completed";
        case 5: return "Cancelled";
        default: return "Unknown";
    }
}

function getOrderTypeName(orderType) {
    switch (orderType) {
        case 1: return "Dine-in";
        case 2: return "Takeaway";
        case 3: return "Delivery";
        default: return "Unknown";
    }
}
</cfscript>
