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

<cftry>

<cfset requestData = deserializeJSON(toString(getHttpRequestData().content))>

<!--- ============================================================================
     SHARDING FORMAT: { "Beacons": [{ "UUID": "...", "Major": 49, "Minor": 15 }] }
     Resolves via BeaconShards -> Businesses (BeaconMajor) -> ServicePoints (BeaconMinor)
     ============================================================================ --->
<cfif structKeyExists(requestData, "Beacons") AND isArray(requestData.Beacons) AND arrayLen(requestData.Beacons) GT 0>
  <cfset beacons = []>

  <cfloop array="#requestData.Beacons#" index="beaconData">
    <cfset uuid = "">
    <cfset major = 0>
    <cfset minor = -1>

    <!--- Extract UUID (normalize: remove dashes, add back in standard format) --->
    <cfif structKeyExists(beaconData, "UUID")>
      <cfset rawUuid = uCase(reReplace(beaconData.UUID, "-", "", "all"))>
      <cfif len(rawUuid) EQ 32>
        <!--- Convert to standard UUID format with dashes for DB lookup --->
        <cfset uuid = lCase(mid(rawUuid,1,8) & "-" & mid(rawUuid,9,4) & "-" & mid(rawUuid,13,4) & "-" & mid(rawUuid,17,4) & "-" & mid(rawUuid,21,12))>
      </cfif>
    </cfif>

    <cfif structKeyExists(beaconData, "Major") AND isNumeric(beaconData.Major)>
      <cfset major = int(beaconData.Major)>
    </cfif>

    <cfif structKeyExists(beaconData, "Minor") AND isNumeric(beaconData.Minor)>
      <cfset minor = int(beaconData.Minor)>
    </cfif>

    <cfif len(uuid) EQ 0 OR major LT 0 OR minor LT 0>
      <cfcontinue>
    </cfif>

    <!--- Resolve via sharding: UUID -> Shard -> Business (Major) -> ServicePoint (Minor) --->
    <cfquery name="qShard" datasource="payfrit">
      SELECT
        biz.ID AS BusinessID,
        biz.Name AS BusinessName,
        biz.ParentBusinessID,
        COALESCE(parent.Name, '') AS ParentBusinessName,
        sp.ID AS ServicePointID,
        sp.Name AS ServicePointName,
        (SELECT COUNT(*) FROM Businesses WHERE ParentBusinessID = biz.ID) AS ChildCount
      FROM BeaconShards bs
      JOIN Businesses biz ON biz.BeaconShardID = bs.ID AND biz.BeaconMajor = <cfqueryparam cfsqltype="cf_sql_smallint" value="#major#">
      LEFT JOIN ServicePoints sp ON sp.BusinessID = biz.ID AND sp.BeaconMinor = <cfqueryparam cfsqltype="cf_sql_smallint" value="#minor#"> AND sp.IsActive = 1
      LEFT JOIN Businesses parent ON biz.ParentBusinessID = parent.ID
      WHERE bs.UUID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#uuid#">
        AND bs.IsActive = 1
        AND biz.IsDemo = 0
        AND biz.IsPrivate = 0
      LIMIT 1
    </cfquery>

    <cfif qShard.recordCount GT 0>
      <cfset arrayAppend(beacons, {
        "UUID" = uCase(reReplace(uuid, "-", "", "all")),
        "Major" = major,
        "Minor" = minor,
        "BeaconID" = 0,
        "BeaconName" = qShard.ServicePointName,
        "BusinessID" = qShard.BusinessID,
        "BusinessName" = qShard.BusinessName,
        "ServicePointID" = val(qShard.ServicePointID),
        "ServicePointName" = qShard.ServicePointName,
        "ParentBusinessID" = val(qShard.ParentBusinessID),
        "ParentBusinessName" = qShard.ParentBusinessName,
        "HasChildren" = qShard.ChildCount GT 0
      })>
    </cfif>
  </cfloop>

  <cfoutput>#serializeJSON({
    "OK" = true,
    "ERROR" = "",
    "BEACONS" = beacons
  })#</cfoutput>
  <cfabort>
