import { SimpleRalphPlugin } from "../simple-ralph-plugin.js";
import * as fs from "fs/promises";
import * as path from "path";
import { execSync } from "child_process";
class TestGenerator {
  ralphPlugin;
  constructor(ralphPlugin) {
    this.ralphPlugin = ralphPlugin;
  }
  /**
   * Generate tests iteratively until coverage target is met
   */
  async generateTests(request) {
    const coverageTarget = request.coverageTarget || 80;
    const task = {
      id: `testgen-${Date.now()}`,
      description: `Generate ${request.framework} tests for ${request.targetFile}`,
      acceptanceCriteria: [
        "All tests pass",
        `Test coverage >= ${coverageTarget}%`,
        "No test duplication",
        "Tests are maintainable and clear"
      ],
      maxIterations: 7
    };
    if (request.includeEdgeCases) {
      task.acceptanceCriteria.push("Edge cases covered");
      task.acceptanceCriteria.push("Error conditions tested");
    }
    if (request.includeIntegrationTests) {
      task.acceptanceCriteria.push("Integration tests included");
    }
    const result = await this.ralphPlugin.runTask(task);
    const analysis = await this.analyzeGeneratedTests(request.targetFile, request.framework);
    return {
      testFiles: analysis.files,
      coverage: analysis.coverage,
      testCount: analysis.testCount,
      passRate: analysis.passRate,
      iterations: result.iterations
    };
  }
  /**
   * Analyze generated tests
   */
  async analyzeGeneratedTests(targetFile, framework) {
    const analysis = {
      files: [],
      coverage: 0,
      testCount: 0,
      passRate: 0
    };
    try {
      const testDir = path.dirname(targetFile);
      const baseName = path.basename(targetFile, path.extname(targetFile));
      const testPatterns = [
        `${baseName}.test.*`,
        `${baseName}.spec.*`,
        `test_${baseName}.*`,
        `${baseName}_test.*`
      ];
      for (const pattern of testPatterns) {
        const files = await this.findFiles(testDir, pattern);
        analysis.files.push(...files);
      }
      analysis.coverage = await this.runCoverageAnalysis(framework);
      const testResults = await this.runTests(framework);
      analysis.testCount = testResults.total;
      analysis.passRate = testResults.passed / testResults.total * 100;
    } catch (error) {
      console.error("Error analyzing tests:", error);
    }
    return analysis;
  }
  /**
   * Find files matching pattern
   */
  async findFiles(dir, pattern) {
    const files = [];
    try {
      const entries = await fs.readdir(dir);
      for (const entry of entries) {
        if (this.matchesPattern(entry, pattern)) {
          files.push(path.join(dir, entry));
        }
      }
    } catch (error) {
      console.error("Error finding files:", error);
    }
    return files;
  }
  /**
   * Simple pattern matching
   */
  matchesPattern(filename, pattern) {
    const regex = new RegExp(pattern.replace(/\*/g, ".*"));
    return regex.test(filename);
  }
  /**
   * Run coverage analysis
   */
  async runCoverageAnalysis(framework) {
    try {
      let command = "";
      switch (framework) {
        case "jest":
          command = "npx jest --coverage --silent";
          break;
        case "vitest":
          command = "npx vitest run --coverage --silent";
          break;
        case "mocha":
          command = "npx nyc mocha";
          break;
        case "pytest":
          command = "pytest --cov --cov-report=json";
          break;
      }
      if (command) {
        const output = execSync(command, { encoding: "utf-8", stdio: "pipe" });
        const match = output.match(/(\d+(?:\.\d+)?)\s*%/);
        if (match) {
          return parseFloat(match[1]);
        }
      }
    } catch (error) {
      console.error("Coverage analysis failed:", error);
    }
    return 0;
  }
  /**
   * Run tests and get results
   */
  async runTests(framework) {
    try {
      let command = "";
      switch (framework) {
        case "jest":
          command = "npx jest --json";
          break;
        case "vitest":
          command = "npx vitest run --reporter=json";
          break;
        case "mocha":
          command = "npx mocha --reporter json";
          break;
        case "pytest":
          command = "pytest --json-report";
          break;
      }
      if (command) {
        const output = execSync(command, { encoding: "utf-8", stdio: "pipe" });
        try {
          const json = JSON.parse(output);
          return {
            total: json.numTotalTests || json.tests || 0,
            passed: json.numPassedTests || json.passes || 0
          };
        } catch {
          const totalMatch = output.match(/(\d+)\s+tests?/i);
          const passedMatch = output.match(/(\d+)\s+pass/i);
          return {
            total: totalMatch ? parseInt(totalMatch[1]) : 0,
            passed: passedMatch ? parseInt(passedMatch[1]) : 0
          };
        }
      }
    } catch (error) {
      console.error("Test execution failed:", error);
    }
    return { total: 0, passed: 0 };
  }
}
async function generateTestsForModule() {
  const ralphPlugin = new SimpleRalphPlugin();
  await ralphPlugin.initialize({
    eventBus: {},
    config: { name: "simple-ralph", version: "2.0.0", enabled: true },
    dataDir: ".ralph",
    getRepository: () => null,
    registerRepository: () => {
    }
  });
  const generator = new TestGenerator(ralphPlugin);
  const result = await generator.generateTests({
    targetFile: "./src/utils/validator.ts",
    framework: "jest",
    coverageTarget: 90,
    includeEdgeCases: true,
    includeIntegrationTests: false,
    mockStrategy: "partial"
  });
  console.log(`Generated ${result.testCount} tests with ${result.coverage}% coverage`);
  console.log(`Pass rate: ${result.passRate}%`);
  console.log(`Completed in ${result.iterations} iterations`);
}
export {
  TestGenerator,
  generateTestsForModule
};
//# sourceMappingURL=test-generator.js.map
