/**
 * PeakPulse backend client — typed HTTP wrappers for the peakpulse-backend (port 4010).
 *
 * Auth: Bearer token from the caller's JWT (same JWT_SECRET as platform-service).
 */

import { config } from './config.js';

export interface PeakPulseClientOptions {
  token?: string;
  requestId?: string;
  productId?: string;
}

async function peakpulseFetch<T>(
  path: string,
  init: RequestInit,
  opts: PeakPulseClientOptions
): Promise<T> {
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(opts.token ? { Authorization: `Bearer ${opts.token}` } : {}),
    ...(opts.requestId ? { 'x-request-id': opts.requestId } : {}),
    ...(opts.productId ? { 'x-product-id': opts.productId } : { 'x-product-id': 'peakpulse' }),
  };
  const res = await fetch(`${config.PEAKPULSE_BACKEND_URL}/api${path}`, {
    ...init,
    headers: { ...((init.headers as Record<string, string>) ?? {}), ...headers },
    signal: AbortSignal.timeout(15_000),
  });
  if (!res.ok) {
    const body = await res.text().catch(() => '');
    throw new Error(`peakpulse-backend ${init.method ?? 'GET'} ${path} → ${res.status}: ${body}`);
  }
  return res.json() as Promise<T>;
}

// ── Sessions ───────────────────────────────────────────────────────────────

export interface PeakSessionDoc {
  id: string;
  clientId?: string;
  userId: string;
  productId: string;
  activityType: 'hiking' | 'skiing' | 'cycling' | 'running';
  status: 'active' | 'completed' | 'paused';
  startTime: string;
  endTime?: string;
  durationSeconds?: number;
  distanceMeters?: number;
  maxSpeedMps?: number;
  averageSpeedMps?: number;
  elevationGainMeters?: number;
  elevationLossMeters?: number;
  maxElevationMeters?: number;
  locationName?: string;
  startLatitude?: number;
  startLongitude?: number;
  unitPreference?: string;
  weather?: {
    tempCelsius?: number;
    conditionCode?: string;
    windSpeedKph?: number;
    uvIndex?: number;
  };
  skiMetrics?: {
    runCount?: number;
    verticalDescentMeters?: number;
    liftTimeSeconds?: number;
    skiTimeSeconds?: number;
  };
  trackPointCount?: number;
  hapticMilestoneCount?: number;
  savedToHealthKit?: boolean;
  notes?: string;
  createdAt: string;
  updatedAt: string;
}

export interface PeakSessionExport {
  exportVersion: string;
  productId: string;
  session: Omit<
    PeakSessionDoc,
    'userId' | 'clientId' | 'savedToHealthKit' | 'createdAt' | 'updatedAt'
  >;
  exportedAt: string;
}

export function peakpulseSessionsList(
  params: {
    activityType?: string;
    status?: string;
    limit?: number;
    offset?: number;
  },
  opts: PeakPulseClientOptions
): Promise<{ items: PeakSessionDoc[]; total: number }> {
  const qs = new URLSearchParams();
  if (params.activityType) qs.set('activityType', params.activityType);
  if (params.status) qs.set('status', params.status);
  if (params.limit !== undefined) qs.set('limit', String(params.limit));
  if (params.offset !== undefined) qs.set('offset', String(params.offset));
  const q = qs.toString();
  return peakpulseFetch(`/peak/sessions${q ? `?${q}` : ''}`, { method: 'GET' }, opts);
}

export function peakpulseSessionGet(
  sessionId: string,
  opts: PeakPulseClientOptions
): Promise<PeakSessionDoc> {
  return peakpulseFetch(`/peak/sessions/${sessionId}`, { method: 'GET' }, opts);
}

export function peakpulseSessionExport(
  sessionId: string,
  opts: PeakPulseClientOptions
): Promise<PeakSessionExport> {
  return peakpulseFetch(`/peak/sessions/${sessionId}/export`, { method: 'GET' }, opts);
}

export function peakpulseGetStats(opts: PeakPulseClientOptions): Promise<Record<string, unknown>> {
  return peakpulseFetch('/peak/stats', { method: 'GET' }, opts);
}

// ── Routes ─────────────────────────────────────────────────────────────────

export interface PeakRouteDoc {
  id: string;
  sessionId: string;
  userId: string;
  productId: string;
  trackPoints: unknown[];
  hapticEvents: unknown[];
  trackPointCount: number;
  hapticEventCount: number;
  boundingBox?: {
    minLat: number;
    maxLat: number;
    minLon: number;
    maxLon: number;
  };
  createdAt: string;
  updatedAt: string;
}

export function peakpulseRoutesList(
  params: { limit?: number; offset?: number },
  opts: PeakPulseClientOptions
): Promise<{ items: PeakRouteDoc[]; total: number }> {
  const qs = new URLSearchParams();
  if (params.limit !== undefined) qs.set('limit', String(params.limit));
  if (params.offset !== undefined) qs.set('offset', String(params.offset));
  const q = qs.toString();
  return peakpulseFetch(`/peak/routes${q ? `?${q}` : ''}`, { method: 'GET' }, opts);
}

export function peakpulseRouteGet(
  sessionId: string,
  opts: PeakPulseClientOptions
): Promise<PeakRouteDoc> {
  return peakpulseFetch(`/peak/routes/${sessionId}`, { method: 'GET' }, opts);
}

export function peakpulseSyncStatus(opts: PeakPulseClientOptions): Promise<{
  userId: string;
  productId: string;
  pendingUploadCount: number;
  lastSyncedAt: string | null;
  oldestPendingAt: string | null;
}> {
  return peakpulseFetch('/peak/sync/status', { method: 'GET' }, opts);
}
