<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<cfsetting requesttimeout="300">
<cfcontent type="application/json; charset=utf-8" reset="true">

<cfscript>
/**
 * Import Business from Scraped Data
 *
 * Creates a complete business with:
 * - Business record with contact info
 * - Categories as Items (ParentID=0)
 * - Menu items as children of categories
 * - Modifier templates linked via ItemTemplateLinks
 * - Modifier options as children of templates
 *
 * POST JSON structure:
 * {
 *   "business": {
 *     "name": "Big Dean's Ocean Front Cafe",
 *     "address": "1615 Ocean Front Walk",
 *     "city": "Santa Monica",
 *     "state": "CA",
 *     "zip": "90401",
 *     "phone": "(310) 393-2666",
 *     "email": "owner@bigdeans.com",
 *     "ownerPhone": "3101234567",
 *     "website": "https://bigdeansoceanfrontcafe.com",
 *     "logoUrl": "https://...",
 *     "headerUrl": "https://...",
 *     "hours": {
 *       "mon": "12:00 PM - 7:00 PM",
 *       "tue": "11:00 AM - 8:00 PM",
 *       ...
 *     }
 *   },
 *   "categories": [
 *     {
 *       "name": "World Famous Burgers",
 *       "sortOrder": 1,
 *       "items": [
 *         {
 *           "name": "Big Dean's Burger",
 *           "description": "The burger that made Santa Monica famous!",
 *           "price": 12.99,
 *           "modifiers": ["onion_style", "add_cheese"]  // template references
 *         }
 *       ]
 *     }
 *   ],
 *   "modifierTemplates": [
 *     {
 *       "id": "onion_style",
 *       "name": "Onions",
 *       "required": true,
 *       "maxSelections": 1,
 *       "options": [
 *         { "name": "No Onions", "price": 0, "isDefault": false },
 *         { "name": "Grilled Onions", "price": 0, "isDefault": true },
 *         { "name": "Raw Onions", "price": 0, "isDefault": false }
 *       ]
 *     }
 *   ],
 *   "ownerUserID": 2,  // optional, defaults to 1
 *   "dryRun": false    // optional, if true just validates without inserting
 * }
 */

response = { "OK": false, "steps": [], "errors": [], "warnings": [] };

