/**
 * Federation API Client
 * Handles federation connection management API requests
 */

import { apiGet, apiPost, apiPatch } from "./client";

/**
 * Federation connection status
 */
export enum FederationConnectionStatus {
  PENDING = "PENDING",
  ACTIVE = "ACTIVE",
  DISCONNECTED = "DISCONNECTED",
  REJECTED = "REJECTED",
}

/**
 * Federation capabilities
 */
export interface FederationCapabilities {
  supportsQuery: boolean;
  supportsCommand: boolean;
  supportsEvent: boolean;
  supportsAgentSpawn: boolean;
  protocolVersion: string;
}

/**
 * Connection details
 */
export interface ConnectionDetails {
  id: string;
  workspaceId: string;
  remoteInstanceId: string;
  remoteUrl: string;
  remotePublicKey: string;
  remoteCapabilities: FederationCapabilities;
  status: FederationConnectionStatus;
  metadata: Record<string, unknown>;
  createdAt: string;
  updatedAt: string;
  connectedAt: string | null;
  disconnectedAt: string | null;
}

/**
 * Public instance identity
 */
export interface PublicInstanceIdentity {
  id: string;
  instanceId: string;
  name: string;
  url: string;
  publicKey: string;
  capabilities: FederationCapabilities;
  metadata: Record<string, unknown>;
  createdAt: string;
  updatedAt: string;
}

/**
 * Initiate connection request
 */
export interface InitiateConnectionRequest {
  remoteUrl: string;
}

/**
 * Accept connection request
 */
export interface AcceptConnectionRequest {
  metadata?: Record<string, unknown>;
}

/**
 * Reject connection request
 */
export interface RejectConnectionRequest {
  reason: string;
}

/**
 * Disconnect connection request
 */
export interface DisconnectConnectionRequest {
  reason?: string;
}

/**
 * Fetch all connections
 */
export async function fetchConnections(
  status?: FederationConnectionStatus
): Promise<ConnectionDetails[]> {
  const params = new URLSearchParams();

  if (status) {
    params.append("status", status);
  }

  const queryString = params.toString();
  const endpoint = queryString
    ? `/api/v1/federation/connections?${queryString}`
    : "/api/v1/federation/connections";

  return apiGet<ConnectionDetails[]>(endpoint);
}

/**
 * Fetch a single connection
 */
export async function fetchConnection(connectionId: string): Promise<ConnectionDetails> {
  return apiGet<ConnectionDetails>(`/api/v1/federation/connections/${connectionId}`);
}

/**
 * Initiate a new connection
 */
export async function initiateConnection(
  request: InitiateConnectionRequest
): Promise<ConnectionDetails> {
  return apiPost<ConnectionDetails>("/api/v1/federation/connections/initiate", request);
}

/**
 * Accept a pending connection
 */
export async function acceptConnection(
  connectionId: string,
  request?: AcceptConnectionRequest
): Promise<ConnectionDetails> {
  return apiPost<ConnectionDetails>(
    `/api/v1/federation/connections/${connectionId}/accept`,
    request ?? {}
  );
}

/**
 * Reject a pending connection
 */
export async function rejectConnection(
  connectionId: string,
  request: RejectConnectionRequest
): Promise<ConnectionDetails> {
  return apiPost<ConnectionDetails>(
    `/api/v1/federation/connections/${connectionId}/reject`,
    request
  );
}

/**
 * Disconnect an active connection
 */
export async function disconnectConnection(
  connectionId: string,
  request?: DisconnectConnectionRequest
): Promise<ConnectionDetails> {
  return apiPost<ConnectionDetails>(
    `/api/v1/federation/connections/${connectionId}/disconnect`,
    request ?? {}
  );
}

/**
 * Get this instance's public identity
 */
export async function fetchInstanceIdentity(): Promise<PublicInstanceIdentity> {
  return apiGet<PublicInstanceIdentity>("/api/v1/federation/instance");
}

/**
 * Update instance configuration request
 */
export interface UpdateInstanceRequest {
  name?: string;
  capabilities?: FederationCapabilities;
  metadata?: Record<string, unknown>;
}

/**
 * Update this instance's configuration
 * Admin-only operation
 */
export async function updateInstanceConfiguration(
  updates: UpdateInstanceRequest
): Promise<PublicInstanceIdentity> {
  return apiPatch<PublicInstanceIdentity>("/api/v1/federation/instance", updates);
}

/**
 * Regenerate instance keypair
 * Admin-only operation
 */
export async function regenerateInstanceKeys(): Promise<PublicInstanceIdentity> {
  return apiPost<PublicInstanceIdentity>("/api/v1/federation/instance/regenerate-keys", {});
}

/**
 * Get mock connections for development only.
 * Returns an empty array in production as defense-in-depth.
 * The federation pages are also gated behind a ComingSoon component
 * in production (SEC-WEB-4), but this provides an additional layer.
 */
export function getMockConnections(): ConnectionDetails[] {
  if (process.env.NODE_ENV !== "development") {
    return [];
  }

  return [
    {
      id: "conn-1",
      workspaceId: "workspace-1",
      remoteInstanceId: "instance-work-001",
      remoteUrl: "https://mosaic.work.example.com",
      remotePublicKey: "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----",
      remoteCapabilities: {
        supportsQuery: true,
        supportsCommand: true,
        supportsEvent: true,
        supportsAgentSpawn: true,
        protocolVersion: "1.0",
      },
      status: FederationConnectionStatus.ACTIVE,
      metadata: {
        name: "Work Instance",
        description: "Corporate Mosaic instance",
      },
      createdAt: new Date("2026-02-01").toISOString(),
      updatedAt: new Date("2026-02-01").toISOString(),
      connectedAt: new Date("2026-02-01").toISOString(),
      disconnectedAt: null,
    },
    {
      id: "conn-2",
      workspaceId: "workspace-1",
      remoteInstanceId: "instance-partner-001",
      remoteUrl: "https://mosaic.partner.example.com",
      remotePublicKey: "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----",
      remoteCapabilities: {
        supportsQuery: true,
        supportsCommand: false,
        supportsEvent: true,
        supportsAgentSpawn: false,
        protocolVersion: "1.0",
      },
      status: FederationConnectionStatus.PENDING,
      metadata: {
        name: "Partner Instance",
        description: "Shared project collaboration",
      },
      createdAt: new Date("2026-02-02").toISOString(),
      updatedAt: new Date("2026-02-02").toISOString(),
      connectedAt: null,
      disconnectedAt: null,
    },
    {
      id: "conn-3",
      workspaceId: "workspace-1",
      remoteInstanceId: "instance-old-001",
      remoteUrl: "https://mosaic.old.example.com",
      remotePublicKey: "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----",
      remoteCapabilities: {
        supportsQuery: true,
        supportsCommand: true,
        supportsEvent: false,
        supportsAgentSpawn: false,
        protocolVersion: "1.0",
      },
      status: FederationConnectionStatus.DISCONNECTED,
      metadata: {
        name: "Previous Instance",
        description: "No longer in use",
      },
      createdAt: new Date("2026-01-15").toISOString(),
      updatedAt: new Date("2026-01-30").toISOString(),
      connectedAt: new Date("2026-01-15").toISOString(),
      disconnectedAt: new Date("2026-01-30").toISOString(),
    },
  ];
}
