/**
 * Minimal gateway REST API client for the TUI and CLI commands.
 */

export interface ModelInfo {
  id: string;
  provider: string;
  name: string;
}

export interface ProviderInfo {
  id: string;
  name: string;
  available: boolean;
  models: ModelInfo[];
}

export interface SessionInfo {
  id: string;
  provider: string;
  modelId: string;
  createdAt: string;
  promptCount: number;
  channels: string[];
  durationMs: number;
}

export interface SessionListResult {
  sessions: SessionInfo[];
  total: number;
}

// ── Agent Config types ──

export interface AgentConfigInfo {
  id: string;
  name: string;
  provider: string;
  model: string;
  status: string;
  projectId: string | null;
  ownerId: string | null;
  systemPrompt: string | null;
  allowedTools: string[] | null;
  skills: string[] | null;
  isSystem: boolean;
  config: Record<string, unknown> | null;
  createdAt: string;
  updatedAt: string;
}

// ── Project types ──

export interface ProjectInfo {
  id: string;
  name: string;
  description: string | null;
  status: string;
  ownerId: string | null;
  createdAt: string;
  updatedAt: string;
}

// ── Mission types ──

export interface MissionInfo {
  id: string;
  name: string;
  description: string | null;
  status: string;
  projectId: string | null;
  userId: string | null;
  phase: string | null;
  milestones: Record<string, unknown>[] | null;
  config: Record<string, unknown> | null;
  createdAt: string;
  updatedAt: string;
}

// ── Mission Task types ──

export interface MissionTaskInfo {
  id: string;
  missionId: string;
  taskId: string | null;
  userId: string;
  status: string;
  description: string | null;
  notes: string | null;
  pr: string | null;
  createdAt: string;
  updatedAt: string;
}

// ── Helpers ──

function headers(sessionCookie: string, gatewayUrl: string) {
  return { Cookie: sessionCookie, Origin: gatewayUrl };
}

function jsonHeaders(sessionCookie: string, gatewayUrl: string) {
  return { ...headers(sessionCookie, gatewayUrl), 'Content-Type': 'application/json' };
}

async function handleResponse<T>(res: Response, errorPrefix: string): Promise<T> {
  if (!res.ok) {
    const body = await res.text().catch(() => '');
    throw new Error(`${errorPrefix} (${res.status}): ${body}`);
  }
  return (await res.json()) as T;
}

// ── Conversation types ──

export interface ConversationInfo {
  id: string;
  title: string | null;
  archived: boolean;
  createdAt: string;
  updatedAt: string;
}

// ── Conversation endpoints ──

export async function createConversation(
  gatewayUrl: string,
  sessionCookie: string,
  data: { title?: string; projectId?: string } = {},
): Promise<ConversationInfo> {
  const res = await fetch(`${gatewayUrl}/api/conversations`, {
    method: 'POST',
    headers: jsonHeaders(sessionCookie, gatewayUrl),
    body: JSON.stringify(data),
  });
  return handleResponse<ConversationInfo>(res, 'Failed to create conversation');
}

// ── Provider / Model endpoints ──

export async function fetchAvailableModels(
  gatewayUrl: string,
  sessionCookie?: string,
): Promise<ModelInfo[]> {
  try {
    const res = await fetch(`${gatewayUrl}/api/providers/models`, {
      headers: {
        ...(sessionCookie ? { Cookie: sessionCookie } : {}),
        Origin: gatewayUrl,
      },
    });
    if (!res.ok) return [];
    const data = (await res.json()) as ModelInfo[];
    return Array.isArray(data) ? data : [];
  } catch {
    return [];
  }
}

export async function fetchProviders(
  gatewayUrl: string,
  sessionCookie?: string,
): Promise<ProviderInfo[]> {
  try {
    const res = await fetch(`${gatewayUrl}/api/providers`, {
      headers: {
        ...(sessionCookie ? { Cookie: sessionCookie } : {}),
        Origin: gatewayUrl,
      },
    });
    if (!res.ok) return [];
    const data = (await res.json()) as ProviderInfo[];
    return Array.isArray(data) ? data : [];
  } catch {
    return [];
  }
}

// ── Session endpoints ──

