import fs from "fs";
import path from "path";
import { Command, Flags } from "@oclif/core";
import { discoverTests } from "../../discovery/index.mjs";
import { resolveProductDir } from "../../config/index.mjs";
import { buildDiscoveryReportLines } from "../presentation/discovery-reporter.mjs";
import { resolveRequestedFiles } from "../args.mjs";
import { sharedFlags } from "../command-helpers.mjs";

export default class DiscoverCommand extends Command {
  static summary = "Discover managed tests and report their metadata";

  static enableJsonFlag = true;

  static flags = {
    ...sharedFlags,
    type: Flags.string({
      char: "t",
      multiple: true,
      description: "Filter by suite type(s): int, e2e, scenario, dal, load, pw, all",
    }),
    suite: Flags.string({
      char: "s",
      multiple: true,
      description: "Filter by suite selector(s)",
    }),
    file: Flags.string({
      char: "f",
      multiple: true,
      description: "Filter by exact file path(s)",
    }),
    "runnable-only": Flags.boolean({
      description: "Show only files not skipped by repo rules",
      default: false,
    }),
    strict: Flags.boolean({
      description: "Fail instead of reporting discovery/config diagnostics",
      default: false,
    }),
    output: Flags.string({
      description: "Write machine-readable discovery JSON to a file",
    }),
    "output-mode": Flags.string({
      description: "Human-readable output mode",
      options: ["compact", "verbose"],
      default: "compact",
    }),
  };

  async run() {
    const { flags } = await this.parse(DiscoverCommand);
    const productDir = resolveProductDir(process.cwd(), flags.dir);
    const fileNames = resolveRequestedFiles(flags.file || [], productDir, process.cwd());
    const result = await discoverTests({
      dir: productDir,
      service: flags.service || null,
      type: flags.type || [],
      suite: flags.suite || [],
      file: fileNames,
      runnableOnly: flags["runnable-only"],
      diagnostics: flags.strict ? "error" : "report",
    });
    let outputLabel = null;
    if (flags.output) {
      const outputPath = path.resolve(productDir, flags.output);
      fs.mkdirSync(path.dirname(outputPath), { recursive: true });
      fs.writeFileSync(outputPath, `${JSON.stringify(result, null, 2)}\n`);
      outputLabel = path.relative(productDir, outputPath) || path.basename(outputPath);
    }

    if (!this.jsonEnabled()) {
      for (const line of buildDiscoveryReportLines(result, { outputMode: flags["output-mode"] })) {
        this.log(line);
      }
      if (outputLabel) this.log(`Wrote ${outputLabel}`);
    }

    return result;
  }
}
