#include "sqs_map.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void ok(int32_t status){if(status){fprintf(stderr,"%s\n",sqsm_map_last_error());assert(!status);}}
static char *text(sqsm_map_bytes_t out){char *s=malloc((size_t)out.len+1);assert(s);memcpy(s,out.data,(size_t)out.len);s[out.len]=0;return s;}
static sqsm_map_bytes_t call(sqsm_map_t map,const char *json){sqsm_map_bytes_t out={0};ok(sqsm_map_camera_json(map,(const uint8_t*)json,strlen(json),&out));return out;}
static double field(const char *json,const char *key){char needle[80];snprintf(needle,sizeof needle,"\"%s\":",key);const char *at=strstr(json,needle);assert(at);return strtod(at+strlen(needle),NULL);}
static double scale(sqsm_map_t map){sqsm_map_bytes_t out=call(map,"{\"method\":\"sqs.scaleAt\",\"args\":[{\"maxWidth\":80}]}");char *s=text(out);double value=field(s,"metersPerPixel");assert(value>0&&field(s,"width")>0&&field(s,"width")<=80);assert(strstr(s,"\"pixelUnit\":\"css\"")&&strstr(s,"\"unit\":\"m\""));assert(fabs(field(s,"distance")/value-field(s,"width"))<1e-8);free(s);ok(sqsm_map_bytes_free(out.allocation));return value;}
int main(void){
 assert(sqsm_map_runtime_flags()&SQSM_MAP_SCALE_TOOLS);sqsm_map_t map=0;ok(sqsm_map_create(256,192,&map));
 sqsm_map_bytes_t out=call(map,"{\"method\":\"jumpTo\",\"args\":[{\"center\":[0,60],\"zoom\":4,\"bearing\":0}]}");ok(sqsm_map_bytes_free(out.allocation));double base=scale(map);
 out=call(map,"{\"method\":\"zoomIn\",\"args\":[]}");ok(sqsm_map_bytes_free(out.allocation));assert(fabs(base/scale(map)-2)<1e-4);
 const char *bad="{\"method\":\"sqs.scaleAt\",\"args\":[{\"maxWidth\":0}]}";out=(sqsm_map_bytes_t){0};assert(sqsm_map_camera_json(map,(const uint8_t*)bad,strlen(bad),&out)==SQSM_MAP_INVALID_ARGUMENT);assert(!out.data&&!out.len&&!out.allocation);
 out=call(map,"{\"method\":\"sqs.scaleAt\",\"args\":[]}");uint64_t allocation=out.allocation;ok(sqsm_map_destroy(map));char *saved=text(out);assert(strstr(saved,"sphere-local"));free(saved);ok(sqsm_map_bytes_free(allocation));assert(sqsm_map_bytes_free(allocation)==SQSM_MAP_STALE_HANDLE);
 puts("scale C host: PASS (real GPU, zoom, validation, post-destroy output ownership)");return 0;
}
