import { BaseSymbolType, InterpreterError, LexerError, ParserError, Lexer, Parser, Config, Interpreter, ColorSymbol, ColorManager, isArray, isObject, NumberWithUnitSymbol } from './chunk-OCQX3WYJ.js';
import './chunk-LZTXD3LN.js';
import fs from 'fs';
import path from 'path';

// src/interpreter/utils/coll.ts
function groupBy(f, coll) {
  const result = {};
  for (const item of coll) {
    const key = f(item);
    if (key in result) {
      result[key].push(item);
    } else {
      result[key] = [item];
    }
  }
  return result;
}

// src/compliance-suite.ts
var SCHEMA_FILE_MAP = {
  "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/hsl-color/0/": "./data/specifications/colors/hsl.json",
  "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/srgb-color/0/": "./data/specifications/colors/srgb.json",
  "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/rgb-color/0/": "./data/specifications/colors/rgb.json",
  "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/lrgb-color/0/": "./data/specifications/colors/lrgb.json"
};
function loadSchemas(schemas) {
  const colorManager = new ColorManager();
  for (const schemaUri of schemas) {
    const filePath = SCHEMA_FILE_MAP[schemaUri];
    if (filePath && fs.existsSync(filePath)) {
      try {
        const specData = fs.readFileSync(filePath, "utf-8");
        colorManager.register(schemaUri, specData);
      } catch (error) {
        console.warn(`Failed to load schema ${schemaUri} from ${filePath}:`, error);
      }
    } else {
      console.warn(`No file mapping found for schema: ${schemaUri}`);
    }
  }
  return colorManager;
}
function readJsonFilesRecursively(dir) {
  let results = [];
  const list = fs.readdirSync(dir);
  list.forEach((file) => {
    const filePath = path.join(dir, file);
    const stat = fs.statSync(filePath);
    if (stat?.isDirectory()) {
      results = results.concat(readJsonFilesRecursively(filePath));
    } else if (file.endsWith(".json")) {
      results.push(filePath);
    }
  });
  return results;
}
var parseTestCasesJson = (json, filePath) => {
  try {
    const testCases = JSON.parse(json);
    return !Array.isArray(testCases) ? [testCases] : testCases;
  } catch (_e) {
    throw new Error(`Could not parse json at path: ${filePath}`);
  }
};
function normalizeContextObject(obj, config, fns) {
  for (const rule of fns) {
    const transformed = rule(obj, config);
    if (typeof transformed !== "undefined") {
      return transformed;
    }
  }
  if (isArray(obj)) {
    return obj.map((el) => normalizeContextObject(el, config, fns));
  }
  if (isObject(obj)) {
    const out = {};
    for (const [k, v] of Object.entries(obj)) {
      out[k] = normalizeContextObject(v, config, fns);
    }
    return out;
  }
  return obj;
}
function transformContextToSymbols(obj, config) {
  return normalizeContextObject(obj, config, [
    (val, config2) => {
      if (isObject(val) && val.type === "NumberWithUnit") {
        const numberVal = val;
        return new NumberWithUnitSymbol(numberVal.value ?? null, numberVal.unit, config2);
      }
    }
  ]);
}
var runTest = (test) => {
  const lexer = new Lexer(test.input);
  const parser = new Parser(lexer);
  const ast = parser.parse(test.inline);
  let config;
  if (test.schemas && test.schemas.length > 0) {
    const colorManager = loadSchemas(test.schemas);
    config = new Config({ colorManager });
  } else {
    config = new Config();
  }
  const references = test.context ? transformContextToSymbols(test.context, config) : {};
  const interpreter = new Interpreter(ast, { references, config });
  return {
    interpreter,
    result: interpreter.interpret()
  };
};
var interpreterSymbolToComplianceResult = (symbol, interpreter) => {
  if (symbol instanceof ColorSymbol) {
    return {
      actualOutput: interpreter.config.colorManager.formatColorMethod(symbol),
      actualOutputType: symbol.getTypeName()
    };
  }
  return {
    actualOutput: symbol.toString(),
    actualOutputType: symbol.getTypeName()
  };
};
var compareResults = (complianceResult, testCase) => {
  const typeMatches = complianceResult.actualOutputType === testCase.expectedOutputType;
  if (testCase.expectedErrorCode) {
    return typeMatches && complianceResult.actualErrorCode === testCase.expectedErrorCode ? "passed" : "failed";
  }
  return typeMatches && complianceResult.actualOutput === testCase.expectedOutput ? "passed" : "failed";
};
async function evaluateStandardCompliance(config) {
  const files = config.file ? [config.file] : config.dir ? readJsonFilesRecursively(config.dir) : [];
  const testResults = files.flatMap((path2) => {
    const content = fs.readFileSync(path2, "utf-8");
    const testCases = parseTestCasesJson(content, path2);
    return testCases.map((testCase) => {
      let testResult;
      try {
        const { result, interpreter } = runTest(testCase);
        if (!(result instanceof BaseSymbolType)) {
          throw new Error(`result (${result}) in s not interpreter Symbol`);
        }
        const complianceResult = interpreterSymbolToComplianceResult(result, interpreter);
        testResult = {
          ...testCase,
          ...complianceResult,
          path: path2,
          status: compareResults(complianceResult, testCase)
        };
      } catch (e) {
        if (e instanceof InterpreterError || e instanceof LexerError || e instanceof ParserError) {
          const complianceResult = {
            actualOutput: e.originalMessage || "",
            actualOutputType: "Error",
            actualErrorCode: e.code
          };
          return {
            ...testCase,
            ...complianceResult,
            path: path2,
            status: compareResults(complianceResult, testCase),
            error: e
          };
        }
        throw e;
      }
      return {
        ...testCase,
        ...testResult,
        status: "passed",
        path: path2
      };
    });
  });
  const { passed = [], failed = [] } = groupBy((x) => x.status, testResults);
  const orderedResults = testResults.map(
    ({
      name,
      input,
      inline,
      context,
      path: path2,
      status,
      actualOutput,
      actualOutputType,
      actualErrorCode,
      expectedOutput,
      expectedOutputType,
      expectedErrorCode,
      ...rest
    }) => ({
      name,
      path: path2,
      status,
      inline,
      context,
      input,
      actualOutput,
      actualOutputType,
      ...actualErrorCode ? { actualErrorCode } : {},
      expectedOutput,
      expectedOutputType,
      ...expectedErrorCode ? { expectedErrorCode } : {},
      ...rest
    })
  );
  const report = {
    passed: passed.length,
    failed: failed.length,
    results: orderedResults
  };
  if (config.output) {
    fs.writeFileSync(config.output, JSON.stringify(report, null, 2), "utf-8");
  }
  return report;
}

export { evaluateStandardCompliance };
//# sourceMappingURL=compliance-suite.js.map
//# sourceMappingURL=compliance-suite.js.map