/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import { activateLocalManagedRuntimeHost } from './runtime-host-local-managed-activation.js';
import { randomUUID } from 'node:crypto';
import { join } from 'node:path';
import { NO_REAL_CONNECTION_CODE } from '@maka/core/connection-error-copy';
import type {
  RuntimeHostConnectionCatalogEntry as ConnectionCatalogEntry,
  RuntimeHostConnectionCatalogSnapshot as ConnectionCatalogSnapshot,
} from '@maka/runtime-host/client';
import type { ChatDefaultPermissionMode } from '@maka/core/settings';
import {
  connectOrSpawnRuntimeHost,
  forceTerminateObservedRegisteredRuntimeHost,
  connectRuntimeHost,
  connectRuntimeHostProfile,
  createClientRuntimeHostProfileCatalog,
  createRuntimeHostPeerClientFromEnvironment,
  createRuntimeHostReconnectingConnection,
  loadOrCreateRuntimeHostClientInstanceId,
  LOCAL_RUNTIME_HOST_PROFILE,
  readRuntimeHostConnectionCatalog,
  RuntimeHostPermanentReconnectError,
  RuntimeHostRemoteCompatibilityError,
  runHostHandoff,
  type OpenHostHandoffSurface,
  type HostHandoffReplacement,
  type HostHandoffObservation,
  runtimeHostStartupError,
  type RuntimeHostConnection,
  type RuntimeHostProfile,
  type ResolvedRuntimeHostProfile,
  type RuntimeHostProfileCatalog,
  type RuntimeHostPeerClient,
} from '@maka/runtime-host/client';
import {
  INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID,
  RUNTIME_HOST_PROTOCOL_VERSION,
  RUNTIME_HOST_COMPATIBILITY_EPOCH,
} from '@maka/runtime-host/protocol';
import {
  readLocalHostDeploymentRecord,
  resolveRuntimeHostManagedDeploymentAuthority,
} from '@maka/runtime-host/operator';
import { resolveMakaClientDataRoot } from '@maka/storage/workspace-root';
import {
  isTemporaryNpxInstallation,
  resolveRuntimeHostNpmGlobalInstallation,
} from './runtime-host-cli-installation.js';
import {
  restartRuntimeHostNpmGlobalDeployment,
  runtimeHostNpmGlobalSourceRetirementAvailable,
} from './runtime-host-local-handoff.js';

/**
 * The mode a new Session starts in belongs to the Host: `session.create`
 * falls back to `chatDefaults.permissionMode` in the Runtime Policy whenever a
 * client omits the field, so that policy value is the single authority.
 *
 * The CLI reads it rather than assuming Auto, because its pickers and its
 * status indicator name the mode a new Session will *actually* get. Assuming
 * Auto against a Host configured for full access would understate the
 * boundary, which is the one direction that must never happen.
 *
 * A failed query throws rather than resolving to `ask`. Understating the
 * boundary is not the safe direction it looks like: creation omits the field
 * either way, so a Host configured for Bypass would run the first prompt with
 * full access while the CLI displayed Auto. If the Host's own policy cannot be
 * read, the CLI has nothing true to show and should not start.
 */
export async function readHostChatDefaultPermissionMode(
  connection: Pick<RuntimeHostConnection, 'request'>,
): Promise<ChatDefaultPermissionMode> {
  return (await connection.request('runtime.policy.query', {})).policy.chatDefaults.permissionMode;
}

export interface RuntimeHostCliConnectionOnlyContext {
  readonly connection: RuntimeHostConnection;
  readonly profile: RuntimeHostProfile;
  close(): Promise<void>;
}

export interface RuntimeHostCliConnectionOnlyContextWithIdentity
  extends RuntimeHostCliConnectionOnlyContext {
  readonly clientInstanceId: string;
  readonly profileIncarnationId?: string;
}

export interface RuntimeHostCliConnectionContext extends RuntimeHostCliConnectionOnlyContext {
  readonly catalog: ConnectionCatalogSnapshot;
}

export interface RuntimeHostCliConnectionContextWithIdentity
  extends RuntimeHostCliConnectionContext,
    RuntimeHostCliConnectionOnlyContextWithIdentity {}

export interface RuntimeHostCliConnectionInput {
  readonly rootPath: string;
  readonly profileId?: string;
  readonly clientDataRoot?: string;
  readonly interactiveSsh?: boolean;
  readonly signal?: AbortSignal;
  readonly handoffSurface?: OpenHostHandoffSurface;
}

