import { describe, it, expect } from "vitest";
import { WorkspaceMemberRole } from "@mosaic/shared";
import { isValidEmail, toWorkspaceMemberRole } from "./validation";

describe("isValidEmail", (): void => {
  describe("valid emails", (): void => {
    it("should accept a standard email", (): void => {
      expect(isValidEmail("user@example.com")).toBe(true);
    });

    it("should accept email with dots in local part", (): void => {
      expect(isValidEmail("first.last@example.com")).toBe(true);
    });

    it("should accept email with plus addressing", (): void => {
      expect(isValidEmail("user+tag@example.com")).toBe(true);
    });

    it("should accept email with subdomain", (): void => {
      expect(isValidEmail("user@mail.example.com")).toBe(true);
    });

    it("should accept email with hyphen in domain", (): void => {
      expect(isValidEmail("user@my-domain.com")).toBe(true);
    });

    it("should accept email with special characters in local part", (): void => {
      expect(isValidEmail("user!#$%&'*+/=?^_`{|}~@example.com")).toBe(true);
    });

    it("should accept email with numbers", (): void => {
      expect(isValidEmail("user123@example456.com")).toBe(true);
    });

    it("should accept single-character local part", (): void => {
      expect(isValidEmail("a@example.com")).toBe(true);
    });
  });

  describe("invalid emails", (): void => {
    it("should reject empty string", (): void => {
      expect(isValidEmail("")).toBe(false);
    });

    it("should reject email without @", (): void => {
      expect(isValidEmail("userexample.com")).toBe(false);
    });

    it("should reject email with only @", (): void => {
      expect(isValidEmail("@")).toBe(false);
    });

    it("should reject email without local part", (): void => {
      expect(isValidEmail("@example.com")).toBe(false);
    });

    it("should reject email without domain", (): void => {
      expect(isValidEmail("user@")).toBe(false);
    });

    it("should reject email with spaces", (): void => {
      expect(isValidEmail("user @example.com")).toBe(false);
    });

    it("should reject email with multiple @ signs", (): void => {
      expect(isValidEmail("user@@example.com")).toBe(false);
    });

    it("should reject email with domain starting with hyphen", (): void => {
      expect(isValidEmail("user@-example.com")).toBe(false);
    });

    it("should reject email exceeding 254 characters", (): void => {
      const longLocal = "a".repeat(243);
      const longEmail = `${longLocal}@example.com`;
      expect(longEmail.length).toBeGreaterThan(254);
      expect(isValidEmail(longEmail)).toBe(false);
    });

    it("should reject email that only contains @", (): void => {
      expect(isValidEmail("just@")).toBe(false);
    });

    it("should reject plaintext without any structure", (): void => {
      expect(isValidEmail("not-an-email")).toBe(false);
    });
  });
});

describe("toWorkspaceMemberRole", (): void => {
  describe("valid roles", (): void => {
    it("should return OWNER for 'OWNER'", (): void => {
      expect(toWorkspaceMemberRole("OWNER")).toBe(WorkspaceMemberRole.OWNER);
    });

    it("should return ADMIN for 'ADMIN'", (): void => {
      expect(toWorkspaceMemberRole("ADMIN")).toBe(WorkspaceMemberRole.ADMIN);
    });

    it("should return MEMBER for 'MEMBER'", (): void => {
      expect(toWorkspaceMemberRole("MEMBER")).toBe(WorkspaceMemberRole.MEMBER);
    });

    it("should return GUEST for 'GUEST'", (): void => {
      expect(toWorkspaceMemberRole("GUEST")).toBe(WorkspaceMemberRole.GUEST);
    });
  });

  describe("invalid roles", (): void => {
    it("should fall back to MEMBER for empty string", (): void => {
      expect(toWorkspaceMemberRole("")).toBe(WorkspaceMemberRole.MEMBER);
    });

    it("should fall back to MEMBER for unknown role", (): void => {
      expect(toWorkspaceMemberRole("SUPERADMIN")).toBe(WorkspaceMemberRole.MEMBER);
    });

    it("should fall back to MEMBER for lowercase variant", (): void => {
      expect(toWorkspaceMemberRole("admin")).toBe(WorkspaceMemberRole.MEMBER);
    });

    it("should fall back to MEMBER for mixed case", (): void => {
      expect(toWorkspaceMemberRole("Admin")).toBe(WorkspaceMemberRole.MEMBER);
    });

    it("should fall back to MEMBER for numeric input", (): void => {
      expect(toWorkspaceMemberRole("123")).toBe(WorkspaceMemberRole.MEMBER);
    });

    it("should fall back to MEMBER for special characters", (): void => {
      expect(toWorkspaceMemberRole("<script>")).toBe(WorkspaceMemberRole.MEMBER);
    });
  });
});
