import { Redis } from 'ioredis';
import { createDb, buildLogs } from '@bmm/db';
import type { BuildEvent, BuildStatus } from '@bmm/types';
import { config } from '../config.js';

const pub = new Redis(config.REDIS_URL, { maxRetriesPerRequest: null });
const db = createDb();

function channel(buildId: string): string {
  return `build:${buildId}`;
}

export async function emitLog(
  buildId: string,
  level: 'info' | 'warn' | 'error',
  message: string,
): Promise<void> {
  const at = new Date().toISOString();
  const evt: BuildEvent = { type: 'log', level, message, at };
  await pub.publish(channel(buildId), JSON.stringify(evt));
  await db.insert(buildLogs).values({ buildId, level, message });
}

export async function emitStatus(buildId: string, status: BuildStatus): Promise<void> {
  const at = new Date().toISOString();
  const evt: BuildEvent = { type: 'status', status, at };
  await pub.publish(channel(buildId), JSON.stringify(evt));
}

export async function emitDone(
  buildId: string,
  status: BuildStatus,
  serverId: string,
  publicUrl: string | null,
): Promise<void> {
  const at = new Date().toISOString();
  const evt: BuildEvent = { type: 'done', status, serverId, publicUrl, at };
  await pub.publish(channel(buildId), JSON.stringify(evt));
}

export async function emitError(buildId: string, message: string): Promise<void> {
  const at = new Date().toISOString();
  const evt: BuildEvent = { type: 'error', message, at };
  await pub.publish(channel(buildId), JSON.stringify(evt));
  await db.insert(buildLogs).values({ buildId, level: 'error', message });
}
