import { describe, it, expect, beforeEach, vi } from "vitest";
import { hashPassword, verifyPassword, registerUser, authenticateUser } from "../services/passwordAuth.ts";

describe("Password Authentication", () => {
  describe("hashPassword", () => {
    it("should hash a password", async () => {
      const password = "testPassword123";
      const hash = await hashPassword(password);
      expect(hash).toBeDefined();
      expect(hash).toContain(":");
      expect(hash.split(":")).toHaveLength(2);
    });

    it("should generate different hashes for the same password", async () => {
      const password = "testPassword123";
      const hash1 = await hashPassword(password);
      const hash2 = await hashPassword(password);
      expect(hash1).not.toBe(hash2);
    });
  });

  describe("verifyPassword", () => {
    it("should verify a correct password", async () => {
      const password = "testPassword123";
      const hash = await hashPassword(password);
      const isValid = await verifyPassword(password, hash);
      expect(isValid).toBe(true);
    });

    it("should reject an incorrect password", async () => {
      const password = "testPassword123";
      const wrongPassword = "wrongPassword456";
      const hash = await hashPassword(password);
      const isValid = await verifyPassword(wrongPassword, hash);
      expect(isValid).toBe(false);
    });
  });

  describe("registerUser", () => {
    it("should require minimum password length", async () => {
      try {
        await registerUser("test@example.com", "short", "Test User");
        expect.fail("Should throw error for short password");
      } catch (error) {
        // Expected to fail
      }
    });

    it("should create a new user with valid credentials", async () => {
      // This test would need a mock database
      // For now, we're testing the password hashing logic
      const password = "validPassword123";
      const hash = await hashPassword(password);
      const isValid = await verifyPassword(password, hash);
      expect(isValid).toBe(true);
    });
  });

  describe("authenticateUser", () => {
    it("should reject invalid email", async () => {
      try {
        await authenticateUser("nonexistent@example.com", "password123");
        expect.fail("Should throw error for invalid email");
      } catch (error) {
        expect(error instanceof Error).toBe(true);
      }
    });

    it("should reject invalid password", async () => {
      try {
        await authenticateUser("test@example.com", "wrongPassword");
        expect.fail("Should throw error for invalid password");
      } catch (error) {
        expect(error instanceof Error).toBe(true);
      }
    });
  });
});

describe("Email Authentication Router", () => {
  describe("signup procedure", () => {
    it("should validate email format", () => {
      const email = "invalid-email";
      expect(email).not.toMatch(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
    });

    it("should validate password length", () => {
      const password = "short";
      expect(password.length).toBeLessThan(8);
    });

    it("should require name", () => {
      const name = "";
      expect(name.length).toBe(0);
    });
  });

  describe("login procedure", () => {
    it("should validate email format", () => {
      const email = "test@example.com";
      expect(email).toMatch(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
    });

    it("should require password", () => {
      const password = "";
      expect(password.length).toBe(0);
    });
  });

  describe("requestPasswordReset procedure", () => {
    it("should validate email format", () => {
      const email = "test@example.com";
      expect(email).toMatch(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
    });

    it("should reject invalid email", () => {
      const email = "invalid-email";
      expect(email).not.toMatch(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
    });
  });

  describe("resetPassword procedure", () => {
    it("should validate email format", () => {
      const email = "test@example.com";
      expect(email).toMatch(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
    });

    it("should validate new password length", () => {
      const password = "newPassword123";
      expect(password.length).toBeGreaterThanOrEqual(8);
    });

    it("should reject short password", () => {
      const password = "short";
      expect(password.length).toBeLessThan(8);
    });
  });
});