export interface RuntimeHostCliTarget {
  readonly connection: ConnectionCatalogEntry;
  readonly model: string;
}

interface RuntimeHostCliContextDeps {
  readonly connectOrSpawn: typeof connectOrSpawnRuntimeHost;
  readonly connectActivatedHost: typeof connectRuntimeHost;
  readonly activateLocalManagedHost: typeof activateLocalManagedRuntimeHost;
  readonly connectProfile: typeof connectRuntimeHostProfile;
  readonly readConnectionCatalog: typeof readRuntimeHostConnectionCatalog;
  readonly loadClientInstanceId: typeof loadOrCreateRuntimeHostClientInstanceId;
  readonly executionCandidateEntrypoint: URL;
  readonly readDeploymentRecord: typeof readLocalHostDeploymentRecord;
  readonly resolveManagedAuthority: typeof resolveRuntimeHostManagedDeploymentAuthority;
  readonly createPeerClient: typeof createRuntimeHostPeerClientFromEnvironment;
  readonly profileCatalog?: RuntimeHostProfileCatalog;
  readonly resolveInstallation: typeof resolveRuntimeHostNpmGlobalInstallation;
  readonly isTemporaryNpxInstallation: typeof isTemporaryNpxInstallation;
  readonly terminateObservedHost: typeof forceTerminateObservedRegisteredRuntimeHost;
  readonly restartDeployment: typeof restartRuntimeHostNpmGlobalDeployment;
  readonly sourceRetirementAvailable: typeof runtimeHostNpmGlobalSourceRetirementAvailable;
}

export async function connectRuntimeHostCli(
  input: RuntimeHostCliConnectionInput,
  overrides: Partial<RuntimeHostCliContextDeps> = {},
): Promise<RuntimeHostCliConnectionContextWithIdentity> {
  const context = await connectRuntimeHostCliConnection(input, overrides);
  try {
    const catalog = await runAbortably(
      () =>
        (overrides.readConnectionCatalog ?? readRuntimeHostConnectionCatalog)(context.connection),
      input.signal,
    );
    return { ...context, catalog };
  } catch (error) {
    await context.close().catch(() => undefined);
    throw error;
  }
}

