/**
 * VL Meta-Driven Test Tool
 *
 * Generates test skeletons deterministically from ProjectMeta/1.0.
 * No LLM needed for skeleton generation — all structure is derived from metadata.
 *
 * Actions:
 *   generate  — create test skeletons from ProjectMeta (deterministic, no LLM)
 *   save      — persist generated skeletons to .vl-code/test-skeletons/
 *
 * Workflow:
 *   1. VLMetaTest {action:"generate"} → get testCases array
 *   2. Inspect each skeleton, update [SKELETON] selectors via VLComponentTest listIds
 *   3. VLMetaTest {action:"save", test_cases:[...]} → write to disk
 *   4. Run with VLComponentTest {action:"run", steps:[...]}
 */
import fs from 'fs/promises';
import path from 'path';
import { generateTestSkeleton } from '../vl/meta-test-generator.js';

export function createVLMetaTestTool(config) {
  return {
    description: 'Generate deterministic test skeletons from ProjectMeta. Derives smoke tests, navigation tests, and CRUD workflow tests for all apps/sections/services — no LLM required. Use generate to create, save to persist to .vl-code/test-skeletons/.',
    parameters: {
      type: 'object',
      properties: {
        action: {
          type: 'string',
          enum: ['generate', 'save'],
          description: 'generate: create test skeletons from ProjectMeta. save: write test_cases to .vl-code/test-skeletons/',
        },
        meta: {
          type: 'object',
          description: 'ProjectMeta object. If omitted, auto-loads from .vl-code/ProjectMeta.json',
        },
        preview_urls: {
          type: 'object',
          description: 'Map of { AppId: "https://preview-url" }. If omitted, reads from .vl-code/project.json previewUrls',
        },
        test_cases: {
          type: 'array',
          description: 'For save action: the testCases array returned by a previous generate call',
          items: { type: 'object' },
        },
        filename: {
          type: 'string',
          description: 'For save action: output filename (default: test-skeletons.json)',
        },
      },
      required: ['action'],
    },
    execute: async (input) => {
      try {
        switch (input.action) {
          case 'generate': {
            // Load ProjectMeta
            let meta = input.meta;
            if (!meta) {
              const metaPath = path.join(config.workDir, '.vl-code', 'ProjectMeta.json');
              try {
                meta = JSON.parse(await fs.readFile(metaPath, 'utf-8'));
              } catch {
                return { error: 'Could not read .vl-code/ProjectMeta.json — run VLMetadata first to generate it.' };
              }
            }

            // Load preview URLs
            let previewUrls = input.preview_urls || {};
            if (!Object.keys(previewUrls).length) {
              try {
                const profilePath = path.join(config.workDir, '.vl-code', 'project.json');
                const profile = JSON.parse(await fs.readFile(profilePath, 'utf-8'));
                previewUrls = profile.previewUrls || {};
              } catch {}
            }

            // Pass interactiveElements from meta.sections for instance-id based selectors
            const { testCases, summary } = generateTestSkeleton(meta, previewUrls, {
              interactiveElements: meta.sections || [],
            });

            const noUrls = summary.appsWithUrls.length === 0;
            const report = [
              `Generated ${summary.totalTests} test skeletons for "${summary.projectName}"`,
              `  Smoke: ${summary.byCategory.smoke} | Navigation: ${summary.byCategory.navigation} | CRUD: ${summary.byCategory.crud}`,
              `  P0: ${summary.byPriority.P0} | P1: ${summary.byPriority.P1}`,
              noUrls
                ? '  WARNING: No preview URLs found — add previewUrls to .vl-code/project.json or pass preview_urls param'
                : `  Apps: ${summary.appsWithUrls.join(', ')}`,
              '',
              'Next steps:',
              ...summary.instructions.map(i => `  ${i}`),
            ].join('\n');

            return { result: report, testCases, summary };
          }

          case 'save': {
            const cases = input.test_cases;
            if (!Array.isArray(cases) || cases.length === 0) {
              return { error: 'test_cases array required for save action — pass the testCases from a generate call.' };
            }

            const outDir = path.join(config.workDir, '.vl-code', 'test-skeletons');
            await fs.mkdir(outDir, { recursive: true });

            const rawName = input.filename || 'test-skeletons.json';
            const fname = rawName.replace(/[^a-zA-Z0-9_.-]/g, '_');
            const outPath = path.join(outDir, fname);

            const payload = {
              generatedAt: new Date().toISOString(),
              totalCases: cases.length,
              testCases: cases,
            };
            await fs.writeFile(outPath, JSON.stringify(payload, null, 2), 'utf-8');

            return { result: `Saved ${cases.length} test skeletons → .vl-code/test-skeletons/${fname}` };
          }

          default:
            return { error: `Unknown action: ${input.action}` };
        }
      } catch (err) {
        return { error: err.message };
      }
    },
  };
}
