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

<cffunction name="apiAbort" access="public" returntype="void" output="true">
  <cfargument name="payload" type="struct" required="true">
  <cfcontent type="application/json; charset=utf-8">
  <cfoutput>#serializeJSON(arguments.payload)#</cfoutput>
  <cfabort>
</cffunction>

<cffunction name="readJsonBody" access="public" returntype="struct" output="false">
  <cfset var raw = getHttpRequestData().content>
  <cfif isNull(raw) OR len(trim(raw)) EQ 0>
    <cfreturn {}>
  </cfif>
  <cftry>
    <cfset var data = deserializeJSON(raw)>
    <cfif isStruct(data)>
      <cfreturn data>
    <cfelse>
      <cfreturn {}>
    </cfif>
    <cfcatch>
      <cfreturn {}>
    </cfcatch>
  </cftry>
</cffunction>

<cfset data = readJsonBody()>
<cfset TaskID = val( structKeyExists(data,"TaskID") ? data.TaskID : 0 )>
<!--- Get UserID from request (auth header) or from JSON body as fallback --->
<cfset UserID = val( structKeyExists(request,"UserID") ? request.UserID : (structKeyExists(data,"UserID") ? data.UserID : 0) )>

<cfif TaskID LTE 0>
  <cfset apiAbort({ "OK": false, "ERROR": "missing_params", "MESSAGE": "TaskID is required." })>
</cfif>

<cftry>
  <!--- Verify task exists --->
  <cfset qTask = queryExecute("
    SELECT TaskID, TaskClaimedByUserID, TaskCompletedOn, TaskOrderID, TaskTypeID
    FROM Tasks
    WHERE TaskID = ?
  ", [ { value = TaskID, cfsqltype = "cf_sql_integer" } ], { datasource = "payfrit" })>

  <cfif qTask.recordCount EQ 0>
    <cfset apiAbort({ "OK": false, "ERROR": "not_found", "MESSAGE": "Task not found." })>
  </cfif>

  <!--- Chat tasks (TaskTypeID = 2) can be closed without being claimed first --->
  <cfset isChatTask = (qTask.TaskTypeID EQ 2)>

  <cfif (NOT isChatTask) AND (qTask.TaskClaimedByUserID EQ 0)>
    <cfset apiAbort({ "OK": false, "ERROR": "not_claimed", "MESSAGE": "Task has not been claimed yet." })>
  </cfif>

  <cfif (NOT isChatTask) AND (UserID GT 0) AND (qTask.TaskClaimedByUserID NEQ UserID)>
    <cfset apiAbort({ "OK": false, "ERROR": "not_yours", "MESSAGE": "This task was claimed by someone else." })>
  </cfif>

  <!--- Check if already completed - use len() to handle both NULL and empty string --->
  <cfif len(trim(qTask.TaskCompletedOn)) GT 0>
    <cfset apiAbort({ "OK": false, "ERROR": "already_completed", "MESSAGE": "Task has already been completed." })>
  </cfif>

  <!--- Mark task as completed --->
  <cfset queryExecute("
    UPDATE Tasks
    SET TaskCompletedOn = NOW()
    WHERE TaskID = ?
  ", [ { value = TaskID, cfsqltype = "cf_sql_integer" } ], { datasource = "payfrit" })>

  <!--- If task has an associated order, mark it as Completed (status 4) --->
  <cfset orderUpdated = false>
  <cfif qTask.TaskOrderID GT 0>
    <cfset queryExecute("
      UPDATE Orders
      SET OrderStatusID = 4,
          OrderLastEditedOn = NOW()
      WHERE OrderID = ?
    ", [ { value = qTask.TaskOrderID, cfsqltype = "cf_sql_integer" } ], { datasource = "payfrit" })>
    <cfset orderUpdated = true>
  </cfif>

  <cfset apiAbort({
    "OK": true,
    "ERROR": "",
    "MESSAGE": "Task completed successfully.",
    "TaskID": TaskID,
    "OrderUpdated": orderUpdated
  })>

  <cfcatch>
    <cfset apiAbort({
      "OK": false,
      "ERROR": "server_error",
      "MESSAGE": "Error completing task",
      "DETAIL": cfcatch.message
    })>
  </cfcatch>
</cftry>