export async function connectRuntimeHostCliConnection(
  input: RuntimeHostCliConnectionInput,
  overrides: Partial<RuntimeHostCliContextDeps> = {},
): Promise<RuntimeHostCliConnectionOnlyContextWithIdentity> {
  const deps: RuntimeHostCliContextDeps = {
    connectOrSpawn: connectOrSpawnRuntimeHost,
    activateLocalManagedHost: activateLocalManagedRuntimeHost,
    connectActivatedHost: connectRuntimeHost,
    connectProfile: connectRuntimeHostProfile,
    readConnectionCatalog: readRuntimeHostConnectionCatalog,
    loadClientInstanceId: loadOrCreateRuntimeHostClientInstanceId,
    executionCandidateEntrypoint: new URL(
      import.meta.resolve('@maka/runtime-host/execution-candidate-main'),
    ),
    readDeploymentRecord: readLocalHostDeploymentRecord,
    resolveManagedAuthority: resolveRuntimeHostManagedDeploymentAuthority,
    createPeerClient: createRuntimeHostPeerClientFromEnvironment,
    resolveInstallation: resolveRuntimeHostNpmGlobalInstallation,
    isTemporaryNpxInstallation,
    terminateObservedHost: forceTerminateObservedRegisteredRuntimeHost,
    restartDeployment: restartRuntimeHostNpmGlobalDeployment,
    sourceRetirementAvailable: runtimeHostNpmGlobalSourceRetirementAvailable,
    ...overrides,
  };
  const resolvedProfile = await resolveHostProfile(input, deps);
  const profile = resolvedProfile.profile;
  const clientInstanceId =
    profile.kind === 'local'
      ? randomUUID()
      : await deps.loadClientInstanceId(
          join(input.clientDataRoot ?? resolveMakaClientDataRoot(), 'runtime-host-client.json'),
        );
  const peerClient: RuntimeHostPeerClient | undefined =
    profile.kind === 'remote' && profile.transport.kind === 'libp2p-direct'
      ? deps.createPeerClient()
      : undefined;
  // A temporary package is evidence for invocation lifetime, never deployment
  // authority. This only guards candidates we create; using an existing Host
  // leaves that Host's ownership and lifetime unchanged.
  const invocationOwned = profile.kind === 'local' && (await deps.isTemporaryNpxInstallation());
  const connectInput = {
    rootPath: input.rootPath,
    protocol: { min: RUNTIME_HOST_PROTOCOL_VERSION, max: RUNTIME_HOST_PROTOCOL_VERSION },
    clientInstanceId,
    compositionId: INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID,
    candidateEntrypoint: deps.executionCandidateEntrypoint,
    ...(invocationOwned ? { closeOnLauncherExit: true } : {}),
  } as const;
  const connect = async (
    signal?: AbortSignal,
    sshInteraction: 'batch' | 'inherit' = 'batch',
  ): Promise<RuntimeHostConnection> => {
    const observe = async (): Promise<HostHandoffObservation<RuntimeHostConnection>> => {
      if (profile.kind !== 'local') {
        try {
          const connection = await deps.connectProfile({
            profile,
            ...(resolvedProfile.credential ? { credential: resolvedProfile.credential } : {}),
            clientInstanceId,
            sshInteraction,
            ...(peerClient ? { peerClient } : {}),
            ...(signal ? { signal } : {}),
          });
          return { kind: 'ready', value: connection };
        } catch (error) {
          if (!(error instanceof RuntimeHostRemoteCompatibilityError)) throw error;
          return {
            kind: 'blocked',
            blocker: {
              identity: JSON.stringify([profile, error.hostEpoch, error.details]),
              target: {
                name: profile.name,
                location: 'remote',
                rootId: profile.rootId,
                hostEpoch: error.hostEpoch,
              },
              reason: 'upgrade',
              mayExitNaturally: false,
              diagnostic: error.message,
            },
          };
        }
      }
      let connected = await deps.connectOrSpawn({
        ...connectInput,
        ...(signal ? { signal } : {}),
      });
      if (connected.kind === 'failed' && connected.reason === 'managed_root_requires_operator') {
        await deps.activateLocalManagedHost({
          rootPath: input.rootPath,
          ...(signal ? { signal } : {}),
        });
        signal?.throwIfAborted();
        // The installed operator owns launch. Compatibility is still projected
        // by the same handoff journey as an already-running managed Host.
        const activated = await deps.connectActivatedHost(connectInput);
        if (activated.kind === 'unavailable' || activated.kind === 'draining') {
          throw new Error(
            `The installed Runtime Host was activated but the local CLI could not join it (${activated.kind === 'unavailable' ? activated.reason : activated.kind}). Use a compatible CLI or update the managed Host through its configured operator.`,
          );
        }
        if (activated.kind === 'connected' && signal?.aborted) {
          await activated.connection.close();
          signal.throwIfAborted();
        }
        connected = activated;
      }
      if (connected.kind === 'incompatible' || connected.kind === 'upgrade_required') {
        const managed = await deps.resolveManagedAuthority(connected.registration.rootId);
        const record = managed
          ? undefined
          : await deps.readDeploymentRecord(connected.registration.rootId);
        let replacement: HostHandoffReplacement | undefined;
        let installation;
        let installationFailure: string | undefined;
        // On-demand managed Hosts are also ephemeral processes. Their durable
        // operator authority, not the process lifetime label, decides who may
        // replace them (including when the Host was already running).
        if (!managed && connected.registration.lifecycleMode === 'ephemeral') {
          try {
            installation = await deps.resolveInstallation();
          } catch (error) {
            installationFailure = error instanceof Error ? error.message : String(error);
          }
          const owner = record?.state.kind === 'handoff' ? record.state.from : record?.state.owner;
          if (
            installation &&
            (!owner ||
              (owner.kind === installation.owner.kind &&
                owner.installationId === installation.owner.installationId))
          ) {
            const expectedInstallation = installation;
            const canInterrupt =
              connected.processIdentity !== undefined ||
              (record
                ? await deps
                    .sourceRetirementAvailable({
                      rootId: connected.registration.rootId,
                      owner: installation.owner,
                      source: record.state.selected,
                    })
                    .catch(() => false)
                : false);
            replacement = {
              kind: record?.state.kind === 'handoff' ? 'repair' : 'replace',
              canReplaceIdle: true,
              canInterrupt,
              execute: async (activeWorkPolicy, _progress, _consent, attemptSignal) => {
                const result = await deps.restartDeployment({
                  rootPath: input.rootPath,
                  registration: connected.registration,
                  ...(connected.processIdentity
                    ? { processIdentity: connected.processIdentity }
                    : {}),
                  activeWorkPolicy,
                  expectedInstallation,
                  ...(attemptSignal ? { signal: attemptSignal } : {}),
                });
                if (result.kind === 'completed') return { kind: 'completed' };
                if (result.kind === 'active_work') return { kind: 'active_work' };
                if (
                  result.kind === 'changed' ||
                  result.kind === 'rejected' ||
                  result.kind === 'operator_required'
                )
                  return { kind: 'changed' };
                return {
                  kind: 'recovery_required',
                  diagnostic: `Local service recovery is required at ${result.phase}`,
                };
              },
            };
          }
        }
        // The same observed-process recovery used by Desktop is available to
        // persistent local invocations without a deployment owner. This is an
        // explicit interruption, never an idle inference or an installation claim.
        const processIdentity = connected.processIdentity;
        if (
          !replacement &&
          !managed &&
          !record &&
          !invocationOwned &&
          connected.registration.lifecycleMode === 'ephemeral' &&
          processIdentity
        ) {
          const registration = connected.registration;
          replacement = {
            kind: 'replace',
            canReplaceIdle: false,
            canInterrupt: true,
            execute: async (policy, progress, consent, attemptSignal) => {
              if (policy !== 'interrupt_active_work' || consent !== 'explicit') {
                return { kind: 'active_work' };
              }
              attemptSignal?.throwIfAborted();
              if (
                (await deps.resolveManagedAuthority(registration.rootId)) ||
                (await deps.readDeploymentRecord(registration.rootId))
              )
                return { kind: 'changed' };
              attemptSignal?.throwIfAborted();
              progress('retiring');
              const stopped = await deps.terminateObservedHost(
                { rootPath: input.rootPath, registration },
                { processIdentity, isCurrent: () => !signal?.aborted && !attemptSignal?.aborted },
              );
              if (!stopped) return { kind: 'changed' };
              progress('verifying');
              return { kind: 'completed' };
            },
          };
        }
        return {
          kind: 'blocked',
          blocker: {
            identity: JSON.stringify([
              connected.registration,
              processIdentity,
              managed?.record,
              record,
              installation,
            ]),
            target: {
              name: profile.name,
              location: 'local',
              rootId: connected.registration.rootId,
              hostEpoch: connected.registration.hostEpoch,
            },
            reason: record?.state.kind === 'handoff' ? 'repair' : 'upgrade',
            ...(!replacement
              ? {
                  recoveryBlocker:
                    managed || connected.registration.lifecycleMode === 'service'
                      ? ('managed' as const)
                      : record
                        ? ('owner' as const)
                        : invocationOwned
                          ? ('installation' as const)
                          : ('identity' as const),
                  diagnostic: [
                    `Host compatibility: ${connected.registration.compatibilityEpoch}; client: ${RUNTIME_HOST_COMPATIBILITY_EPOCH}.`,
                    installationFailure,
                  ]
                    .filter(Boolean)
                    .join('\n'),
                }
              : {}),
            ...(connected.handshake?.activity ? { activity: connected.handshake.activity } : {}),
            mayExitNaturally:
              !managed &&
              connected.registration.lifecycleMode === 'ephemeral' &&
              connected.handshake?.replacement === 'wait_for_idle_exit',
            ...(replacement ? { replacement } : {}),
          },
        };
      }
      if (connected.kind === 'failed') {
        throw runtimeHostStartupError(connected.reason, connected.diagnostic);
      }
      if (connected.registration.generation?.startsWith('npm-global-handoff:')) {
        const record = await deps.readDeploymentRecord(connected.registration.rootId);
        if (record?.state.kind !== 'owned' || record.state.owner.kind !== 'cli') {
          await connected.connection.close().catch(() => undefined);
          throw new RuntimeHostPermanentReconnectError(
            'RUNTIME_HOST_RECOVERY_REQUIRED: The staged local Runtime Host is Ready, but its installation ownership was not durably committed.',
          );
        }
      }
      return { kind: 'ready', value: connected.connection };
    };
    return runHostHandoff({ observe, signal, openSurface: input.handoffSurface });
  };
  let initialConnection: RuntimeHostConnection | undefined;
  let connection: Awaited<ReturnType<typeof createRuntimeHostReconnectingConnection>> | undefined;
  try {
    initialConnection = await acquireAbortably(
      () =>
        connect(
          input.signal,
          input.interactiveSsh && process.stdin.isTTY && process.stdout.isTTY ? 'inherit' : 'batch',
        ),
      input.signal,
    );
    connection = await createRuntimeHostReconnectingConnection({
      initialConnection,
      connect: (signal) => connect(signal, 'batch'),
    });
    initialConnection = undefined;
    const liveConnection = connection;
    return {
      connection: liveConnection,
      profile,
      clientInstanceId,
      ...(resolvedProfile.profileIncarnationId
        ? { profileIncarnationId: resolvedProfile.profileIncarnationId }
        : {}),
      close: async () => {
        try {
          await liveConnection.close();
        } finally {
          await peerClient?.close();
        }
      },
    };
  } catch (error) {
    await (connection ?? initialConnection)?.close().catch(() => undefined);
    await peerClient?.close().catch(() => undefined);
    throw error;
  }
}

