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

<cfscript>
/**
 * Menu CRUD API
 *
 * GET: List all menus for a business
 * POST: Create or update a menu
 * DELETE: Soft-delete a menu
 *
 * Input: BusinessID, and optionally Menu data for POST
 */

response = { "OK": false };

try {
    requestBody = toString(getHttpRequestData().content);
    requestData = {};
    if (len(requestBody)) {
        requestData = deserializeJSON(requestBody);
    }

    businessID = 0;
    if (structKeyExists(requestData, "BusinessID")) {
        businessID = val(requestData.BusinessID);
    }

    if (businessID == 0) {
        apiAbort({ "OK": false, "ERROR": "missing_business_id", "MESSAGE": "BusinessID is required" });
    }

    method = cgi.REQUEST_METHOD;
    action = structKeyExists(requestData, "action") ? lCase(requestData.action) : "list";

    // Handle different actions
    switch (action) {
        case "list":
            // Get all active menus for this business
            qMenus = queryTimed("
                SELECT
                    ID,
                    Name,
                    Description,
                    DaysActive,
                    StartTime,
                    EndTime,
                    SortOrder,
                    IsActive
                FROM Menus
                WHERE BusinessID = :businessID
                  AND IsActive = 1
                ORDER BY SortOrder, Name
            ", { businessID: businessID }, { datasource: "payfrit" });

            menus = [];
            for (i = 1; i <= qMenus.recordCount; i++) {
                // Count categories in this menu
                qCatCount = queryTimed("
                    SELECT COUNT(*) as cnt FROM Categories
                    WHERE BusinessID = :businessID
                      AND MenuID = :menuID
                ", { businessID: businessID, menuID: qMenus.ID[i] }, { datasource: "payfrit" });

                arrayAppend(menus, {
                    "MenuID": qMenus.ID[i],
                    "Name": qMenus.Name[i],
                    "Description": isNull(qMenus.Description[i]) ? "" : qMenus.Description[i],
                    "DaysActive": qMenus.DaysActive[i],
                    "StartTime": isNull(qMenus.StartTime[i]) ? "" : timeFormat(qMenus.StartTime[i], "HH:mm"),
                    "EndTime": isNull(qMenus.EndTime[i]) ? "" : timeFormat(qMenus.EndTime[i], "HH:mm"),
                    "SortOrder": qMenus.SortOrder[i],
                    "CategoryCount": qCatCount.cnt
                });
            }

            response = {
                "OK": true,
                "MENUS": menus,
                "COUNT": arrayLen(menus)
            };
            break;

        case "get":
            // Get a single menu by ID
            menuID = structKeyExists(requestData, "MenuID") ? val(requestData.MenuID) : 0;
            if (menuID == 0) {
                apiAbort({ "OK": false, "ERROR": "missing_menu_id", "MESSAGE": "MenuID is required" });
            }

            qMenu = queryTimed("
                SELECT * FROM Menus
                WHERE ID = :menuID AND BusinessID = :businessID
            ", { menuID: menuID, businessID: businessID }, { datasource: "payfrit" });

            if (qMenu.recordCount == 0) {
                apiAbort({ "OK": false, "ERROR": "menu_not_found", "MESSAGE": "Menu not found" });
            }

            response = {
                "OK": true,
                "MENU": {
                    "MenuID": qMenu.ID,
                    "Name": qMenu.Name,
                    "Description": isNull(qMenu.Description) ? "" : qMenu.Description,
                    "DaysActive": qMenu.DaysActive,
                    "StartTime": isNull(qMenu.StartTime) ? "" : timeFormat(qMenu.StartTime, "HH:mm"),
                    "EndTime": isNull(qMenu.EndTime) ? "" : timeFormat(qMenu.EndTime, "HH:mm"),
                    "SortOrder": qMenu.SortOrder,
                    "IsActive": qMenu.IsActive
                }
            };
            break;

        case "save":
            // Create or update a menu
            menuID = structKeyExists(requestData, "MenuID") ? val(requestData.MenuID) : 0;
            menuName = structKeyExists(requestData, "Name") ? trim(requestData.Name) : "";
            menuDescription = structKeyExists(requestData, "Description") ? trim(requestData.Description) : "";
            menuDaysActive = structKeyExists(requestData, "DaysActive") ? val(requestData.DaysActive) : 127;
            menuStartTime = structKeyExists(requestData, "StartTime") && len(trim(requestData.StartTime)) ? trim(requestData.StartTime) : "";
            menuEndTime = structKeyExists(requestData, "EndTime") && len(trim(requestData.EndTime)) ? trim(requestData.EndTime) : "";
            menuSortOrder = structKeyExists(requestData, "SortOrder") ? val(requestData.SortOrder) : 0;

            if (len(menuName) == 0) {
                apiAbort({ "OK": false, "ERROR": "missing_menu_name", "MESSAGE": "Menu name is required" });
            }

            if (menuID > 0) {
                // Update existing menu
                queryTimed("
                    UPDATE Menus SET
                        Name = :menuName,
                        Description = :menuDescription,
                        DaysActive = :menuDaysActive,
                        StartTime = :menuStartTime,
                        EndTime = :menuEndTime,
                        SortOrder = :menuSortOrder
                    WHERE ID = :menuID AND BusinessID = :businessID
                ", {
                    menuID: { value: menuID, cfsqltype: "cf_sql_integer" },
                    businessID: { value: businessID, cfsqltype: "cf_sql_integer" },
                    menuName: { value: menuName, cfsqltype: "cf_sql_varchar" },
                    menuDescription: { value: menuDescription, cfsqltype: "cf_sql_varchar" },
                    menuDaysActive: { value: menuDaysActive, cfsqltype: "cf_sql_integer" },
                    menuStartTime: { value: menuStartTime, cfsqltype: "cf_sql_time", null: !len(menuStartTime) },
                    menuEndTime: { value: menuEndTime, cfsqltype: "cf_sql_time", null: !len(menuEndTime) },
                    menuSortOrder: { value: menuSortOrder, cfsqltype: "cf_sql_integer" }
                }, { datasource: "payfrit" });

                response = { "OK": true, "MenuID": menuID, "ACTION": "updated" };
            } else {
                // Create new menu
                queryTimed("
                    INSERT INTO Menus (
                        BusinessID, Name, Description,
                        DaysActive, StartTime, EndTime,
                        SortOrder, IsActive, AddedOn
                    ) VALUES (
                        :businessID, :menuName, :menuDescription,
                        :menuDaysActive, :menuStartTime, :menuEndTime,
                        :menuSortOrder, 1, NOW()
                    )
                ", {
                    businessID: { value: businessID, cfsqltype: "cf_sql_integer" },
                    menuName: { value: menuName, cfsqltype: "cf_sql_varchar" },
                    menuDescription: { value: menuDescription, cfsqltype: "cf_sql_varchar" },
                    menuDaysActive: { value: menuDaysActive, cfsqltype: "cf_sql_integer" },
                    menuStartTime: { value: menuStartTime, cfsqltype: "cf_sql_time", null: !len(menuStartTime) },
                    menuEndTime: { value: menuEndTime, cfsqltype: "cf_sql_time", null: !len(menuEndTime) },
                    menuSortOrder: { value: menuSortOrder, cfsqltype: "cf_sql_integer" }
                }, { datasource: "payfrit" });

                result = queryTimed("SELECT LAST_INSERT_ID() as newID", {}, { datasource: "payfrit" });
                response = { "OK": true, "MenuID": result.newID, "ACTION": "created" };
            }
            break;

        case "delete":
            // Soft-delete a menu
            menuID = structKeyExists(requestData, "MenuID") ? val(requestData.MenuID) : 0;
            if (menuID == 0) {
                apiAbort({ "OK": false, "ERROR": "missing_menu_id", "MESSAGE": "MenuID is required" });
            }

            // Check if menu has categories/items for warning
            qCatCheck = queryTimed("
                SELECT COUNT(*) as cnt FROM Categories
                WHERE MenuID = :menuID AND BusinessID = :businessID
            ", { menuID: menuID, businessID: businessID }, { datasource: "payfrit" });

            // Unassign categories from this menu
            if (qCatCheck.cnt > 0) {
                queryTimed("
                    UPDATE Categories SET MenuID = 0
                    WHERE MenuID = :menuID AND BusinessID = :businessID
                ", { menuID: menuID, businessID: businessID }, { datasource: "payfrit" });
            }

            // Soft-delete the menu
            queryTimed("
                UPDATE Menus SET IsActive = 0
                WHERE ID = :menuID AND BusinessID = :businessID
            ", { menuID: menuID, businessID: businessID }, { datasource: "payfrit" });

            response = {
                "OK": true,
                "MenuID": menuID,
                "ACTION": "deleted",
                "CategoriesUnassigned": qCatCheck.cnt
            };
            break;

        case "reorder":
            // Reorder menus
            menuOrder = structKeyExists(requestData, "MenuOrder") ? requestData.MenuOrder : [];
            if (!isArray(menuOrder) || arrayLen(menuOrder) == 0) {
                apiAbort({ "OK": false, "ERROR": "missing_menu_order", "MESSAGE": "MenuOrder array is required" });
            }

            for (i = 1; i <= arrayLen(menuOrder); i++) {
                queryTimed("
                    UPDATE Menus SET SortOrder = :sortOrder
                    WHERE ID = :menuID AND BusinessID = :businessID
                ", {
                    menuID: val(menuOrder[i]),
                    businessID: businessID,
                    sortOrder: i - 1
                }, { datasource: "payfrit" });
            }

            response = { "OK": true, "ACTION": "reordered" };
            break;

        case "setDefault":
            // Set the default menu for this business
            menuID = structKeyExists(requestData, "MenuID") ? val(requestData.MenuID) : 0;
            // MenuID of 0 means "no default" (clear the default)

            if (menuID > 0) {
                // Verify the menu exists and belongs to this business
                qCheck = queryTimed("
                    SELECT ID FROM Menus WHERE ID = :menuID AND BusinessID = :businessID AND IsActive = 1
                ", { menuID: menuID, businessID: businessID }, { datasource: "payfrit" });

                if (qCheck.recordCount == 0) {
                    apiAbort({ "OK": false, "ERROR": "invalid_menu", "MESSAGE": "Menu not found or not active" });
                }
            }

            queryTimed("
                UPDATE Businesses SET DefaultMenuID = :menuID WHERE ID = :businessID
            ", {
                menuID: { value: menuID, cfsqltype: "cf_sql_integer", null: menuID == 0 },
                businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
            }, { datasource: "payfrit" });

            response = { "OK": true, "ACTION": "defaultSet", "DefaultMenuID": menuID };
            break;

        default:
            apiAbort({ "OK": false, "ERROR": "invalid_action", "MESSAGE": "Unknown action: " & action });
    }

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

}

try{logPerf(0);}catch(any e){}
writeOutput(serializeJSON(response));
</cfscript>
