import { ExitCode, InternalService, Microservice, MicroserviceState } from "../../src";

class MockService<M extends Microservice> extends InternalService<M> {
	public NAME = "Mock Service";
	public override boot = jest.fn();
	public override start = jest.fn();
	public override shutdown = jest.fn();
}

class MockServiceBootFail<M extends Microservice> extends InternalService<M> {
	public NAME = "Boot Fail";
	public override async boot() {
		throw new Error();
	}
}

class MockServiceStartFail<M extends Microservice> extends InternalService<M> {
	public NAME = "Start Fail";
	public override async start() {
		throw new Error();
	}
}

class MockServiceShutdownFail<M extends Microservice> extends InternalService<M> {
	public NAME = "Shutdown Fail";
	public override async shutdown() {
		throw new Error();
	}
}

describe("Microservice/Internal Service Integration", () => {
	test("Check that internal service state methods have been executed", async () => {
		let microservice = new Microservice();
		microservice.installService(MockService);
		let executing = microservice.exec();
		microservice.on("ready", () => microservice.quit());
		await executing;
		expect(microservice.service(MockService).boot).toHaveBeenCalled();
		expect(microservice.service(MockService).start).toHaveBeenCalled();
		expect(microservice.service(MockService).shutdown).toHaveBeenCalled();
	});
	test("Trigger boot failure", async () => {
		let microservice = new Microservice();
		microservice.installService(MockServiceBootFail);
		let exitCode = await microservice.exec();
		expect(exitCode).toEqual(ExitCode.BootError);
		expect(microservice.state).toEqual(MicroserviceState.Finished);
	});
	test("Trigger start failure", async () => {
		let microservice = new Microservice();
		microservice.installService(MockServiceStartFail);
		let exitCode = await microservice.exec();
		expect(exitCode).toEqual(ExitCode.StartupError);
		expect(microservice.state).toEqual(MicroserviceState.Finished);
	});
	test("Trigger shutdown failure", async () => {
		let microservice = new Microservice();
		microservice.installService(MockServiceShutdownFail);
		let execPromise = microservice.exec();
		microservice.on("ready", () => microservice.quit());
		let exitCode = await execPromise;
		expect(exitCode).toEqual(ExitCode.ShutdownError);
		expect(microservice.state).toEqual(MicroserviceState.Finished);
	});
});
