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

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

export interface JarvisClientOptions {
  token?: string;
  requestId?: string;
}

// ── Shared fetch helper ────────────────────────────────────────────────────

async function jarvisFetch<T>(
  path: string,
  init: RequestInit,
  opts: JarvisClientOptions
): Promise<T> {
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(opts.token ? { Authorization: `Bearer ${opts.token}` } : {}),
    ...(opts.requestId ? { 'x-request-id': opts.requestId } : {}),
  };
  const res = await fetch(`${config.JARVISJR_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(`jarvisjr-backend ${init.method ?? 'GET'} ${path} → ${res.status}: ${body}`);
  }
  return res.json() as Promise<T>;
}

// ── Agents ─────────────────────────────────────────────────────────────────

export interface JarvisAgentDoc {
  id: string;
  userId: string;
  productId: string;
  name: string;
  role: string;
  systemPrompt: string;
  voiceId?: string;
  coachingFramework?: string;
  accentColor?: string;
  welcomeMessage?: string;
  sessionLength?: number;
  difficultyLevel?: string;
  language?: string;
  privacyLevel?: string;
  checkInSchedule?: string;
  isTemplate?: boolean;
  templateSource?: string;
  totalSessions: number;
  lastSessionAt: string | null;
  createdAt: string;
  updatedAt: string;
}

export interface AgentCreateInput {
  name: string;
  role: string;
  systemPrompt: string;
  voiceId?: string;
  coachingFramework?: string;
  accentColor?: string;
  welcomeMessage?: string;
  sessionLength?: number;
  difficultyLevel?: 'beginner' | 'intermediate' | 'advanced';
  language?: string;
  privacyLevel?: 'standard' | 'strict';
}

export function jarvisAgentCreate(
  input: AgentCreateInput,
  opts: JarvisClientOptions
): Promise<JarvisAgentDoc> {
  return jarvisFetch('/jarvis/agents', { method: 'POST', body: JSON.stringify(input) }, opts);
}

export function jarvisAgentsList(
  params: { limit?: number; offset?: number },
  opts: JarvisClientOptions
): Promise<{ agents: JarvisAgentDoc[]; 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 jarvisFetch(`/jarvis/agents${q ? `?${q}` : ''}`, { method: 'GET' }, opts);
}

export function jarvisAgentDuplicate(
  agentId: string,
  opts: JarvisClientOptions
): Promise<JarvisAgentDoc> {
  return jarvisFetch(`/jarvis/agents/${agentId}/duplicate`, { method: 'POST' }, opts);
}

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

export interface JarvisSessionDoc {
  id: string;
  userId: string;
  productId: string;
  agentId: string;
  mode: string;
  status: 'active' | 'completed';
  summary?: string;
  coachingNotes?: string[];
  skillMetrics?: Record<string, number>;
  duration?: number;
  messageCount: number;
  createdAt: string;
  completedAt: string | null;
}

export interface JarvisSessionStats {
  totalSessions: number;
  totalDurationMinutes: number;
  currentStreak: number;
  longestStreak: number;
  perAgent: Record<string, { sessions: number; avgDuration: number }>;
}

export function jarvisSessionsList(
  params: { limit?: number; offset?: number; agentId?: string },
  opts: JarvisClientOptions
): Promise<{ sessions: JarvisSessionDoc[]; 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));
  if (params.agentId) qs.set('agentId', params.agentId);
  const q = qs.toString();
  return jarvisFetch(`/jarvis/sessions${q ? `?${q}` : ''}`, { method: 'GET' }, opts);
}

export function jarvisSessionsGetStats(opts: JarvisClientOptions): Promise<JarvisSessionStats> {
  return jarvisFetch('/jarvis/sessions/stats', { method: 'GET' }, opts);
}

// ── Memory ─────────────────────────────────────────────────────────────────

export interface JarvisMemoryDoc {
  id: string;
  agentId: string;
  userId: string;
  productId: string;
  sessionId?: string;
  type: 'skill_note' | 'preference' | 'goal' | 'context' | 'exercise';
  content: string;
  importance: number;
  tags?: string[];
  createdAt: string;
  expiresAt?: string;
}

export function jarvisMemoryList(
  agentId: string,
  params: {
    type?: string;
    minImportance?: number;
    limit?: number;
    offset?: number;
  },
  opts: JarvisClientOptions
): Promise<{ memories: JarvisMemoryDoc[]; total: number }> {
  const qs = new URLSearchParams();
  if (params.type) qs.set('type', params.type);
  if (params.minImportance !== undefined) qs.set('minImportance', String(params.minImportance));
  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 jarvisFetch(
    `/jarvis/agents/${agentId}/memory${q ? `?${q}` : ''}`,
    { method: 'GET' },
    opts
  );
}

// ── Marketplace admin ─────────────────────────────────────────────────────

export function jarvisMarketplaceListPending(
  opts: JarvisClientOptions
): Promise<{ listings: unknown[]; total: number }> {
  return jarvisFetch('/marketplace/admin/pending', { method: 'GET' }, opts);
}

export function jarvisMarketplaceCertify(
  listingId: string,
  decision: { decision: 'approved' | 'rejected'; notes?: string },
  opts: JarvisClientOptions
): Promise<unknown> {
  const action = decision.decision === 'approved' ? 'approve' : 'reject';
  return jarvisFetch(
    `/marketplace/admin/${listingId}/${action}`,
    { method: 'POST', body: JSON.stringify(decision) },
    opts
  );
}

export function jarvisMarketplaceGetListing(
  listingId: string,
  opts: JarvisClientOptions
): Promise<Record<string, unknown>> {
  return jarvisFetch(`/marketplace/listings/${listingId}`, { method: 'GET' }, opts);
}

export function jarvisMarketplaceSuspend(
  listingId: string,
  reason: string,
  opts: JarvisClientOptions
): Promise<unknown> {
  return jarvisFetch(
    `/marketplace/admin/${listingId}/suspend`,
    { method: 'POST', body: JSON.stringify({ reason }) },
    opts
  );
}

export function jarvisMarketplaceFeature(
  listingId: string,
  featured: boolean,
  opts: JarvisClientOptions
): Promise<unknown> {
  return jarvisFetch(
    `/marketplace/admin/${listingId}/feature`,
    { method: 'POST', body: JSON.stringify({ featured }) },
    opts
  );
}

export function jarvisMemoryPrune(
  agentId: string,
  opts: JarvisClientOptions
): Promise<{ pruned: number }> {
  return jarvisFetch(`/jarvis/agents/${agentId}/memory/prune`, { method: 'POST' }, opts);
}

export function jarvisMemoryGetContext(
  agentId: string,
  limit: number | undefined,
  opts: JarvisClientOptions
): Promise<{ memories: JarvisMemoryDoc[]; count: number }> {
  const qs = limit !== undefined ? `?limit=${limit}` : '';
  return jarvisFetch(`/jarvis/agents/${agentId}/memory/context${qs}`, { method: 'GET' }, opts);
}

export function jarvisMemoryCreate(
  agentId: string,
  input: {
    sessionId: string;
    type: 'skill_note' | 'preference' | 'goal' | 'context' | 'exercise';
    content: string;
    importance?: number;
    tags?: string[];
    expiresAt?: string | null;
  },
  opts: JarvisClientOptions
): Promise<JarvisMemoryDoc> {
  return jarvisFetch(
    `/jarvis/agents/${agentId}/memory`,
    { method: 'POST', body: JSON.stringify({ ...input, agentId }) },
    opts
  );
}

// ── Teams ─────────────────────────────────────────────────────────────────

export interface JarvisTeamMemberDoc {
  userId: string;
  teamId: string;
  role: 'owner' | 'manager' | 'member';
  status: 'active' | 'invited' | 'removed';
  joinedAt: string;
  invitedBy?: string;
}

export function jarvisTeamsListMembers(
  teamId: string,
  opts: JarvisClientOptions
): Promise<{ members: JarvisTeamMemberDoc[]; total: number }> {
  return jarvisFetch(`/jarvis/teams/${teamId}/members`, { method: 'GET' }, opts);
}
