import { afterEach, describe, expect, it, vi } from "vitest";

import {
  buildAdminUrl,
  buildSiteUrl,
  fromDevelopmentAdminPath,
  getAdminAppPath,
  getAdminBaseUrl,
  getAdminHost,
  getRequestHostname,
  getSiteBaseUrl,
  getSiteHost,
  hasDedicatedAdminHost,
  INTERNAL_ADMIN_PREFIX,
  isAdminHost,
  isDevelopmentAdminPath,
  isInternalAdminPath,
  isLegacyAdminPath,
  toInternalAdminPath,
} from "@/lib/admin-routing";

afterEach(() => {
  vi.unstubAllEnvs();
});

describe("getRequestHostname", () => {
  it("prefers the first non-empty candidate", () => {
    expect(getRequestHostname("root.mohfarawati.de", "internal")).toBe("root.mohfarawati.de");
  });

  it("strips ports and takes the first comma-separated proxy value", () => {
    expect(getRequestHostname(undefined, "root.mohfarawati.de:443, proxy")).toBe("root.mohfarawati.de");
  });

  it("lowercases the hostname", () => {
    expect(getRequestHostname("ROOT.MohFarawati.de")).toBe("root.mohfarawati.de");
  });

  it("falls back to empty string when nothing matches", () => {
    expect(getRequestHostname(undefined, null, "")).toBe("");
  });
});

describe("host configuration", () => {
  it("defaults admin and site hosts", () => {
    expect(getAdminHost()).toBe("root.mohfarawati.de");
    expect(getSiteHost()).toBe("mohfarawati.de");
    expect(hasDedicatedAdminHost()).toBe(true);
  });

  it("reads ADMIN_HOST override and normalizes case/whitespace", () => {
    vi.stubEnv("ADMIN_HOST", "  Admin.Example.COM ");
    expect(getAdminHost()).toBe("admin.example.com");
  });

  it("derives the site host from NEXT_PUBLIC_SITE_URL", () => {
    vi.stubEnv("NEXT_PUBLIC_SITE_URL", "https://example.org/some/path");
    expect(getSiteHost()).toBe("example.org");
  });

  it("hasDedicatedAdminHost is false when admin and site hosts match", () => {
    vi.stubEnv("ADMIN_HOST", "example.com");
    vi.stubEnv("NEXT_PUBLIC_SITE_URL", "https://example.com");
    expect(hasDedicatedAdminHost()).toBe(false);
  });

  it("isAdminHost compares against the configured admin host", () => {
    expect(isAdminHost("root.mohfarawati.de")).toBe(true);
    expect(isAdminHost("mohfarawati.de")).toBe(false);
  });
});

describe("path predicates", () => {
  it("recognizes legacy /root paths", () => {
    expect(isLegacyAdminPath("/root")).toBe(true);
    expect(isLegacyAdminPath("/root/portfolio")).toBe(true);
    expect(isLegacyAdminPath("/rooting")).toBe(false);
    expect(isLegacyAdminPath("/")).toBe(false);
  });

  it("recognizes development /root paths", () => {
    expect(isDevelopmentAdminPath("/root")).toBe(true);
    expect(isDevelopmentAdminPath("/root/media")).toBe(true);
    expect(isDevelopmentAdminPath("/rootx")).toBe(false);
  });

  it("recognizes internal admin paths", () => {
    expect(isInternalAdminPath(INTERNAL_ADMIN_PREFIX)).toBe(true);
    expect(isInternalAdminPath(`${INTERNAL_ADMIN_PREFIX}/smtp`)).toBe(true);
    expect(isInternalAdminPath("/admin")).toBe(false);
  });
});

describe("path translation", () => {
  it("maps public paths to internal admin paths", () => {
    expect(toInternalAdminPath("/")).toBe(INTERNAL_ADMIN_PREFIX);
    expect(toInternalAdminPath("/portfolio")).toBe(`${INTERNAL_ADMIN_PREFIX}/portfolio`);
    expect(toInternalAdminPath("portfolio")).toBe(`${INTERNAL_ADMIN_PREFIX}/portfolio`);
  });

  it("strips the dev /root prefix", () => {
    expect(fromDevelopmentAdminPath("/root")).toBe("/");
    expect(fromDevelopmentAdminPath("/root/portfolio")).toBe("/portfolio");
    expect(fromDevelopmentAdminPath("/portfolio")).toBe("/portfolio");
  });
});

describe("getAdminAppPath", () => {
  it("returns bare paths when a dedicated admin host exists", () => {
    // default env: admin host != site host -> dedicated host branch
    expect(getAdminAppPath("/")).toBe("/");
    expect(getAdminAppPath("/smtp")).toBe("/smtp");
  });

  it("uses the /root dev prefix when no dedicated host and not production", () => {
    vi.stubEnv("ADMIN_HOST", "example.com");
    vi.stubEnv("NEXT_PUBLIC_SITE_URL", "https://example.com");
    vi.stubEnv("NODE_ENV", "development");
    expect(getAdminAppPath("/")).toBe("/root");
    expect(getAdminAppPath("/portfolio")).toBe("/root/portfolio");
  });

  it("returns bare paths in production even without a dedicated host", () => {
    vi.stubEnv("ADMIN_HOST", "example.com");
    vi.stubEnv("NEXT_PUBLIC_SITE_URL", "https://example.com");
    vi.stubEnv("NODE_ENV", "production");
    expect(getAdminAppPath("/portfolio")).toBe("/portfolio");
  });
});

describe("url builders", () => {
  it("builds admin urls from NEXT_PUBLIC_ADMIN_URL", () => {
    expect(getAdminBaseUrl()).toBe("https://root.mohfarawati.de");
    expect(buildAdminUrl("/smtp")).toBe("https://root.mohfarawati.de/smtp");
  });

  it("trims trailing slashes from configured base urls", () => {
    vi.stubEnv("NEXT_PUBLIC_ADMIN_URL", "https://admin.example.com/");
    expect(getAdminBaseUrl()).toBe("https://admin.example.com");
  });

  it("builds site urls from NEXT_PUBLIC_SITE_URL", () => {
    expect(getSiteBaseUrl()).toBe("https://mohfarawati.de");
    expect(buildSiteUrl("/about")).toBe("https://mohfarawati.de/about");
    expect(buildSiteUrl("/")).toBe("https://mohfarawati.de/");
  });
});
