import { test, expect } from "vitest";
import { createParaglide } from "../create-paraglide.js";
import { newProject } from "@inlang/sdk";
test("pathname based localization", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            // literal match
            {
                pattern: "/blog/about",
                localized: [
                    ["en", "/blog/about"],
                    ["de", "/de/artikel/ueber-uns"],
                ],
            },
            // parameter
            {
                pattern: "/blog/:id",
                localized: [
                    ["en", "/blog/:id"],
                    ["de", "/de/artikel/:id"],
                ],
            },
            // wildcard
            {
                pattern: "/:path(.*)",
                localized: [
                    ["de", "/de/:path(.*)"],
                    ["en", "/:path(.*)"],
                ],
            },
        ],
    });
    // wildcard - en to de
    expect(runtime.localizeUrl("https://example.com/home", { locale: "de" }).href).toBe("https://example.com/de/home");
    // wildcard - de to en
    expect(runtime.localizeUrl("https://example.com/de/home", { locale: "en" }).href).toBe("https://example.com/home");
    // wildcard - en to en
    expect(runtime.localizeUrl("https://example.com/about", { locale: "en" }).href).toBe("https://example.com/about");
    // wildcard - delocalizing de
    expect(runtime.deLocalizeUrl("https://example.com/de/about").href).toBe("https://example.com/about");
    // literal match
    expect(runtime.localizeUrl("https://example.com/blog/about", { locale: "de" }).href).toBe("https://example.com/de/artikel/ueber-uns");
    expect(runtime.deLocalizeUrl("https://example.com/de/artikel/ueber-uns").href).toBe("https://example.com/blog/about");
    // parameter matching
    expect(runtime.localizeUrl("https://example.com/blog/56", { locale: "de" }).href).toBe("https://example.com/de/artikel/56");
    expect(runtime.deLocalizeUrl("https://example.com/de/artikel/56").href).toBe("https://example.com/blog/56");
});
test("cross domain urls", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            // Development/deployment mapping
            {
                pattern: "https://localhost::port/:path*",
                localized: [
                    ["de", "https://localhost::port/de/:path*"],
                    ["en", "https://localhost::port/:path*"],
                ],
            },
            // Domain based localization
            {
                pattern: "https://example.com/:path*",
                localized: [
                    ["en", "https://example.com/:path*"],
                    ["de", "https://de.example.com/:path*"],
                ],
            },
        ],
    });
    // in development use localhost with different mapping
    expect(runtime.localizeUrl("https://localhost:5173/about", { locale: "de" }).href).toBe("https://localhost:5173/de/about");
    expect(runtime.localizeUrl("https://localhost:5173/about", { locale: "en" }).href).toBe("https://localhost:5173/about");
    expect(runtime.deLocalizeUrl("https://localhost:5173/de/about").href).toBe("https://localhost:5173/about");
    // DE routing
    expect(runtime.localizeUrl("https://de.example.com/about", { locale: "de" }).href).toBe("https://de.example.com/about");
    expect(runtime.localizeUrl("https://de.example.com/about", { locale: "en" }).href).toBe("https://example.com/about");
    // delocalizing
    expect(runtime.deLocalizeUrl("https://de.example.com/about").href).toBe("https://example.com/about");
    // EN routing
    expect(runtime.localizeUrl("https://example.com/about", { locale: "de" }).href).toBe("https://de.example.com/about");
    expect(runtime.localizeUrl("https://example.com/about", { locale: "en" }).href).toBe("https://example.com/about");
    // delocalizing
    expect(runtime.deLocalizeUrl("https://example.com/about").href).toBe("https://example.com/about");
});
test("multi tenancy", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de", "fr"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            // 1) customer1.fr => root path locale is fr, other locales via sub-path e.g. /en/
            {
                pattern: "https://customer1.fr/:path*",
                localized: [
                    ["en", "https://customer1.fr/en/:path*"],
                    ["fr", "https://customer1.fr/:path*"],
                ],
            },
            // 2) customer2.com => root path locale is en, other locales via sub-path e.g. /fr/
            {
                pattern: "https://customer2.com/:path*",
                localized: [
                    ["fr", "https://customer2.com/fr/:path*"],
                    ["en", "https://customer2.com/:path*"],
                ],
            },
            // 3) Any other domain => path-based for en/fr
            {
                pattern: "https://:domain(.*)/:path*",
                localized: [
                    ["en", "https://:domain(.*)/en/:path*"],
                    ["fr", "https://:domain(.*)/fr/:path*"],
                ],
            },
        ],
    });
    // customer 1 - localizing french to french
    expect(runtime.localizeUrl("https://customer1.fr/about", { locale: "fr" }).href).toBe("https://customer1.fr/about");
    // customer 1 - localizing from french to english
    expect(runtime.localizeUrl("https://customer1.fr/about", { locale: "en" }).href).toBe("https://customer1.fr/en/about");
    // customer 1 - de-localizing french
    expect(runtime.deLocalizeUrl("https://customer1.fr/en/about").href).toBe("https://customer1.fr/about");
    // customer 2 - english to english
    expect(runtime.localizeUrl("https://customer2.com/about", { locale: "en" }).href).toBe("https://customer2.com/about");
    // customer 2 - english to french
    expect(runtime.localizeUrl("https://customer2.com/about", { locale: "fr" }).href).toBe("https://customer2.com/fr/about");
    // customer 2 - de-localize french
    expect(runtime.deLocalizeUrl("https://customer2.com/fr/about").href).toBe("https://customer2.com/about");
});
test("providing a URL object as input", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "https://:domain(.*)/:path*",
                localized: [
                    ["en", "https://:domain(.*)/:path*"],
                    ["de", "https://de.:domain(.*)/:path*"],
                ],
            },
        ],
    });
    const url = new URL("https://example.com/about");
    expect(runtime.localizeUrl(url, { locale: "de" }).href).toBe("https://de.example.com/about");
    expect(runtime.deLocalizeUrl(url).href).toBe("https://example.com/about");
});
test("localhost with portname", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: ":protocol://:domain(.*)::port?/:path(.*)?",
                localized: [
                    ["de", ":protocol://:domain(.*)::port?/de/:path(.*)?"],
                    ["en", ":protocol://:domain(.*)::port?/:path(.*)?"],
                ],
            },
        ],
    });
    // http
    expect(runtime.deLocalizeUrl(new URL("http://localhost:5173/de/about")).href).toBe("http://localhost:5173/about");
    // https
    expect(runtime.deLocalizeUrl(new URL("https://localhost:5173/de/about")).href).toBe("https://localhost:5173/about");
    // no port
    expect(runtime.deLocalizeUrl(new URL("https://localhost/de/about")).href).toBe("https://localhost/about");
    // pathnames
    expect(runtime.deLocalizeUrl(new URL("http://localhost:5173/about")).href).toBe("http://localhost:5173/about");
    expect(runtime.deLocalizeUrl(new URL("http://localhost:5173/")).href).toBe("http://localhost:5173/");
    expect(runtime.deLocalizeUrl(new URL("https://localhost:5173/de")).href).toBe("https://localhost:5173/");
});
test("it keeps the query parameters", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "https://:domain(.*)/:path(.*)?",
                localized: [
                    ["de", "https://:domain(.*)/de/:path(.*)?"],
                    ["en", "https://:domain(.*)/:path(.*)?"],
                ],
            },
        ],
    });
    expect(runtime.localizeUrl("https://example.com/about?foo=bar&baz=qux", {
        locale: "de",
    }).href).toBe("https://example.com/de/about?foo=bar&baz=qux");
    expect(runtime.deLocalizeUrl("https://example.com/de/about?foo=bar&baz=qux").href).toBe("https://example.com/about?foo=bar&baz=qux");
});
test("it keeps the url hash", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "https://:domain(.*)/:path(.*)?",
                localized: [
                    ["de", "https://:domain(.*)/de/:path(.*)?"],
                    ["en", "https://:domain(.*)/:path(.*)?"],
                ],
            },
        ],
    });
    expect(runtime.localizeUrl("https://example.com/about#test", { locale: "de" }).href).toBe("https://example.com/de/about#test");
    expect(runtime.deLocalizeUrl("https://example.com/de/about#test").href).toBe("https://example.com/about#test");
});
// URL Pattern implicitly matches all paths
//
// The pattern https://example.com is interpreted as https://example.com.*
// It effectively matches every path under https://example.com/
// This means any request, including https://example.com/about, will match.
test("it keeps the url path", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "https://example.com",
                localized: [
                    ["de", "https://example.de"],
                    ["en", "https://example.com"],
                ],
            },
        ],
    });
    expect(runtime.localizeUrl("https://example.com/about", { locale: "de" }).href).toBe("https://example.de/about");
    expect(runtime.deLocalizeUrl("https://example.de/about").href).toBe("https://example.com/about");
});
test("uses getLocale when no locale is provided", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "https://:domain(.*)/:path(.*)?",
                localized: [
                    ["de", "https://:domain(.*)/de/:path(.*)?"],
                    ["en", "https://:domain(.*)/en/:path(.*)?"],
                ],
            },
        ],
    });
    // Override getLocale to return German
    runtime.overwriteGetLocale(() => "de");
    expect(runtime.getLocale()).toBe("de");
    // Should use "de" from getLocale since no locale provided
    expect(runtime.localizeUrl("https://example.com/about").href).toBe("https://example.com/de/about");
    // Should still use explicit locale when provided
    expect(runtime.localizeUrl("https://example.com/about", { locale: "en" }).href).toBe("https://example.com/en/about");
});
test("normalizes mixed-case explicit locales for custom url patterns", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "https://:domain(.*)/:path(.*)?",
                localized: [
                    ["de", "https://:domain(.*)/de/:path(.*)?"],
                    ["en", "https://:domain(.*)/:path(.*)?"],
                ],
            },
        ],
    });
    expect(runtime.localizeUrl("https://example.com/about", {
        locale: "DE",
    }).href).toBe("https://example.com/de/about");
    expect(runtime.localizeUrl("https://example.com/de/about", {
        locale: "EN",
    }).href).toBe("https://example.com/about");
});
// https://github.com/opral/inlang-paraglide-js/issues/381
test.each([
    // empty url pattern will set TREE_SHAKE_DEFAULT_ULR_PATTERN_USED to true
    {},
    // real default url pattern to align behaviour
    {
        urlPatterns: [
            {
                pattern: ":protocol://:domain(.*)::port?/:path(.*)?",
                localized: [
                    ["de", ":protocol://:domain(.*)::port?/de/:path(.*)?"],
                    ["en", ":protocol://:domain(.*)::port?/:path(.*)?"],
                ],
            },
        ],
    },
])("default url pattern", async (compilerOptions) => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        ...compilerOptions,
    });
    runtime.overwriteGetLocale(() => "en");
    expect(runtime.localizeUrl("https://example.com/about").href).toBe("https://example.com/about");
    runtime.overwriteGetLocale(() => "de");
    expect(runtime.localizeUrl("https://example.com/").href).toBe("https://example.com/de/");
    expect(runtime.localizeUrl("https://example.com/about").href).toBe("https://example.com/de/about");
    // Should still use explicit locale when provided
    expect(runtime.localizeUrl("https://example.com/about", { locale: "de" }).href).toBe("https://example.com/de/about");
    expect(runtime.localizeUrl("https://example.com/about", {
        locale: "DE",
    }).href).toBe("https://example.com/de/about");
    expect(runtime.localizeUrl("https://example.com/about", { locale: "en" }).href).toBe("https://example.com/about");
    expect(runtime.localizeUrl("https://example.com/de/about", {
        locale: "EN",
    }).href).toBe("https://example.com/about");
    expect(runtime.deLocalizeUrl("https://example.com/de/about").href).toBe("https://example.com/about");
    expect(runtime.deLocalizeUrl("https://example.com/about").href).toBe("https://example.com/about");
});
test("auto fills the url base path", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "/:path(.*)?",
                localized: [
                    ["de", "/de/:path(.*)?"],
                    ["en", "/:path(.*)?"],
                ],
            },
        ],
    });
    expect(runtime.localizeUrl("https://example.com/about", { locale: "en" }).href).toBe("https://example.com/about");
    expect(runtime.localizeUrl("https://example.com/about", { locale: "de" }).href).toBe("https://example.com/de/about");
    expect(runtime.deLocalizeUrl("https://example.com/de/about").href).toBe("https://example.com/about");
});
// https://github.com/opral/inlang-paraglide-js/issues/454
test("works with no trailing slash at the end", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "/:path(.*)?",
                localized: [
                    ["en", "/en/:path(.*)?"],
                    ["de", "/de/:path(.*)?"],
                ],
            },
        ],
    });
    expect(runtime.deLocalizeUrl("https://example.com/en/").href).toBe("https://example.com/");
    expect(runtime.deLocalizeUrl("https://example.com/en").href).toBe("https://example.com/");
});
// https://github.com/opral/inlang-paraglide-js/issues/452#issuecomment-2715761308
test("falls through if no match is found", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "/about",
                localized: [
                    ["de", "/ueber"],
                    ["en", "/about"],
                ],
            },
        ],
    });
    expect(runtime.localizeUrl("https://example.com/", { locale: "en" }).href).toBe("https://example.com/");
    expect(runtime.deLocalizeUrl("https://example.com/").href).toBe("https://example.com/");
});
test("defining no localized pattern leads to a fallthrough", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "/specific-path",
                localized: [["en", "/specific-path"]],
            },
        ],
    });
    // doesn't localize because no localized pattern is defined
    expect(runtime.localizeUrl("https://example.com/specific-path", { locale: "de" })
        .href).toBe("https://example.com/specific-path");
    // doesn't delocalize because no localized pattern is defined
    expect(runtime.deLocalizeUrl("https://example.com/de/specific-path").href).toBe("https://example.com/de/specific-path");
});
// https://github.com/opral/inlang-paraglide-js/issues/456
test("routing to a 404 page", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "/404",
                localized: [
                    ["en", "/404"],
                    ["de", "/de/404"],
                ],
            },
            {
                pattern: "specific-path",
                localized: [
                    ["en", "/specific-path"],
                    ["de", "/de/404"],
                ],
            },
            {
                pattern: "/:path(.*)?",
                localized: [
                    ["en", "/:path(.*)?"],
                    ["de", "/de/:path(.*)?"],
                ],
            },
        ],
    });
    expect(runtime.localizeUrl("https://example.com/specific-path", { locale: "en" })
        .href).toBe("https://example.com/specific-path");
    // localizing to a 404 page
    expect(runtime.localizeUrl("https://example.com/specific-path", { locale: "de" })
        .href).toBe("https://example.com/de/404");
    // other paths work because of the catch all
    expect(runtime.localizeUrl("https://example.com/other-path", { locale: "de" }).href).toBe("https://example.com/de/other-path");
});
// Test showing the importance of pattern order in the localized array
test("pattern order in localized array - correct order (specific first)", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "/:path(.*)?",
                localized: [
                    // CORRECT ORDER: more specific pattern first
                    ["de", "/de/:path(.*)?"], // More specific pattern with prefix
                    ["en", "/:path(.*)?"], // Less specific pattern without prefix
                ],
            },
        ],
    });
    // These should work correctly with the specific (de) pattern first
    expect(runtime.localizeUrl("https://example.com/about", { locale: "en" }).href).toBe("https://example.com/about");
    expect(runtime.localizeUrl("https://example.com/about", { locale: "de" }).href).toBe("https://example.com/de/about");
    // Delocalization should work correctly too
    expect(runtime.deLocalizeUrl("https://example.com/de/about").href).toBe("https://example.com/about");
});
// Test showing the importance of pattern order in the localized array
test("pattern order in localized array - incorrect order (generic first)", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                pattern: "/:path(.*)?",
                localized: [
                    // INCORRECT ORDER: less specific pattern first
                    ["en", "/:path(.*)?"], // Less specific pattern without prefix
                    ["de", "/de/:path(.*)?"], // More specific pattern with prefix that may never match
                ],
            },
        ],
    });
    // English localization works as expected
    expect(runtime.localizeUrl("https://example.com/about", { locale: "en" }).href).toBe("https://example.com/about");
    // German localization still works when explicitly requested
    expect(runtime.localizeUrl("https://example.com/about", { locale: "de" }).href).toBe("https://example.com/de/about");
    // The problem happens with delocalization:
    // With incorrect pattern order, the generic /:path(.*)?
    // pattern matches first and swallows the /de/ prefix
    expect(runtime.deLocalizeUrl("https://example.com/de/about").href).toBe("https://example.com/de/about"); // Should be "https://example.com/about"
});
// Test for port number issue with specific port numbers in the URL pattern
test("handles explicit port numbers in URL patterns correctly", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                // Using explicit port number - this causes issues with deLocalizeUrl
                pattern: "http://localhost:5173/:path(.*)?",
                localized: [
                    ["de", "http://localhost:5173/de/:path(.*)?"],
                    ["en", "http://localhost:5173/:path(.*)?"],
                ],
            },
        ],
    });
    // Localization should work correctly
    expect(runtime.localizeUrl("http://localhost:5173/about", { locale: "de" }).href).toBe("http://localhost:5173/de/about");
    expect(runtime.localizeUrl("http://localhost:5173/about", { locale: "en" }).href).toBe("http://localhost:5173/about");
    // This is where the bug occurs - delocalizing a URL with a port number
    // The port number (5173) is incorrectly treated as a path parameter
    expect(runtime.deLocalizeUrl("http://localhost:5173/de/about").href).toBe("http://localhost:5173/about");
});
// Test for the correct approach using port as a pattern parameter
test("correctly handles port numbers as pattern parameters", async () => {
    const runtime = await createParaglide({
        blob: await newProject({
            settings: {
                baseLocale: "en",
                locales: ["en", "de"],
            },
        }),
        strategy: ["url"],
        urlPatterns: [
            {
                // Using port as a proper pattern parameter with :: syntax
                pattern: "http://localhost::port/:path(.*)?",
                localized: [
                    ["de", "http://localhost::port/de/:path(.*)?"],
                    ["en", "http://localhost::port/:path(.*)?"],
                ],
            },
        ],
    });
    // Localization should work correctly
    expect(runtime.localizeUrl("http://localhost:5173/about", { locale: "de" }).href).toBe("http://localhost:5173/de/about");
    expect(runtime.localizeUrl("http://localhost:5173/about", { locale: "en" }).href).toBe("http://localhost:5173/about");
    // Delocalization should also work correctly with the proper pattern
    expect(runtime.deLocalizeUrl("http://localhost:5173/de/about").href).toBe("http://localhost:5173/about");
});
//# sourceMappingURL=localize-url.test.js.map