/**
 * Test event emitter
 * Creates fake Jetstream events and processes them through the real ingester handler
 */

import { handleEvent, type IngesterDb } from "../../../ingester/src/handler";
import type { JetstreamEvent } from "../../../ingester/src/jetstream";
import { getTestDb } from "./test-db";

let rkeyCounter = 0;
let cidCounter = 0;
let timeUsCounter = Date.now() * 1000;

function generateRkey(): string {
  return `test_${Date.now()}_${++rkeyCounter}`;
}

function generateCid(): string {
  return `bafytest${++cidCounter}`;
}

function generateTimeUs(): number {
  return ++timeUsCounter;
}

export function resetCounters(): void {
  rkeyCounter = 0;
  cidCounter = 0;
  timeUsCounter = Date.now() * 1000;
}

type Collection = "app.sidetrail.trail" | "app.sidetrail.walk" | "app.sidetrail.completion";

interface EmitResult {
  uri: string;
  cid: string;
  rkey: string;
}

/**
 * Emit a create/update event through the ingester
 */
export async function emit(
  collection: Collection,
  did: string,
  record: Record<string, unknown>,
  existingRkey?: string,
): Promise<EmitResult> {
  const db = getTestDb() as unknown as IngesterDb;
  const rkey = existingRkey || generateRkey();
  const cid = generateCid();
  const operation = existingRkey ? "update" : "create";

  const event: JetstreamEvent = {
    did,
    time_us: generateTimeUs(),
    kind: "commit",
    commit: {
      operation,
      record,
      rev: `rev_${Date.now()}`,
      collection,
      rkey,
      cid,
    },
  };

  await handleEvent(db, event);

  return {
    uri: `at://${did}/${collection}/${rkey}`,
    cid,
    rkey,
  };
}

/**
 * Emit a delete event through the ingester
 */
export async function emitDelete(collection: Collection, uri: string): Promise<void> {
  const db = getTestDb() as unknown as IngesterDb;
  const parts = uri.split("/");
  const rkey = parts[parts.length - 1];
  const did = parts[2];

  const event: JetstreamEvent = {
    did,
    time_us: generateTimeUs(),
    kind: "commit",
    commit: {
      operation: "delete",
      rev: `rev_${Date.now()}`,
      collection,
      rkey,
    },
  };

  await handleEvent(db, event);
}

let seqCounter = 0;

export function resetSeqCounter(): void {
  seqCounter = 0;
}

type AccountStatus = "takendown" | "suspended" | "deleted" | "deactivated";

/**
 * Emit an account event through the ingester
 * Simulates account status changes (takedown, suspension, deletion, reactivation)
 */
export async function emitAccount(
  did: string,
  active: boolean,
  status?: AccountStatus,
): Promise<void> {
  const db = getTestDb() as unknown as IngesterDb;
  const seq = ++seqCounter;

  const event: JetstreamEvent = {
    did,
    time_us: generateTimeUs(),
    kind: "account",
    account: {
      active,
      did,
      seq,
      time: new Date().toISOString(),
      status: active ? undefined : status,
    },
  };

  await handleEvent(db, event);
}
