// Code generated by protoc-gen-ts-client. DO NOT EDIT.
// source: worldmonitor/displacement/v1/service.proto

export interface GetDisplacementSummaryRequest {
  year: number;
  countryLimit: number;
  flowLimit: number;
}

export interface GetDisplacementSummaryResponse {
  summary?: DisplacementSummary;
  fetchedAt: number;
  dataAvailable: boolean;
}

export interface DisplacementSummary {
  year: number;
  globalTotals?: GlobalDisplacementTotals;
  countries: CountryDisplacement[];
  topFlows: DisplacementFlow[];
}

export interface GlobalDisplacementTotals {
  refugees: number;
  asylumSeekers: number;
  idps: number;
  stateless: number;
  total: number;
}

export interface CountryDisplacement {
  code: string;
  name: string;
  refugees: number;
  asylumSeekers: number;
  idps: number;
  stateless: number;
  totalDisplaced: number;
  hostRefugees: number;
  hostAsylumSeekers: number;
  hostTotal: number;
  location?: GeoCoordinates;
}

export interface GeoCoordinates {
  latitude: number;
  longitude: number;
}

export interface DisplacementFlow {
  originCode: string;
  originName: string;
  asylumCode: string;
  asylumName: string;
  refugees: number;
  originLocation?: GeoCoordinates;
  asylumLocation?: GeoCoordinates;
}

export interface GetPopulationExposureRequest {
  mode: string;
  lat: number;
  lon: number;
  radius: number;
}

export interface GetPopulationExposureResponse {
  success: boolean;
  countries: CountryPopulationEntry[];
  exposure?: ExposureResult;
}

export interface CountryPopulationEntry {
  code: string;
  name: string;
  population: number;
  densityPerKm2: number;
}

export interface ExposureResult {
  exposedPopulation: number;
  exposureRadiusKm: number;
  nearestCountry: string;
  densityPerKm2: number;
}

export interface FieldViolation {
  field: string;
  description: string;
}

export class ValidationError extends Error {
  violations: FieldViolation[];

  constructor(violations: FieldViolation[]) {
    super("Validation failed");
    this.name = "ValidationError";
    this.violations = violations;
  }
}

export class ApiError extends Error {
  statusCode: number;
  body: string;

  constructor(statusCode: number, message: string, body: string) {
    super(message);
    this.name = "ApiError";
    this.statusCode = statusCode;
    this.body = body;
  }
}

export interface DisplacementServiceClientOptions {
  fetch?: typeof fetch;
  defaultHeaders?: Record<string, string>;
}

export interface DisplacementServiceCallOptions {
  headers?: Record<string, string>;
  signal?: AbortSignal;
}

export class DisplacementServiceClient {
  private baseURL: string;
  private fetchFn: typeof fetch;
  private defaultHeaders: Record<string, string>;

  constructor(baseURL: string, options?: DisplacementServiceClientOptions) {
    this.baseURL = baseURL.replace(/\/+$/, "");
    this.fetchFn = options?.fetch ?? globalThis.fetch;
    this.defaultHeaders = { ...options?.defaultHeaders };
  }

  async getDisplacementSummary(req: GetDisplacementSummaryRequest, options?: DisplacementServiceCallOptions): Promise<GetDisplacementSummaryResponse> {
    let path = "/api/displacement/v1/get-displacement-summary";
    const params = new URLSearchParams();
    if (req.year != null && req.year !== 0) params.set("year", String(req.year));
    if (req.countryLimit != null && req.countryLimit !== 0) params.set("country_limit", String(req.countryLimit));
    if (req.flowLimit != null && req.flowLimit !== 0) params.set("flow_limit", String(req.flowLimit));
    const url = this.baseURL + path + (params.toString() ? "?" + params.toString() : "");

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as GetDisplacementSummaryResponse;
  }

  async getPopulationExposure(req: GetPopulationExposureRequest, options?: DisplacementServiceCallOptions): Promise<GetPopulationExposureResponse> {
    let path = "/api/displacement/v1/get-population-exposure";
    const params = new URLSearchParams();
    if (req.mode != null && req.mode !== "") params.set("mode", String(req.mode));
    if (req.lat != null && req.lat !== 0) params.set("lat", String(req.lat));
    if (req.lon != null && req.lon !== 0) params.set("lon", String(req.lon));
    if (req.radius != null && req.radius !== 0) params.set("radius", String(req.radius));
    const url = this.baseURL + path + (params.toString() ? "?" + params.toString() : "");

    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...this.defaultHeaders,
      ...options?.headers,
    };

    const resp = await this.fetchFn(url, {
      method: "GET",
      headers,
      signal: options?.signal,
    });

    if (!resp.ok) {
      return this.handleError(resp);
    }

    return await resp.json() as GetPopulationExposureResponse;
  }

  private async handleError(resp: Response): Promise<never> {
    const body = await resp.text();
    if (resp.status === 400) {
      try {
        const parsed = JSON.parse(body);
        if (parsed.violations) {
          throw new ValidationError(parsed.violations);
        }
      } catch (e) {
        if (e instanceof ValidationError) throw e;
      }
    }
    throw new ApiError(resp.status, `Request failed with status ${resp.status}`, body);
  }
}

