import type {
  Reporter,
  FullConfig,
  Suite,
  TestCase,
  TestResult,
  FullResult,
  TestError,
} from "@playwright/test/reporter";

import { reportTestResults, validateAIOConfig } from "./aio-utils";
import { AioConfig, TestData } from "./model";
import AioTestsLogger from "./AioTestsLogger";
import aioTestsLogger from "./AioTestsLogger";

class AioReporter implements Reporter {
  static start = true;
  static end = true;
  aioConfig: AioConfig | undefined;
  testSummary: TestData[] = [];
  customOption: any;
  multiBrowser = false;
  multiBrowserRetry: Map<string, number> = new Map<string, number>();

  constructor(options: { aioConfig?: AioConfig } = {}) {
    this.customOption = options;
  }

  onBegin(config: FullConfig, suite: Suite) {
    for (const project of config.projects) {
      this.multiBrowserRetry.set(project.name, project.retries);
    }
    if (AioReporter.start) {
      AioTestsLogger.logStartEnd("AIO Tests Playwright Reporter - Reporting results - test 2");
      AioReporter.start = false;
    }
    if (this.customOption.aioConfig == null || this.customOption.aioConfig == undefined) {
      AioTestsLogger.error("AIO config is not defined.");
      return;
    }
    this.aioConfig = validateAIOConfig(this.customOption.aioConfig, true);
    if (!this.aioConfig) {
      return;
    }
    if (suite.entries().length > 1) {
      this.multiBrowser = true;
    }
  }

  onTestBegin(test: TestCase) {}

  onTestEnd(test: TestCase, result: TestResult) {
    // @ts-ignore
    if(!this.aioConfig?.createNewRunForRetries && result.status != 'passed' && result.retry < this.multiBrowserRetry.get(test._projectId)! )
      return;
    let pattern = new RegExp("\\w+-TC-\\d+", "gi");
    let match;
    test.tags.forEach((tag) => {
      do {
        match = pattern.exec(tag);
        if (match) {
          this.testSummary.push({ test: test, result: result });
          break;
        }
      } while (match != null);
    });
  }

  onEnd(result: FullResult) {}

  async onExit(): Promise<void> {
    if (this.aioConfig) {
      await reportTestResults(this.aioConfig, this.testSummary, this.multiBrowser);
    }
    if (AioReporter.end) {
      AioTestsLogger.logStartEnd("AIO Tests Playwright Reporter - Reporting results completed");
      AioReporter.end = false;
    }
    return Promise.resolve();
  }

  onError(error: TestError): void {
    AioTestsLogger.error(error.message || "Playwright error occurred.");
  }
}
export default AioReporter;
