import { resolve } from "node:path";
import type { Page } from "playwright";
import { testDevices } from "../testDevices";
import { withPlaywright } from "../utils/withPlaywright";
import type { Task } from "./TaskExecutor";

type CaptureCase = {
  name: string;
  setup: (page: Page) => Promise<void>;
};

export const defineCapture = (options: {
  href: string;
  cases?: readonly CaptureCase[];
}) => {
  const { href, cases = [] } = options;

  const paths = href
    .split("/")
    .map((path) => path.trim())
    .filter((path) => path !== "");

  const colorSchemes = ["light", "dark"] as const;

  const captureWithCase = async (
    device: (typeof testDevices)[number],
    colorScheme: (typeof colorSchemes)[number],
    testCase?: CaptureCase,
  ) => {
    await withPlaywright(
      async ({ context, cleanUp }) => {
        try {
          const page = await context.newPage();
          await page.goto(href);

          await page.waitForLoadState("domcontentloaded");
          await page.waitForTimeout(1000);

          if (testCase) {
            await testCase.setup(page);
          }

          await page.waitForTimeout(1000);

          const picturePath = testCase
            ? resolve(
                "e2e",
                "snapshots",
                ...paths,
                testCase.name,
                `${device.name}-${colorScheme}.png`,
              )
            : resolve(
                "e2e",
                "snapshots",
                ...paths,
                `${device.name}-${colorScheme}.png`,
              );

          await page.screenshot({
            path: picturePath,
            fullPage: true,
          });

          console.log(`[captured] ${picturePath}`);
        } finally {
          await cleanUp();
        }
      },
      {
        contextOptions: {
          ...device.device,
          baseURL: "http://localhost:4000",
          colorScheme,
        },
      },
    );
  };

  const tasks = testDevices.flatMap((device): Task[] => {
    return colorSchemes.flatMap((colorScheme): Task[] => [
      {
        key: `${device.name}-${colorScheme}-default`,
        execute: () => captureWithCase(device, colorScheme),
      },
      ...cases.map((testCase) => ({
        key: `${device.name}-${colorScheme}-${testCase.name}`,
        execute: () => captureWithCase(device, colorScheme, testCase),
      })),
    ]);
  });

  return {
    tasks,
  } as const;
};
