// SDK
#include "cJSON.h"
#include "esp_app_format.h"
#include "esp_chip_info.h"
#include "esp_http_server.h"
#include "esp_ota_ops.h"
#include "esp_system.h"
#include "esp_timer.h"

// Project
#include "appstate.hpp"
#include "types.hpp"

internal esp_err_t api_system_info_handler(httpd_req_t *req)
{
  httpd_resp_set_type(req, "application/json");
  httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

  cJSON *root = cJSON_CreateObject();

  esp_chip_info_t chip_info;
  esp_chip_info(&chip_info);

  const char *model = "ESP32-S3";
  if (chip_info.model == CHIP_ESP32)
  {
    model = "ESP32";
  }
  else if (chip_info.model == CHIP_ESP32S2)
  {
    model = "ESP32-S2";
  }
  else if (chip_info.model == CHIP_ESP32S3)
  {
    model = "ESP32-S3";
  }
  else if (chip_info.model == CHIP_ESP32C3)
  {
    model = "ESP32-C3";
  }

  cJSON_AddStringToObject(root, "chip", model);

  uint32_t free_heap = esp_get_free_heap_size();
  cJSON_AddNumberToObject(root, "free_heap", free_heap);

  uint64_t uptime_sec = esp_timer_get_time() / 1000000;
  cJSON_AddNumberToObject(root, "uptime", uptime_sec);

  const esp_app_desc_t *app_desc = esp_app_get_description();
  cJSON_AddStringToObject(root, "firmware", app_desc->version);

  const char *conn_type = "offline";
  if (g_Ethernet_Initialized)
  {
    conn_type = "ethernet";
  }
  else if (g_Wifi_Initialized)
  {
    conn_type = "wifi";
  }
  cJSON_AddStringToObject(root, "connection", conn_type);

  const char *sys_info = cJSON_Print(root);
  httpd_resp_sendstr(req, sys_info);

  free((void *)sys_info);
  cJSON_Delete(root);

  return ESP_OK;
}

internal const httpd_uri_t api_system_info_uri = {.uri = "/api/system/info",
                                                  .method = HTTP_GET,
                                                  .handler =
                                                      api_system_info_handler,
                                                  .user_ctx = NULL};