try {
    requestBody = toString(getHttpRequestData().content);
    if (!len(requestBody)) {
        throw(message="No request body provided");
    }

    data = deserializeJSON(requestBody);
    dryRun = structKeyExists(data, "dryRun") && data.dryRun == true;

    if (dryRun) {
        response.steps.append("DRY RUN MODE - no changes will be made");
    }

    // Validate required fields
    if (!structKeyExists(data, "business") || !structKeyExists(data.business, "name")) {
        throw(message="business.name is required");
    }

    biz = data.business;
    ownerUserID = structKeyExists(data, "ownerUserID") ? val(data.ownerUserID) : 1;

    // Step 1: Create or find business
    response.steps.append("Step 1: Creating business record...");

    qCheck = queryExecute("
        SELECT BusinessID FROM Businesses WHERE BusinessName = :name
    ", { name: biz.name }, { datasource: "payfrit" });

    if (qCheck.recordCount > 0) {
        BusinessID = qCheck.BusinessID;
        response.steps.append("Business already exists with ID: " & BusinessID);
        response.warnings.append("Existing business found - will add to existing menu");
    } else if (!dryRun) {
        queryExecute("
            INSERT INTO Businesses (BusinessName, BusinessUserID, BusinessAddressID, BusinessDeliveryZipCodes, BusinessAddedOn) VALUES (:name, :ownerID, 0, '', NOW())
        ", {
            name: biz.name, ownerID: ownerUserID
        }, { datasource: "payfrit" });

        qNew = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
        BusinessID = qNew.id;
        response.steps.append("Created business with ID: " & BusinessID);
    } else {
        BusinessID = 0;
        response.steps.append("Would create business: " & biz.name);
    }

    // Step 2: Create modifier templates first (they need to exist before items reference them)
    response.steps.append("Step 2: Creating modifier templates...");

    templateMap = {}; // Maps template string ID to database ItemID
    templates = structKeyExists(data, "modifierTemplates") ? data.modifierTemplates : [];

    for (tmpl in templates) {
        templateStringID = tmpl.id;
        templateName = tmpl.name;
        required = structKeyExists(tmpl, "required") && tmpl.required == true;
        maxSelections = structKeyExists(tmpl, "maxSelections") ? val(tmpl.maxSelections) : 0;

        if (!dryRun) {
            // Check if template already exists for this business
            qTmpl = queryExecute("
                SELECT ItemID FROM Items
                WHERE ItemBusinessID = :bizID
                  AND ItemName = :name
                  AND ItemParentItemID = 0
                  AND ItemID IN (SELECT TemplateItemID FROM ItemTemplateLinks)
            ", { bizID: BusinessID, name: templateName }, { datasource: "payfrit" });

            if (qTmpl.recordCount > 0) {
                templateItemID = qTmpl.ItemID;
                response.steps.append("Template exists: " & templateName & " (ID: " & templateItemID & ")");
            } else {
                // Create template as Item at ParentID=0, with ItemIsCollapsible=1 to mark it as a template
                // This ensures the API filter excludes it from categories
                queryExecute("
                    INSERT INTO Items (
                        ItemBusinessID, ItemName, ItemParentItemID, ItemPrice,
                        ItemIsActive, ItemRequiresChildSelection, ItemMaxNumSelectionReq, ItemSortOrder, ItemIsCollapsible
                    ) VALUES (
                        :bizID, :name, 0, 0, 1, :required, :maxSelect, 0, 1
                    )
                ", {
                    bizID: BusinessID,
                    name: templateName,
                    required: required ? 1 : 0,
                    maxSelect: maxSelections
                }, { datasource: "payfrit" });

                qNewTmpl = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
                templateItemID = qNewTmpl.id;
                response.steps.append("Created template: " & templateName & " (ID: " & templateItemID & ")");
            }

            templateMap[templateStringID] = templateItemID;

            // Create template options
            options = structKeyExists(tmpl, "options") ? tmpl.options : [];
            optionOrder = 1;
            for (opt in options) {
                optName = opt.name;
                optPrice = structKeyExists(opt, "price") ? val(opt.price) : 0;
                optDefault = structKeyExists(opt, "isDefault") && opt.isDefault == true;

                qOpt = queryExecute("
                    SELECT ItemID FROM Items
                    WHERE ItemBusinessID = :bizID AND ItemName = :name AND ItemParentItemID = :parentID
                ", { bizID: BusinessID, name: optName, parentID: templateItemID }, { datasource: "payfrit" });

                if (qOpt.recordCount == 0) {
                    queryExecute("
                        INSERT INTO Items (
                            ItemBusinessID, ItemName, ItemParentItemID, ItemPrice,
                            ItemIsActive, ItemIsCheckedByDefault, ItemSortOrder
                        ) VALUES (
                            :bizID, :name, :parentID, :price, 1, :isDefault, :sortOrder
                        )
                    ", {
                        bizID: BusinessID,
                        name: optName,
                        parentID: templateItemID,
                        price: optPrice,
                        isDefault: optDefault ? 1 : 0,
                        sortOrder: optionOrder
                    }, { datasource: "payfrit" });
                }
                optionOrder++;
            }
        } else {
            response.steps.append("Would create template: " & templateName & " with " & arrayLen(tmpl.options) & " options");
            templateMap[templateStringID] = 0;
        }
    }

    // Step 3: Create categories (as Items at ParentID=0)
    response.steps.append("Step 3: Creating categories...");

    categoryMap = {}; // Maps category name to ItemID
    categories = structKeyExists(data, "categories") ? data.categories : [];
    catOrder = 1;

    for (cat in categories) {
        catName = cat.name;

        if (!dryRun) {
            // Check if category exists (Item at ParentID=0, not a template)
            qCat = queryExecute("
                SELECT ItemID FROM Items
                WHERE ItemBusinessID = :bizID
                  AND ItemName = :name
                  AND ItemParentItemID = 0
                  AND ItemID NOT IN (SELECT TemplateItemID FROM ItemTemplateLinks)
            ", { bizID: BusinessID, name: catName }, { datasource: "payfrit" });

            if (qCat.recordCount > 0) {
                categoryItemID = qCat.ItemID;
                response.steps.append("Category exists: " & catName);
            } else {
                queryExecute("
                    INSERT INTO Items (
                        ItemBusinessID, ItemName, ItemParentItemID, ItemPrice,
                        ItemIsActive, ItemSortOrder
                    ) VALUES (
                        :bizID, :name, 0, 0, 1, :sortOrder
                    )
                ", {
                    bizID: BusinessID,
                    name: catName,
                    sortOrder: catOrder
                }, { datasource: "payfrit" });

                qNewCat = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
                categoryItemID = qNewCat.id;
                response.steps.append("Created category: " & catName & " (ID: " & categoryItemID & ")");
            }

            categoryMap[catName] = categoryItemID;
        } else {
            response.steps.append("Would create category: " & catName);
            categoryMap[catName] = 0;
        }
        catOrder++;
    }

    // Step 4: Create menu items as children of categories
    response.steps.append("Step 4: Creating menu items...");

    totalItems = 0;
    totalLinks = 0;

    for (cat in categories) {
        catName = cat.name;
        categoryItemID = categoryMap[catName];
        items = structKeyExists(cat, "items") ? cat.items : [];
        itemOrder = 1;

        for (item in items) {
            itemName = item.name;
            itemDesc = structKeyExists(item, "description") ? item.description : "";
            itemPrice = structKeyExists(item, "price") ? val(item.price) : 0;

            if (!dryRun) {
                // Check if item exists
                qItem = queryExecute("
                    SELECT ItemID FROM Items
                    WHERE ItemBusinessID = :bizID AND ItemName = :name AND ItemParentItemID = :parentID
                ", { bizID: BusinessID, name: itemName, parentID: categoryItemID }, { datasource: "payfrit" });

                if (qItem.recordCount > 0) {
                    menuItemID = qItem.ItemID;
                } else {
                    queryExecute("
                        INSERT INTO Items (
                            ItemBusinessID, ItemName, ItemDescription, ItemParentItemID,
                            ItemPrice, ItemIsActive, ItemSortOrder
                        ) VALUES (
                            :bizID, :name, :desc, :parentID, :price, 1, :sortOrder
                        )
                    ", {
                        bizID: BusinessID,
                        name: itemName,
                        desc: itemDesc,
                        parentID: categoryItemID,
                        price: itemPrice,
                        sortOrder: itemOrder
                    }, { datasource: "payfrit" });

                    qNewItem = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
                    menuItemID = qNewItem.id;
                }

                // Link modifier templates to this item
                modifiers = structKeyExists(item, "modifiers") ? item.modifiers : [];
                modOrder = 1;
                for (modRef in modifiers) {
                    if (structKeyExists(templateMap, modRef)) {
                        templateItemID = templateMap[modRef];

                        // Check if link exists
                        qLink = queryExecute("
                            SELECT 1 FROM ItemTemplateLinks
                            WHERE ItemID = :itemID AND TemplateItemID = :templateID
                        ", { itemID: menuItemID, templateID: templateItemID }, { datasource: "payfrit" });

                        if (qLink.recordCount == 0) {
                            queryExecute("
                                INSERT INTO ItemTemplateLinks (ItemID, TemplateItemID, SortOrder)
                                VALUES (:itemID, :templateID, :sortOrder)
                            ", {
                                itemID: menuItemID,
                                templateID: templateItemID,
                                sortOrder: modOrder
                            }, { datasource: "payfrit" });
                            totalLinks++;
                        }
                        modOrder++;
                    } else {
                        response.warnings.append("Unknown modifier reference: " & modRef & " on item: " & itemName);
                    }
                }
            }

            totalItems++;
            itemOrder++;
        }
    }

    response.steps.append("Created " & totalItems & " menu items with " & totalLinks & " template links");

    // Summary
    response.OK = true;
    response.summary = {
        "businessID": BusinessID,
        "businessName": biz.name,
        "categoriesCreated": arrayLen(categories),
        "templatesCreated": arrayLen(templates),
        "itemsCreated": totalItems,
        "templateLinksCreated": totalLinks,
        "dryRun": dryRun
    };

    if (dryRun) {
        response.steps.append("DRY RUN COMPLETE - no changes were made");
    } else {
        response.steps.append("IMPORT COMPLETE!");
    }

} catch (any e) {
    response.errors.append(e.message);
    if (len(e.detail)) {
        response.errors.append(e.detail);
    }
}

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