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

<cfscript>
/**
 * Save/Update Category
 *
 * POST body:
 * {
 *   "CategoryID": 123,              // Required for update
 *   "BusinessID": 37,       // Required for insert
 *   "Name": "Breakfast",
 *   "SortOrder": 1,
 *   "OrderTypes": "1,2,3",  // 1=Dine-In, 2=Takeaway, 3=Delivery
 *   "ScheduleStart": "06:00:00",  // Optional, null = always available
 *   "ScheduleEnd": "11:00:00",    // Optional
 *   "ScheduleDays": "2,3,4,5,6"   // Optional, 1=Sun..7=Sat, null = all days
 * }
 */

function readJsonBody() {
    var raw = getHttpRequestData().content;
    if (isNull(raw) || len(trim(raw)) == 0) return {};
    try {
        var data = deserializeJSON(raw);
        return isStruct(data) ? data : {};
    } catch (any e) {
        return {};
    }
}

response = { "OK": false };

try {
    data = readJsonBody();

    CategoryID = structKeyExists(data, "CategoryID") ? val(data.CategoryID) : 0;
    BusinessID = structKeyExists(data, "BusinessID") ? val(data.BusinessID) : 0;
    Name = structKeyExists(data, "Name") ? left(trim(data.Name), 30) : "";
    SortOrder = structKeyExists(data, "SortOrder") ? val(data.SortOrder) : 0;
    OrderTypes = structKeyExists(data, "OrderTypes") ? trim(data.OrderTypes) : "1,2,3";
    ScheduleStart = structKeyExists(data, "ScheduleStart") && len(trim(data.ScheduleStart))
        ? trim(data.ScheduleStart) : javaCast("null", "");
    ScheduleEnd = structKeyExists(data, "ScheduleEnd") && len(trim(data.ScheduleEnd))
        ? trim(data.ScheduleEnd) : javaCast("null", "");
    ScheduleDays = structKeyExists(data, "ScheduleDays") && len(trim(data.ScheduleDays))
        ? trim(data.ScheduleDays) : javaCast("null", "");

    if (CategoryID > 0) {
        // Update existing category
        queryExecute("
            UPDATE Categories SET
                Name = :name,
                SortOrder = :sortOrder,
                OrderTypes = :orderTypes,
                ScheduleStart = :schedStart,
                ScheduleEnd = :schedEnd,
                ScheduleDays = :schedDays
            WHERE ID = :catId
        ", {
            catId: CategoryID,
            name: Name,
            sortOrder: SortOrder,
            orderTypes: OrderTypes,
            schedStart: { value = ScheduleStart, cfsqltype = "cf_sql_time", null = isNull(ScheduleStart) },
            schedEnd: { value = ScheduleEnd, cfsqltype = "cf_sql_time", null = isNull(ScheduleEnd) },
            schedDays: { value = ScheduleDays, cfsqltype = "cf_sql_varchar", null = isNull(ScheduleDays) }
        }, { datasource = "payfrit" });

        response["OK"] = true;
        response["CategoryID"] = CategoryID;
        response["MESSAGE"] = "Category updated";

    } else if (BusinessID > 0 && len(Name)) {
        // Insert new category
        queryExecute("
            INSERT INTO Categories
            (BusinessID, Name, SortOrder, OrderTypes,
             ScheduleStart, ScheduleEnd, ScheduleDays, AddedOn)
            VALUES
            (:bizId, :name, :sortOrder, :orderTypes, :schedStart, :schedEnd, :schedDays, NOW())
        ", {
            bizId: BusinessID,
            name: Name,
            sortOrder: SortOrder,
            orderTypes: OrderTypes,
            schedStart: { value = ScheduleStart, cfsqltype = "cf_sql_time", null = isNull(ScheduleStart) },
            schedEnd: { value = ScheduleEnd, cfsqltype = "cf_sql_time", null = isNull(ScheduleEnd) },
            schedDays: { value = ScheduleDays, cfsqltype = "cf_sql_varchar", null = isNull(ScheduleDays) }
        }, { datasource = "payfrit" });

        qNew = queryExecute("SELECT LAST_INSERT_ID() as newId", {}, { datasource = "payfrit" });
        response["OK"] = true;
        response["CategoryID"] = qNew.newId;
        response["MESSAGE"] = "Category created";

    } else {
        response["ERROR"] = "invalid_params";
        response["MESSAGE"] = "CategoryID required for update, or BusinessID and Name for insert";
    }

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

writeOutput(serializeJSON(response));
</cfscript>
