#include "native_boundary.h"
#include <cassert>
#include <cstring>
#include <string>
int main() {
  char *ok = scctools_submit_json(" { \"duty\": 0.5, \"capacitors\": 2, \"phases\": 2, \"stages\": 2, \"architecture\": \"qfa-graph\", \"version\": 1 } ");
  assert(ok && std::strstr(ok,"\"type\":\"result\"") && std::strstr(ok,"\"A\"") && std::strstr(ok,"\"m\"")); for (const char *key : {"\"B\"", "\"r\"", "\"Ar\"", "\"ZSSL\"", "\"ZFSL\"", "\"ZESR\"", "\"ZSCC\"", "\"stress\"", "\"symbols\""}) assert(std::strstr(ok, key)); scctools_free(ok);
  for (int stages : {2, 3, 4, 5}) {
    const std::string request = "{\"version\":1,\"architecture\":\"qfa-graph\",\"topology\":\"h-dickson\",\"stages\":" + std::to_string(stages) + ",\"phases\":2,\"duty\":0.5}";
    char *expanded = scctools_submit_json(request.c_str());
    const std::string expected_stages = "\"stages\":" + std::to_string(stages);
    assert(expanded && std::strstr(expanded, "\"type\":\"result\"") &&
           std::strstr(expanded, "\"topology\":\"h-dickson\"") &&
           std::strstr(expanded, expected_stages.c_str()) && std::strstr(expanded, "\"Acaps\"") &&
           std::strstr(expanded, "\"Asw\"") && std::strstr(expanded, "\"Asw_act\"") &&
           std::strstr(expanded, "\"graph\"") && std::strstr(expanded, "\"cutset\""));
    if (stages == 5) assert(std::strstr(expanded, "\"outputs\":[2,3,4,5,6,7,8]"));
    scctools_free(expanded);
  }
  char *ssl = scctools_submit_json("{\"version\":1,\"operation\":\"optimize-sizing\",\"kind\":\"ssl\",\"stages\":2,\"phases\":2,\"duty\":0.5,\"mode\":-1,\"lower_bounds\":[0.1,0.1],\"upper_bounds\":[0.9,0.9]}");
  assert(ssl && std::strstr(ssl, "\"operation\":\"optimize-sizing\"") && std::strstr(ssl, "\"feasible\":true") && std::strstr(ssl, "\"allocations\"") && std::strstr(ssl, "\"equality_residuals\"") && std::strstr(ssl, "\"objective\"")); scctools_free(ssl);
  char *fsl = scctools_submit_json("{\"version\":1,\"operation\":\"optimize-sizing\",\"kind\":\"fsl\",\"stages\":2,\"phases\":2,\"duty\":0.5,\"mode\":-1}");
  assert(fsl && std::strstr(fsl, "\"kind\":\"fsl\"") && std::strstr(fsl, "\"feasible\":true")); scctools_free(fsl);
  char *infeasible = scctools_submit_json("{\"version\":1,\"operation\":\"optimize-sizing\",\"kind\":\"ssl\",\"stages\":2,\"phases\":2,\"duty\":0.5,\"lower_bounds\":[0.8,0.8]}");
  assert(infeasible && std::strstr(infeasible, "INFEASIBLE_SIZING") && std::strstr(infeasible, "bounds")); scctools_free(infeasible);
  char *bad = scctools_submit_json("{\"version\":1,\"architecture\":\"qfa-graph\",\"topology\":\"h-dickson\",\"stages\":2,\"phases\":3,\"duty\":0.5}");
  assert(bad && std::strstr(bad,"UNSUPPORTED_PHASE_COUNT")); scctools_free(bad);
  char *too_few = scctools_submit_json("{\"version\":1,\"architecture\":\"qfa-graph\",\"stages\":2,\"phases\":2,\"capacitors\":1,\"duty\":0.5}");
  assert(too_few && std::strstr(too_few,"INVALID_INPUT")); scctools_free(too_few);
  for (const char *invalid : {"{\"version\":1,\"architecture\":\"qfa-graph\",\"stages\":2,\"phases\":2,\"capacitors\":2}", " {\"version\":1,\"architecture\":\"qfa-graph\",\"stages\":2,\"phases\":2,\"capacitors\":2,\"duty\":0.5} trailing"}) {
    char *rejected = scctools_submit_json(invalid); assert(rejected && std::strstr(rejected,"INVALID_INPUT")); scctools_free(rejected);
  }
  char *singular = scctools_submit_json("{\"version\":1,\"operation\":\"solve-charge-vectors\",\"capacitors\":1,\"duty\":[0.5,0.5],\"cutsets\":[[[0,0,0]],[[0,0,0],[0,0,0]]]}" );
  assert(singular && std::strstr(singular, "SINGULAR_SYSTEM")); scctools_free(singular);
  char *duplicate = scctools_submit_json("{\"version\":1,\"version\":1,\"architecture\":\"qfa-graph\",\"stages\":2,\"phases\":2,\"capacitors\":2,\"duty\":0.5}");
  assert(duplicate && std::strstr(duplicate, "INVALID_INPUT")); scctools_free(duplicate);
  char *control = scctools_submit_json("{\"bad\nfield\":1}");
  assert(control && std::strstr(control, "INVALID_INPUT") && !std::strchr(control, '\n')); scctools_free(control);
  const std::string prefix="{\"version\":1,\"architecture\":\"qfa-graph\",\"stages\":2,\"phases\":2,\"capacitors\":2,\"duty\":0.5,\"substitutions\":";
  for (const char *values : {"{}", "null", "[]", "{\"duty\":[0,1],\"capacitances\":[1,2],\"switch_resistances\":[1,1,1,1],\"capacitor_esr\":[0,0],\"frequency\":[1]}"}) {
    char *result=scctools_submit_json((prefix+values+"}").c_str());
    assert(result && std::strstr(result,"INVALID_SUBSTITUTION"));scctools_free(result);
  }
  char *huge=scctools_submit_json("{\"version\":1e300}");assert(huge && std::strstr(huge,"INVALID_INPUT"));scctools_free(huge);
  return 0;
}