export async function fetchSessions(
  gatewayUrl: string,
  sessionCookie: string,
): Promise<SessionListResult> {
  const res = await fetch(`${gatewayUrl}/api/sessions`, {
    headers: headers(sessionCookie, gatewayUrl),
  });
  return handleResponse<SessionListResult>(res, 'Failed to list sessions');
}

export async function deleteSession(
  gatewayUrl: string,
  sessionCookie: string,
  sessionId: string,
): Promise<void> {
  const res = await fetch(`${gatewayUrl}/api/sessions/${encodeURIComponent(sessionId)}`, {
    method: 'DELETE',
    headers: headers(sessionCookie, gatewayUrl),
  });
  if (!res.ok && res.status !== 204) {
    const body = await res.text().catch(() => '');
    throw new Error(`Failed to destroy session (${res.status}): ${body}`);
  }
}

// ── Agent Config endpoints ──

export async function fetchAgentConfigs(
  gatewayUrl: string,
  sessionCookie: string,
): Promise<AgentConfigInfo[]> {
  const res = await fetch(`${gatewayUrl}/api/agents`, {
    headers: headers(sessionCookie, gatewayUrl),
  });
  return handleResponse<AgentConfigInfo[]>(res, 'Failed to list agents');
}

export async function fetchAgentConfig(
  gatewayUrl: string,
  sessionCookie: string,
  id: string,
): Promise<AgentConfigInfo> {
  const res = await fetch(`${gatewayUrl}/api/agents/${encodeURIComponent(id)}`, {
    headers: headers(sessionCookie, gatewayUrl),
  });
  return handleResponse<AgentConfigInfo>(res, 'Failed to get agent');
}

export async function createAgentConfig(
  gatewayUrl: string,
  sessionCookie: string,
  data: {
    name: string;
    provider: string;
    model: string;
    projectId?: string;
    systemPrompt?: string;
    allowedTools?: string[];
    skills?: string[];
    config?: Record<string, unknown>;
  },
): Promise<AgentConfigInfo> {
  const res = await fetch(`${gatewayUrl}/api/agents`, {
    method: 'POST',
    headers: jsonHeaders(sessionCookie, gatewayUrl),
    body: JSON.stringify(data),
  });
  return handleResponse<AgentConfigInfo>(res, 'Failed to create agent');
}

export async function updateAgentConfig(
  gatewayUrl: string,
  sessionCookie: string,
  id: string,
  data: Record<string, unknown>,
): Promise<AgentConfigInfo> {
  const res = await fetch(`${gatewayUrl}/api/agents/${encodeURIComponent(id)}`, {
    method: 'PATCH',
    headers: jsonHeaders(sessionCookie, gatewayUrl),
    body: JSON.stringify(data),
  });
  return handleResponse<AgentConfigInfo>(res, 'Failed to update agent');
}

export async function deleteAgentConfig(
  gatewayUrl: string,
  sessionCookie: string,
  id: string,
): Promise<void> {
  const res = await fetch(`${gatewayUrl}/api/agents/${encodeURIComponent(id)}`, {
    method: 'DELETE',
    headers: headers(sessionCookie, gatewayUrl),
  });
  if (!res.ok && res.status !== 204) {
    const body = await res.text().catch(() => '');
    throw new Error(`Failed to delete agent (${res.status}): ${body}`);
  }
}

// ── Project endpoints ──

export async function fetchProjects(
  gatewayUrl: string,
  sessionCookie: string,
): Promise<ProjectInfo[]> {
  const res = await fetch(`${gatewayUrl}/api/projects`, {
    headers: headers(sessionCookie, gatewayUrl),
  });
  return handleResponse<ProjectInfo[]>(res, 'Failed to list projects');
}

// ── Mission endpoints ──

export async function fetchMissions(
  gatewayUrl: string,
  sessionCookie: string,
): Promise<MissionInfo[]> {
  const res = await fetch(`${gatewayUrl}/api/missions`, {
    headers: headers(sessionCookie, gatewayUrl),
  });
  return handleResponse<MissionInfo[]>(res, 'Failed to list missions');
}