function acquireAbortably<T extends { close(): Promise<void> }>(
  operation: () => Promise<T>,
  signal?: AbortSignal,
): Promise<T> {
  if (!signal) return operation();
  if (signal.aborted) return Promise.reject(signal.reason);
  return new Promise<T>((resolve, reject) => {
    let settled = false;
    const settle = (callback: () => void) => {
      if (settled) return false;
      settled = true;
      signal.removeEventListener('abort', onAbort);
      callback();
      return true;
    };
    const onAbort = () => settle(() => reject(signal.reason));
    signal.addEventListener('abort', onAbort, { once: true });
    let running: Promise<T>;
    try {
      running = operation();
    } catch (error) {
      settle(() => reject(error));
      return;
    }
    void running.then(
      (value) => {
        if (!settle(() => resolve(value))) void value.close().catch(() => undefined);
      },
      (error: unknown) => settle(() => reject(error)),
    );
  });
}

function runAbortably<T>(operation: () => Promise<T>, signal?: AbortSignal): Promise<T> {
  if (!signal) return operation();
  if (signal.aborted) return Promise.reject(signal.reason);
  return new Promise<T>((resolve, reject) => {
    let settled = false;
    const settle = (callback: () => void) => {
      if (settled) return;
      settled = true;
      signal.removeEventListener('abort', onAbort);
      callback();
    };
    const onAbort = () => settle(() => reject(signal.reason));
    signal.addEventListener('abort', onAbort, { once: true });
    let running: Promise<T>;
    try {
      running = operation();
    } catch (error) {
      settle(() => reject(error));
      return;
    }
    void running.then(
      (value) => settle(() => resolve(value)),
      (error: unknown) => settle(() => reject(error)),
    );
  });
}

