/**
 * Shared test harness for server.test.ts family.
 *
 * Provides database setup, queue mocking, and env handling used by all
 * WebhookServer test suites.  Each test file gets its own in‑memory DB
 * via the factory-style setup/teardown pair.
 */
import { Database } from 'bun:sqlite';
import { beforeAll, afterAll, beforeEach } from 'bun:test';
import { WebhookServer } from '../../src/server';
import { ResponseQueue } from '../../src/services/response-queue';
import { GroupSyncService } from '../../src/services/group-sync';
import { initializeDatabase } from '../../src/db';
import { setDb, resetDb } from '../../src/db/locator';
import { SimulatedResponseQueue } from './queue';

// ── Request builder ────────────────────────────────────────────────────

export function createTestRequest(payload: unknown): Request {
	return new Request('http://localhost:3007', {
		method: 'POST',
		headers: { 'Content-Type': 'application/json' },
		body: JSON.stringify(payload),
	});
}

// ── Date helper ────────────────────────────────────────────────────────

export function getFutureDate(days: number): string {
	const date = new Date();
	date.setDate(date.getDate() + days);
	return date.toISOString().split('T')[0];
}

// ── Lifecycle helpers ──────────────────────────────────────────────────

// ── Internal state ─────────────────────────────────────────────────────

const ENV_BACKUP = { ...process.env };

// ── Public lifecycle factory ───────────────────────────────────────────

/**
 * Register the standard beforeAll / afterAll / beforeEach hooks for a
 * WebhookServer test module.  Returns the shared in‑memory test DB so
 * individual tests can query it directly.
 *
 * Usage (at module scope in each test file):
 *   const testDb = registerServerTestLifecycle();
 */
export function registerServerTestLifecycle(): Database {
	const db = new Database(':memory:');
	initializeDatabase(db);

	const originalAdd = (ResponseQueue as any).add;

	beforeAll(() => {
		/* DB already set up */
	});

	afterAll(() => {
		(ResponseQueue as any).add = originalAdd;
		resetDb();
		db.close();
	});

	beforeEach(() => {
		// Clear simulated queue and swap in the fake
		SimulatedResponseQueue.clear();
		(ResponseQueue as any).add = SimulatedResponseQueue.add;

		// Point WebhookServer at the test DB
		WebhookServer.dbInstance = db;
		setDb(db);

		// Re‑init schema (safe after destructive tests that DROP tables)
		initializeDatabase(db);

		// Truncate data
		db.exec('DELETE FROM response_queue');
		try { db.exec('DELETE FROM task_origins'); } catch { /* may not exist */ }
		db.exec('DELETE FROM tasks');
		db.exec('DELETE FROM users');
		db.exec('DELETE FROM groups');

		// Canonical active group
		db.exec(`
      INSERT OR IGNORE INTO groups (id, community_id, name, active)
      VALUES ('group-id@g.us', 'test-community', 'Test Group', 1)
    `);
		(GroupSyncService as any).cacheActiveGroups();

		// Standard test env
		process.env = { ...ENV_BACKUP, INSTANCE_NAME: 'test-instance', NODE_ENV: 'test' };
	});

	return db;
}