export async function fetchMission(
  gatewayUrl: string,
  sessionCookie: string,
  id: string,
): Promise<MissionInfo> {
  const res = await fetch(`${gatewayUrl}/api/missions/${encodeURIComponent(id)}`, {
    headers: headers(sessionCookie, gatewayUrl),
  });
  return handleResponse<MissionInfo>(res, 'Failed to get mission');
}

export async function createMission(
  gatewayUrl: string,
  sessionCookie: string,
  data: {
    name: string;
    description?: string;
    projectId?: string;
    status?: string;
    phase?: string;
    milestones?: Record<string, unknown>[];
    config?: Record<string, unknown>;
  },
): Promise<MissionInfo> {
  const res = await fetch(`${gatewayUrl}/api/missions`, {
    method: 'POST',
    headers: jsonHeaders(sessionCookie, gatewayUrl),
    body: JSON.stringify(data),
  });
  return handleResponse<MissionInfo>(res, 'Failed to create mission');
}

export async function updateMission(
  gatewayUrl: string,
  sessionCookie: string,
  id: string,
  data: Record<string, unknown>,
): Promise<MissionInfo> {
  const res = await fetch(`${gatewayUrl}/api/missions/${encodeURIComponent(id)}`, {
    method: 'PATCH',
    headers: jsonHeaders(sessionCookie, gatewayUrl),
    body: JSON.stringify(data),
  });
  return handleResponse<MissionInfo>(res, 'Failed to update mission');
}

export async function deleteMission(
  gatewayUrl: string,
  sessionCookie: string,
  id: string,
): Promise<void> {
  const res = await fetch(`${gatewayUrl}/api/missions/${encodeURIComponent(id)}`, {
    method: 'DELETE',
    headers: headers(sessionCookie, gatewayUrl),
  });
  if (!res.ok && res.status !== 204) {
    const body = await res.text().catch(() => '');
    throw new Error(`Failed to delete mission (${res.status}): ${body}`);
  }
}

// ── Conversation Message types ──

export interface ConversationMessage {
  id: string;
  role: 'user' | 'assistant' | 'system' | 'tool';
  content: string;
  createdAt: string;
}

// ── Conversation Message endpoints ──

export async function fetchConversationMessages(
  gatewayUrl: string,
  sessionCookie: string,
  conversationId: string,
): Promise<ConversationMessage[]> {
  const res = await fetch(
    `${gatewayUrl}/api/conversations/${encodeURIComponent(conversationId)}/messages`,
    {
      headers: headers(sessionCookie, gatewayUrl),
    },
  );
  return handleResponse<ConversationMessage[]>(res, 'Failed to fetch conversation messages');
}

// ── Mission Task endpoints ──

export async function fetchMissionTasks(
  gatewayUrl: string,
  sessionCookie: string,
  missionId: string,
): Promise<MissionTaskInfo[]> {
  const res = await fetch(`${gatewayUrl}/api/missions/${encodeURIComponent(missionId)}/tasks`, {
    headers: headers(sessionCookie, gatewayUrl),
  });
  return handleResponse<MissionTaskInfo[]>(res, 'Failed to list mission tasks');
}

export async function createMissionTask(
  gatewayUrl: string,
  sessionCookie: string,
  missionId: string,
  data: {
    description?: string;
    status?: string;
    notes?: string;
    pr?: string;
    taskId?: string;
  },
): Promise<MissionTaskInfo> {
  const res = await fetch(`${gatewayUrl}/api/missions/${encodeURIComponent(missionId)}/tasks`, {
    method: 'POST',
    headers: jsonHeaders(sessionCookie, gatewayUrl),
    body: JSON.stringify(data),
  });
  return handleResponse<MissionTaskInfo>(res, 'Failed to create mission task');
}

export async function updateMissionTask(
  gatewayUrl: string,
  sessionCookie: string,
  missionId: string,
  taskId: string,
  data: Record<string, unknown>,
): Promise<MissionTaskInfo> {
  const res = await fetch(
    `${gatewayUrl}/api/missions/${encodeURIComponent(missionId)}/tasks/${encodeURIComponent(taskId)}`,
    {
      method: 'PATCH',
      headers: jsonHeaders(sessionCookie, gatewayUrl),
      body: JSON.stringify(data),
    },
  );
  return handleResponse<MissionTaskInfo>(res, 'Failed to update mission task');
}
