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

<cfscript>
/**
 * Migrate Unified Schema to Categories
 *
 * This script:
 * 1. Finds all "category" Items (ParentID=0, not templates, not collapsible)
 * 2. Creates corresponding entries in Categories table
 * 3. Updates child Items with the new CategoryID
 *
 * GET: ?BusinessID=27 (or all if not specified)
 */

response = { "OK": false, "BusinessesProcessed": [], "Errors": [] };

try {
    // Get BusinessID from URL if specified
    businessFilter = "";
    if (structKeyExists(url, "BusinessID") && val(url.BusinessID) > 0) {
        businessFilter = val(url.BusinessID);
    }

    // Find all businesses with items in unified schema
    if (len(businessFilter)) {
        qBusinesses = queryTimed("
            SELECT DISTINCT BusinessID as BusinessID
            FROM Items
            WHERE BusinessID = :bid AND BusinessID > 0
        ", { bid: businessFilter }, { datasource: "payfrit" });
    } else {
        qBusinesses = queryTimed("
            SELECT DISTINCT BusinessID as BusinessID
            FROM Items
            WHERE BusinessID > 0
        ", {}, { datasource: "payfrit" });
    }

    for (biz in qBusinesses) {
        bizId = biz.ID;
        bizResult = { "BusinessID": bizId, "CategoriesCreated": 0, "ItemsUpdated": 0 };

        try {
            // Find category-like Items (parent=0, not collapsible, has children, not in template links)
            qCategoryItems = queryTimed("
                SELECT DISTINCT
                    p.ID,
                    p.Name,
                    p.SortOrder
                FROM Items p
                INNER JOIN Items c ON c.ParentItemID = p.ID
                WHERE p.BusinessID = :bizId
                  AND p.ParentItemID = 0
                  AND (p.IsCollapsible = 0 OR p.IsCollapsible IS NULL)
                  AND NOT EXISTS (
                      SELECT 1 FROM lt_ItemID_TemplateItemID tl WHERE tl.TemplateItemID = p.ID
                  )
                ORDER BY p.SortOrder, p.Name
            ", { bizId: bizId }, { datasource: "payfrit" });

            sortOrder = 0;
            for (catItem in qCategoryItems) {
                // Check if category already exists for this business with same name
                qExisting = queryTimed("
                    SELECT ID FROM Categories
                    WHERE BusinessID = :bizId AND Name = :name
                ", { bizId: bizId, name: left(catItem.Name, 30) }, { datasource: "payfrit" });

                if (qExisting.recordCount == 0) {
                    // Get next CategoryID
                    qMaxId = queryTimed("
                        SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Categories
                    ", {}, { datasource: "payfrit" });
                    newCatId = qMaxId.nextId;

                    // Create new category with explicit ID
                    queryTimed("
                        INSERT INTO Categories
                        (ID, BusinessID, ParentCategoryID, Name, SortOrder, AddedOn)
                        VALUES (:catId, :bizId, 0, :name, :sortOrder, NOW())
                    ", {
                        catId: newCatId,
                        bizId: bizId,
                        name: left(catItem.Name, 30),
                        sortOrder: sortOrder
                    }, { datasource: "payfrit" });

                    bizResult.CategoriesCreated++;
                } else {
                    newCatId = qExisting.ID;
                }

                // Update all children of this category Item to have the new CategoryID
                queryTimed("
                    UPDATE Items
                    SET CategoryID = :catId
                    WHERE ParentItemID = :parentId
                      AND BusinessID = :bizId
                ", {
                    catId: newCatId,
                    parentId: catItem.ID,
                    bizId: bizId
                }, { datasource: "payfrit" });

                qUpdated = queryTimed("SELECT ROW_COUNT() as cnt", {}, { datasource: "payfrit" });
                bizResult.ItemsUpdated += qUpdated.cnt;

                sortOrder++;
            }

            arrayAppend(response.BusinessesProcessed, bizResult);

        } catch (any bizErr) {
            arrayAppend(response.Errors, {
                "BusinessID": bizId,
                "Error": bizErr.message
            });
        }
    }

    response["OK"] = true;
    response["TotalBusinesses"] = qBusinesses.recordCount;

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

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