<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">

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

<cfscript>
/**
 * Update Business Settings
 * Updates settings for the currently selected business
 *
 * POST: {
 *   TaxRatePercent: 8.25  (percentage, will be converted to decimal)
 *   -- OR --
 *   TaxRate: 0.0825       (decimal, stored directly)
 * }
 *
 * Requires: request.BusinessID (set by auth middleware)
 */

function apiAbort(obj) {
    writeOutput(serializeJSON(obj));
    abort;
}

function readJsonBody() {
    raw = toString(getHttpRequestData().content);
    if (isNull(raw) || len(trim(raw)) EQ 0) {
        apiAbort({ OK: false, ERROR: "missing_body" });
    }
    try {
        parsed = deserializeJSON(raw);
    } catch (any e) {
        apiAbort({ OK: false, ERROR: "bad_json", MESSAGE: "Invalid JSON body" });
    }
    if (!isStruct(parsed)) {
        apiAbort({ OK: false, ERROR: "bad_json", MESSAGE: "JSON must be an object" });
    }
    return parsed;
}

if (!structKeyExists(request, "BusinessID") || !isNumeric(request.BusinessID) || request.BusinessID LTE 0) {
    apiAbort({ OK: false, ERROR: "no_business_selected" });
}

try {
    data = readJsonBody();
    updates = [];
    params = { businessId: request.BusinessID };

    // Handle tax rate (accept either percent or decimal)
    if (structKeyExists(data, "TaxRatePercent") && isNumeric(data.TaxRatePercent)) {
        taxRate = data.TaxRatePercent / 100;
        if (taxRate < 0 || taxRate > 0.5) {
            apiAbort({ OK: false, ERROR: "invalid_tax_rate", MESSAGE: "Tax rate must be between 0% and 50%" });
        }
        arrayAppend(updates, "TaxRate = :taxRate");
        params.taxRate = { value: taxRate, cfsqltype: "cf_sql_decimal" };
    } else if (structKeyExists(data, "TaxRate") && isNumeric(data.TaxRate)) {
        taxRate = data.TaxRate;
        if (taxRate < 0 || taxRate > 0.5) {
            apiAbort({ OK: false, ERROR: "invalid_tax_rate", MESSAGE: "Tax rate must be between 0 and 0.5" });
        }
        arrayAppend(updates, "TaxRate = :taxRate");
        params.taxRate = { value: taxRate, cfsqltype: "cf_sql_decimal" };
    }

    // Add more updatable fields as needed
    if (structKeyExists(data, "Name") && len(trim(data.Name))) {
        arrayAppend(updates, "Name = :businessName");
        params.businessName = { value: left(trim(data.Name), 100), cfsqltype: "cf_sql_varchar" };
    }

    if (structKeyExists(data, "Phone")) {
        arrayAppend(updates, "Phone = :phone");
        params.phone = { value: left(trim(data.Phone), 20), cfsqltype: "cf_sql_varchar" };
    }

    // Track whether we need to update address separately
    hasAddressUpdate = false;
    addrFields = {};
    if (structKeyExists(data, "Address") && len(trim(data.Address))) {
        hasAddressUpdate = true;
        addrFields.Line1 = left(trim(data.Address), 100);
    }
    if (structKeyExists(data, "City")) {
        hasAddressUpdate = true;
        addrFields.City = left(trim(data.City), 50);
    }
    if (structKeyExists(data, "Zip")) {
        hasAddressUpdate = true;
        addrFields.ZIPCode = left(trim(data.Zip), 10);
    }

    if (arrayLen(updates) == 0 && !hasAddressUpdate) {
        apiAbort({ OK: false, ERROR: "no_fields", MESSAGE: "No valid fields to update" });
    }

    // Build and execute Businesses update
    if (arrayLen(updates) > 0) {
        sql = "UPDATE Businesses SET " & arrayToList(updates, ", ") & " WHERE ID = :businessId";
        queryExecute(sql, params, { datasource: "payfrit" });
    }

    // Update address in Addresses table if needed
    if (hasAddressUpdate) {
        qExistingAddr = queryExecute("
            SELECT ID FROM Addresses
            WHERE (BusinessID = :businessId OR ID = (SELECT AddressID FROM Businesses WHERE ID = :businessId))
              AND IsDeleted = 0
            LIMIT 1
        ", { businessId: request.BusinessID }, { datasource: "payfrit" });

        if (qExistingAddr.recordCount > 0) {
            addrUpdates = [];
            addrParams = { addrId: qExistingAddr.ID };
            if (structKeyExists(addrFields, "Line1")) {
                arrayAppend(addrUpdates, "Line1 = :line1");
                addrParams.line1 = { value: addrFields.Line1, cfsqltype: "cf_sql_varchar" };
            }
            if (structKeyExists(addrFields, "City")) {
                arrayAppend(addrUpdates, "City = :city");
                addrParams.city = { value: addrFields.City, cfsqltype: "cf_sql_varchar" };
            }
            if (structKeyExists(addrFields, "ZIPCode")) {
                arrayAppend(addrUpdates, "ZIPCode = :zip");
                addrParams.zip = { value: addrFields.ZIPCode, cfsqltype: "cf_sql_varchar" };
            }
            if (arrayLen(addrUpdates) > 0) {
                queryExecute("UPDATE Addresses SET " & arrayToList(addrUpdates, ", ") & " WHERE ID = :addrId",
                    addrParams, { datasource: "payfrit" });
            }
        }
    }

    // Return updated settings
    q = queryExecute("
        SELECT b.ID, b.Name, b.TaxRate, b.Phone
        FROM Businesses b
        WHERE b.ID = :businessId
        LIMIT 1
    ", { businessId: request.BusinessID }, { datasource: "payfrit" });

    qAddr = queryExecute("
        SELECT a.Line1, a.City, a.ZIPCode, s.Abbreviation AS State
        FROM Addresses a
        LEFT JOIN tt_States s ON s.ID = a.StateID
        WHERE (a.BusinessID = :businessId OR a.ID = (SELECT AddressID FROM Businesses WHERE ID = :businessId))
          AND a.IsDeleted = 0
        LIMIT 1
    ", { businessId: request.BusinessID }, { datasource: "payfrit" });

    taxRateRaw = isNumeric(q.TaxRate) ? q.TaxRate : 0;
    taxRatePercent = taxRateRaw * 100;

    writeOutput(serializeJSON({
        "OK": true,
        "MESSAGE": "Settings updated",
        "SETTINGS": {
            "BusinessID": q.ID,
            "Name": q.Name,
            "TaxRate": taxRateRaw,
            "TaxRatePercent": taxRatePercent,
            "Address": qAddr.recordCount > 0 ? (qAddr.Line1 ?: "") : "",
            "City": qAddr.recordCount > 0 ? (qAddr.City ?: "") : "",
            "State": qAddr.recordCount > 0 ? (qAddr.State ?: "") : "",
            "Zip": qAddr.recordCount > 0 ? (qAddr.ZIPCode ?: "") : "",
            "Phone": q.Phone ?: "",
            "Email": ""
        }
    }));

} catch (any e) {
    apiAbort({ OK: false, ERROR: "server_error", MESSAGE: e.message });
}
</cfscript>
