import { describe, it, expect, beforeEach } from "vitest";
import { AppReduced, type AppType } from "ui/client/utils/AppReduced";
import type { BkndAdminProps } from "ui/Admin";

// Import the normalizeAdminPath function for testing
// Note: This assumes the function is exported or we need to test it indirectly through public methods

describe("AppReduced", () => {
   let mockAppJson: AppType;
   let appReduced: AppReduced;

   beforeEach(() => {
      mockAppJson = {
         data: {
            entities: {},
            relations: {},
         },
         flows: {
            flows: {},
         },
         auth: {},
      } as AppType;
   });

   describe("getSettingsPath", () => {
      it("should return settings path with basepath", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getSettingsPath();

         expect(result).toBe("~/admin/settings");
      });

      it("should return settings path with empty basepath", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getSettingsPath();

         expect(result).toBe("~/settings");
      });

      it("should append additional path segments", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getSettingsPath(["user", "profile"]);

         expect(result).toBe("~/admin/settings/user/profile");
      });

      it("should normalize multiple slashes", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "//admin//",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getSettingsPath(["//user//"]);

         expect(result).toBe("~/admin/settings/user");
      });

      it("should handle basepath without leading slash", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getSettingsPath();

         expect(result).toBe("~/admin/settings");
      });
   });

   describe("getAbsolutePath", () => {
      it("should return absolute path with basepath", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getAbsolutePath("dashboard");

         expect(result).toBe("~/admin/dashboard");
      });

      it("should return base path when no path provided", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getAbsolutePath();

         expect(result).toBe("~/admin");
      });

      it("should normalize paths correctly", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "//admin//",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getAbsolutePath("//dashboard//");

         expect(result).toBe("~/admin/dashboard");
      });
   });

   describe("options getter", () => {
      it("should return merged options with defaults", () => {
         const customOptions: BkndAdminProps["config"] = {
            basepath: "/custom-admin",
            logo_return_path: "/custom-home",
         };

         appReduced = new AppReduced(mockAppJson, customOptions);
         const options = appReduced.options;

         expect(options).toEqual({
            logo_return_path: "/custom-home",
            basepath: "/custom-admin",
         });
      });

      it("should use default logo_return_path when not provided", () => {
         const customOptions: BkndAdminProps["config"] = {
            basepath: "/admin",
         };

         appReduced = new AppReduced(mockAppJson, customOptions);
         const options = appReduced.options;

         expect(options.logo_return_path).toBe("/");
         expect(options.basepath).toBe("/admin");
      });
   });

   describe("path normalization behavior", () => {
      it("should normalize duplicate slashes in settings path", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getSettingsPath(["//nested//path//"]);

         expect(result).toBe("~/admin/settings/nested/path");
      });

      it("should handle root path normalization", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getAbsolutePath();

         // The normalizeAdminPath function removes trailing slashes except for root "/"
         // When basepath is "/", the result is "~/" which becomes "~" after normalization
         expect(result).toBe("~");
      });

      it("should preserve entity paths ending with slash", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getAbsolutePath("entity/");

         expect(result).toBe("~/admin/entity");
      });

      it("should remove trailing slashes from non-entity paths", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getAbsolutePath("dashboard/");

         expect(result).toBe("~/admin/dashboard");
      });
   });

   describe("withBasePath - double slash fix (admin_basepath with trailing slash)", () => {
      it("should not produce double slashes when admin_basepath has trailing slash", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/",
            admin_basepath: "/admin/",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.withBasePath("/data");

         expect(result).toBe("/admin/data");
         expect(result).not.toContain("//");
      });

      it("should work correctly when admin_basepath has no trailing slash", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/",
            admin_basepath: "/admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.withBasePath("/data");

         expect(result).toBe("/admin/data");
      });

      it("should handle absolute paths with admin_basepath trailing slash", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/",
            admin_basepath: "/admin/",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getAbsolutePath("data");

         expect(result).toBe("~/admin/data");
         expect(result).not.toContain("//");
      });

      it("should handle settings path with admin_basepath trailing slash", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/",
            admin_basepath: "/admin/",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getSettingsPath(["general"]);

         expect(result).toBe("~/admin/settings/general");
         expect(result).not.toContain("//");
      });
   });

   describe("edge cases", () => {
      it("should handle undefined basepath", () => {
         const options: BkndAdminProps["config"] = {
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getSettingsPath();

         // When basepath is undefined, it defaults to empty string
         expect(result).toBe("~/settings");
      });

      it("should handle null path segments", () => {
         const options: BkndAdminProps["config"] = {
            basepath: "/admin",
            logo_return_path: "/",
         };

         appReduced = new AppReduced(mockAppJson, options);
         const result = appReduced.getSettingsPath(["", "valid", ""]);

         expect(result).toBe("~/admin/settings/valid");
      });
   });
});
