<cfsetting showdebugoutput="false">
<cfcontent type="application/json; charset=utf-8">
<cfscript>
/**
 * Create an admin rating for a worker on a completed task
 *
 * POST: {
 *   TaskID: 123,
 *   AdminUserID: 456,
 *   onTime: true/false,
 *   completedScope: true/false,
 *   requiredFollowup: true/false,
 *   continueAllow: true/false
 * }
 */

function readJsonBody() {
    var raw = getHttpRequestData().content;
    if (isNull(raw) || len(trim(raw)) == 0) return {};
    try {
        var data = deserializeJSON(raw);
        return isStruct(data) ? data : {};
    } catch (any e) {
        return {};
    }
}

function generateToken() {
    return lcase(replace(createUUID(), "-", "", "all"));
}

try {
    data = readJsonBody();
    taskID = val(structKeyExists(data, "TaskID") ? data.TaskID : 0);
    adminUserID = val(structKeyExists(data, "AdminUserID") ? data.AdminUserID : 0);

    if (taskID == 0) {
        writeOutput(serializeJSON({ "OK": false, "ERROR": "missing_task", "MESSAGE": "TaskID is required." }));
        abort;
    }

    if (adminUserID == 0) {
        writeOutput(serializeJSON({ "OK": false, "ERROR": "missing_admin", "MESSAGE": "AdminUserID is required." }));
        abort;
    }

    // Verify task exists and is completed
    qTask = queryTimed("
        SELECT t.ID, t.ClaimedByUserID, t.CompletedOn, t.BusinessID
        FROM Tasks t
        WHERE t.ID = :taskID
    ", { taskID: taskID });

    if (qTask.recordCount == 0) {
        writeOutput(serializeJSON({ "OK": false, "ERROR": "not_found", "MESSAGE": "Task not found." }));
        abort;
    }

    if (len(trim(qTask.CompletedOn)) == 0) {
        writeOutput(serializeJSON({ "OK": false, "ERROR": "not_completed", "MESSAGE": "Task has not been completed yet." }));
        abort;
    }

    workerUserID = qTask.ClaimedByUserID;
    if (workerUserID == 0) {
        writeOutput(serializeJSON({ "OK": false, "ERROR": "no_worker", "MESSAGE": "No worker assigned to this task." }));
        abort;
    }

    // Check if admin rating already exists for this task
    qExisting = queryTimed("
        SELECT ID FROM TaskRatings
        WHERE TaskID = :taskID
          AND Direction = 'admin_rates_worker'
        LIMIT 1
    ", { taskID: taskID });

    if (qExisting.recordCount > 0) {
        writeOutput(serializeJSON({ "OK": false, "ERROR": "already_rated", "MESSAGE": "This task has already been rated by an admin." }));
        abort;
    }

    // Insert the admin rating (completed immediately since admin submits directly)
    token = generateToken();
    queryTimed("
        INSERT INTO TaskRatings (
            TaskID, ByUserID, ForUserID, Direction,
            OnTime, CompletedScope, RequiredFollowup, ContinueAllow,
            AccessToken, ExpiresOn, CompletedOn
        ) VALUES (
            :taskID, :adminUserID, :workerUserID, 'admin_rates_worker',
            :onTime, :completedScope, :requiredFollowup, :continueAllow,
            :token, DATE_ADD(NOW(), INTERVAL 24 HOUR), NOW()
        )
    ", {
        taskID: taskID,
        adminUserID: adminUserID,
        workerUserID: workerUserID,
        onTime: { value: structKeyExists(data,"onTime") ? (data.onTime ? 1 : 0) : javaCast("null",""), cfsqltype: "cf_sql_tinyint", null: !structKeyExists(data,"onTime") },
        completedScope: { value: structKeyExists(data,"completedScope") ? (data.completedScope ? 1 : 0) : javaCast("null",""), cfsqltype: "cf_sql_tinyint", null: !structKeyExists(data,"completedScope") },
        requiredFollowup: { value: structKeyExists(data,"requiredFollowup") ? (data.requiredFollowup ? 1 : 0) : javaCast("null",""), cfsqltype: "cf_sql_tinyint", null: !structKeyExists(data,"requiredFollowup") },
        continueAllow: { value: structKeyExists(data,"continueAllow") ? (data.continueAllow ? 1 : 0) : javaCast("null",""), cfsqltype: "cf_sql_tinyint", null: !structKeyExists(data,"continueAllow") },
        token: token
    });

    ratingID = queryTimed("SELECT LAST_INSERT_ID() AS id", {}).id;

    writeOutput(serializeJSON({
        "OK": true,
        "MESSAGE": "Rating submitted successfully.",
        "RatingID": ratingID
    }));

} catch (any e) {
    writeOutput(serializeJSON({
        "OK": false,
        "ERROR": "server_error",
        "MESSAGE": "Error creating rating",
        "DETAIL": e.message
    }));
}
</cfscript>
