import { parse as yamlParse } from "yaml";
import type { ParseOptions, DocumentOptions, SchemaOptions, ToJSOptions, ScalarTag } from "yaml";
import { readTextFile } from "./utils.ts";

// Custom YAML tags that resolve `!inline value` and `!inline_fileset value`
// back to their string-prefix form ("!inline value").
// Without these, the yaml parser strips the tag and returns just the scalar,
// breaking the string-prefix-based !inline detection used throughout the CLI.
const inlineTag: ScalarTag = {
  tag: "!inline",
  resolve(value: string) {
    return "!inline " + value;
  },
};

const inlineFilesetTag: ScalarTag = {
  tag: "!inline_fileset",
  resolve(value: string) {
    return "!inline_fileset " + value;
  },
};

const WINDMILL_CUSTOM_TAGS: ScalarTag[] = [inlineTag, inlineFilesetTag];

type YamlParseOptions = ParseOptions & DocumentOptions & SchemaOptions & ToJSOptions;

export async function yamlParseFile(path: string, options: YamlParseOptions = {}) {
  try {
    return yamlParse(await readTextFile(path), {
      ...options,
      customTags: [...WINDMILL_CUSTOM_TAGS, ...((options.customTags as ScalarTag[] | undefined) ?? [])],
    });
  } catch (e) {
    throw new Error(`Error parsing yaml ${path}`, { cause: e });
  }
}

export function yamlParseContent(
  path: string,
  content: string,
  options: YamlParseOptions = {},
) {
  try {
    return yamlParse(content, {
      ...options,
      customTags: [...WINDMILL_CUSTOM_TAGS, ...((options.customTags as ScalarTag[] | undefined) ?? [])],
    });
  } catch (e) {
    throw new Error(`Error parsing yaml ${path}`, { cause: e });
  }
}
