import { expect, test } from "vitest";
import { createProject as typescriptProject, ts, } from "@ts-morph/bootstrap";
import { createRuntimeFile } from "./create-runtime.js";
import fs from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "url";
import { defaultCompilerOptions } from "../compiler-options.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const superStrictRuleOutAnyErrorTsSettings = {
    outDir: "dist",
    declaration: true,
    allowJs: true,
    checkJs: true,
    noImplicitAny: true,
    noUnusedLocals: true,
    noUnusedParameters: true,
    noImplicitReturns: true,
    noImplicitThis: true,
    noUncheckedIndexedAccess: true,
    noPropertyAccessFromIndexSignature: true,
    module: ts.ModuleKind.Node16,
    strict: true,
};
test("createRuntimeFile throws if urlPatterns contains an unknown locale", () => {
    expect(() => createRuntimeFile({
        baseLocale: "en",
        locales: ["en", "de"],
        compilerOptions: {
            ...defaultCompilerOptions,
            urlPatterns: [
                {
                    pattern: "https://example.com/:path*",
                    localized: [["fr", "https://example.com/fr/:path*"]],
                },
            ],
        },
    })).toThrow('Invalid locale "fr" in urlPatterns. It must be one of the locales defined in the "locales" array.');
});
test("cookie cache clearer remains internal in the generated runtime", () => {
    const jsdocRuntime = createRuntimeFile({
        baseLocale: "en",
        locales: ["en", "de"],
        compilerOptions: {
            ...defaultCompilerOptions,
            strategy: ["cookie", "baseLocale"],
        },
    });
    expect(jsdocRuntime).toContain("function clearLocaleCookieCache");
    expect(jsdocRuntime).not.toContain("export function clearLocaleCookieCache");
});
test("runtime type", async () => {
    const project = await typescriptProject({
        useInMemoryFileSystem: true,
        compilerOptions: superStrictRuleOutAnyErrorTsSettings,
    });
    const jsdocRuntime = createRuntimeFile({
        baseLocale: "en",
        locales: ["en"],
        compilerOptions: defaultCompilerOptions,
    }).replace('import * as pathToRegexp from "@inlang/paraglide-js/path-to-regexp";', "");
    const file = (path) => {
        return [path, fs.readFileSync(resolve(__dirname, path), "utf-8")];
    };
    project.createSourceFile("./runtime.js", jsdocRuntime);
    project.createSourceFile(...file("./type.ts"));
    project.createSourceFile(...file("./ambient.d.ts"));
    // add the imports for the types in the runtime type
    for (const name of fs.readdirSync(__dirname)) {
        if (name.endsWith(".js")) {
            project.createSourceFile(...file(name));
        }
    }
    project.createSourceFile("./test.ts", `
    import * as runtime from "./runtime.js"
    import type { Runtime } from "./type.js"

    runtime satisfies Runtime

		// getLocale() should return type should be a union of language tags, not a generic string
    runtime.getLocale() satisfies "de" | "en" | "en-US"

    // locales should have a narrow type, not a generic string
    runtime.locales satisfies Readonly<Array<"de" | "en" | "en-US">>

    // setLocale() should fail if the given language tag is not included in locales
    // @ts-expect-error - invalid locale
    runtime.setLocale("fr")

    // setLocale() should not fail if the given language tag is included in locales
    runtime.setLocale("de")

		// getTextDirection() should return a strict direction union
		runtime.getTextDirection() satisfies "ltr" | "rtl"

		// isLocale should narrow the type of it's argument
		const thing = 5;

		let a: "de" | "en" | "en-US";

		if(runtime.isLocale(thing)) {
			a = thing
		} else {
			// @ts-expect-error - thing is not a language tag
			a = thing
		}

		// to make ts not complain about unused variables
		runtime.toLocale("EN") satisfies "de" | "en" | "en-US" | undefined
		runtime.toLocale(123) satisfies "de" | "en" | "en-US" | undefined

		console.log(a)
    `);
    const program = project.createProgram();
    const diagnostics = ts
        .getPreEmitDiagnostics(program)
        // ignore 'export' modifier cannot be applied to ambient modules and module augmentations since they are always visible. /ambient.d.ts
        .filter((d) => d.code !== 2668)
        .filter((d) => d.messageText.toString().includes("path-to-regexp"));
    for (const diagnostic of diagnostics) {
        console.error(diagnostic.messageText, diagnostic.file?.fileName);
    }
    expect(diagnostics.length).toEqual(0);
});
//# sourceMappingURL=type.test.js.map