#!/usr/bin/env node
import assert from 'assert';
import fs from 'fs';
import os from 'os';
import path from 'path';
import { createAutoTestPipelineTool, buildPreviewCacheKey, buildWorkspaceFingerprint, buildPromptCacheKey, buildParseCacheKey, buildGeneratedCasesCacheKey, buildPageVisibilityCacheKey } from './src/tools/autotest-pipeline.js';
import { WorkflowBuilder } from './src/tools/autotest/workflow-builder.js';
import { TestRunner } from './src/tools/autotest/test-runner.js';
import { WorkflowExecutor } from './src/vl/workflow-executor.js';

console.log('\n── AutoTest Generate Cache ──');

const workDir = fs.mkdtempSync(path.join(os.tmpdir(), 'vlcode-autotest-cache-'));
const vlDir = path.join(workDir, '.vl-code');
fs.mkdirSync(vlDir, { recursive: true });

const baseUrl = 'https://example.test/app';
const projectContext = {
  getAllFiles() {
    return [];
  },
};

fs.writeFileSync(path.join(vlDir, 'project.json'), JSON.stringify({
  previewUrls: { App: baseUrl },
}, null, 2));
fs.writeFileSync(path.join(vlDir, 'last-compile.json'), JSON.stringify({
  gid: 4242,
  timestamp: '2026-03-15T16:00:00.000Z',
  previewUrls: { App: baseUrl },
}, null, 2));

const metadata = { apps: [], sections: [], components: [], services: [], databases: [] };
const navElements = [];
const plan = {
  appName: 'App',
  appId: 'App',
  homePage: '/',
  pages: [{ path: '/', name: 'Home', navPath: [] }],
  criticalPaths: [],
};
const target = WorkflowBuilder.planCaseGenerationTargets(plan, 4)[0];
const cachedCases = [{
  id: 'WF_001',
  name: 'Cached Smoke',
  priority: 'P0',
  page: '/',
  _generationTargetId: target.id,
  steps: [
    { action: 'navigate', selector: baseUrl },
    { action: 'assert_visible', selector: 'text=Home' },
  ],
}];

const workspaceFingerprint = buildWorkspaceFingerprint(projectContext);
const previewCacheKey = buildPreviewCacheKey(workDir, baseUrl);
const promptCacheKey = buildPromptCacheKey({ appId: 'App', workspaceFingerprint, appMeta: metadata, navElements });
const parseCacheKey = buildParseCacheKey({ appId: 'App', workspaceFingerprint, appMeta: metadata, navElements });
const casesCacheKey = buildGeneratedCasesCacheKey({
  appId: 'App',
  workspaceFingerprint,
  appMeta: metadata,
  baseUrl,
  navElements,
  target,
  workDir,
});
const visibilityCacheKey = buildPageVisibilityCacheKey({
  previewCacheKey,
  appId: 'App',
  testPlan: plan,
});

fs.writeFileSync(path.join(vlDir, 'autotest-cache.json'), JSON.stringify({
  version: 1,
  navDiscovery: {
    [previewCacheKey]: { updatedAt: '2026-03-15T16:00:00.000Z', lastUsedAt: Date.now(), value: navElements },
  },
  pageVisibility: {
    [visibilityCacheKey]: { updatedAt: '2026-03-15T16:00:00.000Z', lastUsedAt: Date.now(), value: { '/': { visibleIds: [] } } },
  },
  promptFragments: {
    [promptCacheKey]: { updatedAt: '2026-03-15T16:00:00.000Z', lastUsedAt: Date.now(), value: 'cached metadata context' },
  },
  parsedPlans: {
    [parseCacheKey]: { updatedAt: '2026-03-15T16:00:00.000Z', lastUsedAt: Date.now(), value: plan },
  },
  generatedCases: {
    [casesCacheKey]: { updatedAt: '2026-03-15T16:00:00.000Z', lastUsedAt: Date.now(), value: cachedCases },
  },
}, null, 2));

const originalDiscoverNav = TestRunner.discoverNavElementsOnce;
const originalLaunch = TestRunner.prototype.launch;
const originalExecute = WorkflowExecutor.prototype.execute;

TestRunner.discoverNavElementsOnce = async () => {
  throw new Error('nav discovery should not run on cache hit');
};
TestRunner.prototype.launch = async function launchShouldNotRun() {
  throw new Error('browser launch should not run on cache hit');
};
WorkflowExecutor.prototype.execute = async function executeShouldNotRun() {
  throw new Error('workflow execution should not run on cache hit');
};

try {
  const tool = createAutoTestPipelineTool(
    {
      workDir,
      autotest: { useWorkflowEngine: true, maxCases: 4 },
      llmProvider: 'cli',
      cliAvailable: true,
      model: 'claude-opus-4-6',
    },
    projectContext
  );

  const result = await tool.execute({ action: 'generate', baseUrl, maxCases: 4 });
  assert.match(result.result, /Generated 1 test cases/);
  assert.equal(result.testCases.length, 1, 'cached generate should return cached cases');
  assert.equal(result.testCases[0].name, 'Cached Smoke');
} finally {
  TestRunner.discoverNavElementsOnce = originalDiscoverNav;
  TestRunner.prototype.launch = originalLaunch;
  WorkflowExecutor.prototype.execute = originalExecute;
  fs.rmSync(workDir, { recursive: true, force: true });
}

console.log('PASS test-autotest-generate-cache.js');