</cfif>

<!--- ============================================================================
     LEGACY FORMAT: { "UUIDs": ["uuid1", "uuid2", ...] }
     Resolves via old Beacons table
     ============================================================================ --->
<cfif NOT structKeyExists(requestData, "UUIDs") OR NOT isArray(requestData.UUIDs) OR arrayLen(requestData.UUIDs) EQ 0>
  <cfoutput>#serializeJSON({
    "OK" = true,
    "ERROR" = "",
    "BEACONS" = []
  })#</cfoutput>
  <cfabort>
</cfif>

<!--- Clean and normalize UUIDs (remove dashes, uppercase) --->
<cfset cleanUUIDs = []>
<cfloop array="#requestData.UUIDs#" index="uuid">
  <cfset cleanUUID = uCase(reReplace(uuid, "-", "", "all"))>
  <cfif len(cleanUUID) EQ 32>
    <cfset arrayAppend(cleanUUIDs, cleanUUID)>
  </cfif>
</cfloop>

<cfif arrayLen(cleanUUIDs) EQ 0>
  <cfoutput>#serializeJSON({
    "OK" = true,
    "ERROR" = "",
    "BEACONS" = []
  })#</cfoutput>
  <cfabort>
</cfif>

<!--- Query for matching beacons with business info --->
<cfquery name="qBeacons" datasource="payfrit">
  SELECT
    b.ID AS BeaconID,
    b.Name AS BeaconName,
    b.UUID,
    COALESCE(sp.ID, 0) AS ServicePointID,
    COALESCE(sp.Name, '') AS ServicePointName,
    COALESCE(sp.BusinessID, lt.BusinessID, b.BusinessID) AS BusinessID,
    biz.Name AS BusinessName,
    biz.ParentBusinessID AS ParentBusinessID,
    COALESCE(parent.Name, '') AS ParentBusinessName,
    (SELECT COUNT(*) FROM Businesses WHERE ParentBusinessID = biz.ID) AS ChildCount
  FROM Beacons b
  LEFT JOIN ServicePoints sp ON sp.BeaconID = b.ID
  LEFT JOIN lt_BeaconsID_BusinessesID lt ON lt.BeaconID = b.ID
  INNER JOIN Businesses biz ON COALESCE(sp.BusinessID, lt.BusinessID, b.BusinessID) = biz.ID
  LEFT JOIN Businesses parent ON biz.ParentBusinessID = parent.ID
  WHERE b.UUID IN (<cfqueryparam value="#arrayToList(cleanUUIDs)#" cfsqltype="cf_sql_varchar" list="true">)
    AND b.IsActive = 1
    AND biz.IsDemo = 0
    AND biz.IsPrivate = 0
</cfquery>

<cfset beacons = []>
<cfloop query="qBeacons">
  <cfset arrayAppend(beacons, {
    "UUID" = qBeacons.UUID,
    "BeaconID" = qBeacons.BeaconID,
    "BeaconName" = qBeacons.BeaconName,
    "BusinessID" = qBeacons.BusinessID,
    "BusinessName" = qBeacons.BusinessName,
    "ServicePointID" = qBeacons.ServicePointID,
    "ServicePointName" = qBeacons.ServicePointName,
    "ParentBusinessID" = val(qBeacons.ParentBusinessID),
    "ParentBusinessName" = qBeacons.ParentBusinessName,
    "HasChildren" = qBeacons.ChildCount GT 0
  })>
</cfloop>

<cfoutput>#serializeJSON({
  "OK" = true,
  "ERROR" = "",
  "BEACONS" = beacons
})#</cfoutput>

<cfcatch type="any">
  <cfoutput>#serializeJSON({
    "OK" = false,
    "ERROR" = cfcatch.message
  })#</cfoutput>
</cfcatch>
</cftry>