async function resolveHostProfile(
  input: { readonly profileId?: string; readonly clientDataRoot?: string },
  deps: RuntimeHostCliContextDeps,
): Promise<ResolvedRuntimeHostProfile> {
  if (input.profileId === undefined || input.profileId === LOCAL_RUNTIME_HOST_PROFILE.id) {
    return { profile: LOCAL_RUNTIME_HOST_PROFILE };
  }
  const root = input.clientDataRoot ?? resolveMakaClientDataRoot();
  const catalog = deps.profileCatalog ?? createClientRuntimeHostProfileCatalog(root);
  return catalog.resolve(input.profileId);
}

export function resolveRuntimeHostCliTarget(
  catalog: ConnectionCatalogSnapshot,
  input: { readonly connectionSlug?: string; readonly model?: string } = {},
): RuntimeHostCliTarget {
  const defaultTarget = catalog.defaultTarget;
  const connection = input.connectionSlug
    ? catalog.connections.find((candidate) => candidate.slug === input.connectionSlug)
    : catalog.connections.find(
        (candidate) => candidate.connectionId === defaultTarget?.connectionId,
      );
  if (!connection || !connection.enabled) {
    throw new Error(
      input.connectionSlug
        ? `Runtime Host model connection is unavailable: ${input.connectionSlug}`
        : `${NO_REAL_CONNECTION_CODE}:missing_default_connection: Runtime Host has no default model connection`,
    );
  }
  const model =
    input.model ??
    (connection.connectionId === defaultTarget?.connectionId
      ? defaultTarget.modelId
      : connection.enabledModelIds[0]);
  if (!model || !connection.enabledModelIds.includes(model)) {
    throw new Error(`Runtime Host model is unavailable for ${connection.slug}: ${model ?? ''}`);
  }
  return { connection, model };
}
