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

<cfscript>
function apiAbort(payload) {
  writeOutput(serializeJSON(payload));
  abort;
}

// Localhost-only protection
remoteAddr = cgi.REMOTE_ADDR;
if (remoteAddr != "127.0.0.1" && remoteAddr != "::1" && remoteAddr != "0:0:0:0:0:0:0:1" && remoteAddr != "10.10.0.2") {
  apiAbort({ "OK": false, "ERROR": "forbidden" });
}

try {
  // Parse parameters
  view = structKeyExists(url, "view") ? lcase(url.view) : "count";
  hours = structKeyExists(url, "hours") ? val(url.hours) : 24;
  if (hours <= 0 || hours > 720) hours = 24;
  limitRows = structKeyExists(url, "limit") ? val(url.limit) : 20;
  if (limitRows <= 0 || limitRows > 100) limitRows = 20;

  // Flush any buffered metrics first
  flushPerfBuffer();

  response = { "OK": true, "VIEW": view, "HOURS": hours };

  if (view == "count") {
    // Top endpoints by call count
    q = queryExecute("
      SELECT
        Endpoint,
        COUNT(*) as Calls,
        ROUND(AVG(TotalMs)) as AvgMs,
        ROUND(AVG(DbMs)) as AvgDbMs,
        ROUND(AVG(AppMs)) as AvgAppMs,
        MAX(TotalMs) as MaxMs,
        ROUND(AVG(QueryCount), 1) as AvgQueries,
        ROUND(AVG(ResponseBytes)) as AvgBytes
      FROM ApiPerfLogs
      WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
      GROUP BY Endpoint
      ORDER BY Calls DESC
      LIMIT :lim
    ", {
      hours: { value: hours, cfsqltype: "cf_sql_integer" },
      lim: { value: limitRows, cfsqltype: "cf_sql_integer" }
    }, { datasource: "payfrit" });

    rows = [];
    for (row in q) {
      arrayAppend(rows, {
        "Endpoint": row.Endpoint,
        "Calls": row.Calls,
        "AvgMs": row.AvgMs,
        "AvgDbMs": row.AvgDbMs,
        "AvgAppMs": row.AvgAppMs,
        "MaxMs": row.MaxMs,
        "AvgQueries": row.AvgQueries,
        "AvgBytes": row.AvgBytes
      });
    }
    response["DATA"] = rows;

  } else if (view == "latency") {
    // Top endpoints by average latency
    q = queryExecute("
      SELECT
        Endpoint,
        COUNT(*) as Calls,
        ROUND(AVG(TotalMs)) as AvgMs,
        ROUND(AVG(DbMs)) as AvgDbMs,
        ROUND(AVG(AppMs)) as AvgAppMs,
        MAX(TotalMs) as MaxMs,
        ROUND(AVG(QueryCount), 1) as AvgQueries
      FROM ApiPerfLogs
      WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
      GROUP BY Endpoint
      HAVING Calls >= 3
      ORDER BY AvgMs DESC
      LIMIT :lim
    ", {
      hours: { value: hours, cfsqltype: "cf_sql_integer" },
      lim: { value: limitRows, cfsqltype: "cf_sql_integer" }
    }, { datasource: "payfrit" });

    rows = [];
    for (row in q) {
      arrayAppend(rows, {
        "Endpoint": row.Endpoint,
        "Calls": row.Calls,
        "AvgMs": row.AvgMs,
        "AvgDbMs": row.AvgDbMs,
        "AvgAppMs": row.AvgAppMs,
        "MaxMs": row.MaxMs,
        "AvgQueries": row.AvgQueries
      });
    }
    response["DATA"] = rows;

  } else if (view == "slow") {
    // Slowest individual requests
    q = queryExecute("
      SELECT Endpoint, TotalMs, DbMs, AppMs, QueryCount, ResponseBytes,
             BusinessID, UserID, LoggedAt
      FROM ApiPerfLogs
      WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
      ORDER BY TotalMs DESC
      LIMIT :lim
    ", {
      hours: { value: hours, cfsqltype: "cf_sql_integer" },
      lim: { value: limitRows, cfsqltype: "cf_sql_integer" }
    }, { datasource: "payfrit" });

    rows = [];
    for (row in q) {
      arrayAppend(rows, {
        "Endpoint": row.Endpoint,
        "TotalMs": row.TotalMs,
        "DbMs": row.DbMs,
        "AppMs": row.AppMs,
        "QueryCount": row.QueryCount,
        "ResponseBytes": row.ResponseBytes,
        "BusinessID": row.BusinessID,
        "UserID": row.UserID,
        "LoggedAt": dateTimeFormat(row.LoggedAt, "yyyy-mm-dd HH:nn:ss")
      });
    }
    response["DATA"] = rows;

  } else if (view == "summary") {
    // Overall summary stats
    q = queryExecute("
      SELECT
        COUNT(*) as TotalRequests,
        COUNT(DISTINCT Endpoint) as UniqueEndpoints,
        ROUND(AVG(TotalMs)) as OverallAvgMs,
        MAX(TotalMs) as OverallMaxMs,
        ROUND(AVG(DbMs)) as OverallAvgDbMs,
        ROUND(AVG(AppMs)) as OverallAvgAppMs,
        ROUND(AVG(QueryCount), 1) as OverallAvgQueries,
        MIN(LoggedAt) as FirstLog,
        MAX(LoggedAt) as LastLog
      FROM ApiPerfLogs
      WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
    ", {
      hours: { value: hours, cfsqltype: "cf_sql_integer" }
    }, { datasource: "payfrit" });

    response["DATA"] = {
      "TotalRequests": q.TotalRequests,
      "UniqueEndpoints": q.UniqueEndpoints,
      "OverallAvgMs": q.OverallAvgMs,
      "OverallMaxMs": q.OverallMaxMs,
      "OverallAvgDbMs": q.OverallAvgDbMs,
      "OverallAvgAppMs": q.OverallAvgAppMs,
      "OverallAvgQueries": q.OverallAvgQueries,
      "FirstLog": isDate(q.FirstLog) ? dateTimeFormat(q.FirstLog, "yyyy-mm-dd HH:nn:ss") : "",
      "LastLog": isDate(q.LastLog) ? dateTimeFormat(q.LastLog, "yyyy-mm-dd HH:nn:ss") : ""
    };

  } else {
    apiAbort({ "OK": false, "ERROR": "invalid_view", "MESSAGE": "Use ?view=count|latency|slow|summary" });
  }

  apiAbort(response);

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