import { createHash } from 'node:crypto';
import { open, realpath, stat } from 'node:fs/promises';
import { isAbsolute, resolve } from 'node:path';
import { MAX_ATTACHMENT_BYTES } from '@maka/core/attachments';
import {
  createToolResultArchiveCapability,
  isPathInside,
  stableToolResultArchiveArtifactId,
  type ToolResultArchiveCapability,
  type ToolArtifactRecorderInput,
  type ToolResultArchiveReaderInput,
  type ToolResultArchiveReadResult,
  type ToolResultArchiveRecorderInput,
  type ToolResultArchiveResourceReadInput,
} from '@maka/runtime';
import type { InteractiveArtifactStoreWriter } from '@maka/storage/artifact-stores';

export interface HostExecutionArtifactServices {
  recordToolArtifacts(event: ToolArtifactRecorderInput): Promise<void>;
  /**
   * One archive authority over the session artifact store (#2026). All three
   * reads and the writer address the same store, so the host has no way to hand
   * out half of it.
   */
  toolResultArchive: ToolResultArchiveCapability;
}

export function createHostExecutionArtifactServices(input: {
  artifacts: InteractiveArtifactStoreWriter;
  requestDrain: () => void;
}): HostExecutionArtifactServices {
  const runWrite = async <T>(operation: () => Promise<T>): Promise<T> => {
    try {
      return await operation();
    } catch (error) {
      input.requestDrain();
      throw error;
    }
  };

  const recordToolArtifacts = async (event: ToolArtifactRecorderInput): Promise<void> => {
    for (const candidate of event.candidates) {
      let content = candidate.content;
      if (content === undefined && candidate.sourcePath) {
        content = (await readBoundedSourceFile(event.cwd, candidate.sourcePath)) ?? undefined;
      }
      if (content === undefined || contentBytes(content) > MAX_ATTACHMENT_BYTES) continue;
      await runWrite(() =>
        input.artifacts.create({
          sessionId: event.sessionId,
          turnId: event.turnId,
          name: candidate.name,
          kind: candidate.kind,
          content,
          ...(candidate.mimeType ? { mimeType: candidate.mimeType } : {}),
          source: candidate.source ?? 'tool_result',
          ...(candidate.summary ? { summary: candidate.summary } : {}),
        }),
      );
    }
  };

  const services: HostExecutionArtifactServices = {
    recordToolArtifacts,
    toolResultArchive: createToolResultArchiveCapability({
      archiveToolResult: (event: ToolResultArchiveRecorderInput) =>
        runWrite(async () => {
          const artifactId = stableToolResultArchiveArtifactId(event);
          const existing = await input.artifacts.getInSession(event.sessionId, artifactId);
          if (existing.record?.status === 'live') {
            const read = await readArchive(input.artifacts, {
              artifactId,
              sessionId: event.sessionId,
              bodySha256: event.bodySha256,
              originalBytes: event.originalBytes,
              maxBytes: event.originalBytes,
            });
            if (!read.ok) {
              throw new Error(`Tool result archive identity conflict: ${read.reason}`);
            }
            return { artifactId };
          }
          const artifact = await input.artifacts.create({
            id: artifactId,
            sessionId: event.sessionId,
            turnId: event.turnId,
            name: `archived-${event.toolName}-${event.runtimeEventId}.json`,
            kind: 'file',
            content: event.serializedResult,
            mimeType: 'application/json',
            source: 'tool_result_archive',
            summary: `Archived ${event.toolName} tool result for context budget replay`,
          });
          return { artifactId: artifact.id };
        }),
      readToolResultArchive: (event: ToolResultArchiveReaderInput) =>
        readArchive(input.artifacts, event),
      readArchivedToolResultResource: (event: ToolResultArchiveResourceReadInput) =>
        readArchive(input.artifacts, event),
    }),
  };
  return Object.freeze(services);
}

async function readBoundedSourceFile(cwd: string, sourcePath: string): Promise<Buffer | null> {
  const candidate = isAbsolute(sourcePath) ? sourcePath : resolve(cwd, sourcePath);
  let root: string;
  let target: string;
  try {
    [root, target] = await Promise.all([realpath(cwd), realpath(candidate)]);
  } catch {
    return null;
  }
  if (!isPathInside(root, target)) return null;
  let handle: Awaited<ReturnType<typeof open>> | undefined;
  try {
    handle = await open(target, 'r');
    const opened = await handle.stat();
    if (!opened.isFile() || opened.size > MAX_ATTACHMENT_BYTES) return null;
    const currentTarget = await realpath(target);
    if (!isPathInside(root, currentTarget)) return null;
    const current = await stat(currentTarget);
    if (current.dev !== opened.dev || current.ino !== opened.ino) return null;
    const bytes = Buffer.allocUnsafe(opened.size);
    let offset = 0;
    while (offset < bytes.byteLength) {
      const read = await handle.read(bytes, offset, bytes.byteLength - offset, offset);
      if (read.bytesRead === 0) break;
      offset += read.bytesRead;
    }
    return offset === bytes.byteLength ? bytes : bytes.subarray(0, offset);
  } catch {
    return null;
  } finally {
    await handle?.close().catch(() => undefined);
  }
}

function contentBytes(content: string | Uint8Array): number {
  return typeof content === 'string' ? Buffer.byteLength(content, 'utf8') : content.byteLength;
}

async function readArchive(
  artifacts: InteractiveArtifactStoreWriter,
  event: Pick<
    ToolResultArchiveReaderInput,
    'artifactId' | 'sessionId' | 'bodySha256' | 'originalBytes' | 'maxBytes'
  >,
): Promise<ToolResultArchiveReadResult> {
  const entry = await artifacts.getInSession(event.sessionId, event.artifactId);
  const record = entry.record;
  if (!record) return { ok: false, reason: 'not_found' };
  if (record.status === 'deleted') return { ok: false, reason: 'deleted' };
  if (record.source !== 'tool_result_archive') return { ok: false, reason: 'source_mismatch' };
  if (record.sizeBytes !== event.originalBytes) return { ok: false, reason: 'size_mismatch' };
  const read = await artifacts.readTextInSession(event.sessionId, event.artifactId, {
    maxBytes: event.maxBytes ?? event.originalBytes,
  });
  if (!read.ok) return read;
  if (sha256(read.text) !== event.bodySha256) return { ok: false, reason: 'corrupt' };
  return { ok: true, serializedResult: read.text };
}

function sha256(text: string): string {
  return createHash('sha256').update(text).digest('hex');
}
