import type { StartedTestContainer } from "testcontainers";
import { GenericContainer, Wait } from "testcontainers";
import { describe, expect, test } from "vitest";

import { PiHoleIntegration } from "../src";

const DEFAULT_PASSWORD = "12341234";
const DEFAULT_API_KEY = "3b1434980677dcf53fa8c4a611db3b1f0f88478790097515c0abb539102778b9"; // Some hash generated from password

describe("Pi-hole integration", () => {
  test("getSummaryAsync should return summary from pi-hole", async () => {
    // Arrange
    const piholeContainer = await createPiHoleContainer(DEFAULT_PASSWORD).start();
    const piHoleIntegration = createPiHoleIntegration(piholeContainer, DEFAULT_API_KEY);

    // Act
    const result = await piHoleIntegration.getSummaryAsync();

    // Assert
    expect(result.adsBlockedToday).toBe(0);
    expect(result.adsBlockedTodayPercentage).toBe(0);
    expect(result.dnsQueriesToday).toBe(0);
    expect(result.domainsBeingBlocked).toBeGreaterThan(1);

    // Cleanup
    await piholeContainer.stop();
  }, 20_000); // Timeout of 20 seconds

  test("testConnectionAsync should not throw", async () => {
    // Arrange
    const piholeContainer = await createPiHoleContainer(DEFAULT_PASSWORD).start();
    const piHoleIntegration = createPiHoleIntegration(piholeContainer, DEFAULT_API_KEY);

    // Act
    const actAsync = async () => await piHoleIntegration.testConnectionAsync();

    // Assert
    await expect(actAsync()).resolves.not.toThrow();

    // Cleanup
    await piholeContainer.stop();
  }, 20_000); // Timeout of 20 seconds

  test("testConnectionAsync should throw with wrong credentials", async () => {
    // Arrange
    const piholeContainer = await createPiHoleContainer(DEFAULT_PASSWORD).start();
    const piHoleIntegration = createPiHoleIntegration(piholeContainer, "wrong-api-key");

    // Act
    const actAsync = async () => await piHoleIntegration.testConnectionAsync();

    // Assert
    await expect(actAsync()).rejects.toThrow();

    // Cleanup
    await piholeContainer.stop();
  }, 20_000); // Timeout of 20 seconds
});

const createPiHoleContainer = (password: string) => {
  return new GenericContainer("pihole/pihole:latest")
    .withEnvironment({
      WEBPASSWORD: password,
    })
    .withExposedPorts(80)
    .withWaitStrategy(Wait.forLogMessage("Pi-hole Enabled"));
};

const createPiHoleIntegration = (container: StartedTestContainer, apiKey: string) => {
  return new PiHoleIntegration({
    id: "1",
    decryptedSecrets: [
      {
        kind: "apiKey",
        value: apiKey,
      },
    ],
    name: "Pi hole",
    url: `http://${container.getHost()}:${container.getMappedPort(80)}`,
  });
};
