import { describe, it, expect } from "vitest";
import { validate } from "class-validator";
import { plainToInstance } from "class-transformer";
import { CreateActivityLogDto } from "./create-activity-log.dto";
import { ActivityAction, EntityType } from "@prisma/client";

describe("CreateActivityLogDto", () => {
  describe("required fields validation", () => {
    it("should pass with all required fields valid", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors).toHaveLength(0);
    });

    it("should fail when workspaceId is missing", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const workspaceIdError = errors.find((e) => e.property === "workspaceId");
      expect(workspaceIdError).toBeDefined();
    });

    it("should fail when userId is missing", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const userIdError = errors.find((e) => e.property === "userId");
      expect(userIdError).toBeDefined();
    });

    it("should fail when action is missing", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const actionError = errors.find((e) => e.property === "action");
      expect(actionError).toBeDefined();
    });

    it("should fail when entityType is missing", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const entityTypeError = errors.find((e) => e.property === "entityType");
      expect(entityTypeError).toBeDefined();
    });

    it("should fail when entityId is missing", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const entityIdError = errors.find((e) => e.property === "entityId");
      expect(entityIdError).toBeDefined();
    });
  });

  describe("UUID validation", () => {
    it("should fail with invalid workspaceId UUID", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "invalid-uuid",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      expect(errors[0].property).toBe("workspaceId");
    });

    it("should fail with invalid userId UUID", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "not-a-uuid",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const userIdError = errors.find((e) => e.property === "userId");
      expect(userIdError).toBeDefined();
    });

    it("should fail with invalid entityId UUID", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "bad-entity-id",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const entityIdError = errors.find((e) => e.property === "entityId");
      expect(entityIdError).toBeDefined();
    });
  });

  describe("enum validation", () => {
    it("should pass with all valid ActivityAction values", async () => {
      const actions = Object.values(ActivityAction);

      for (const action of actions) {
        const dto = plainToInstance(CreateActivityLogDto, {
          workspaceId: "550e8400-e29b-41d4-a716-446655440000",
          userId: "550e8400-e29b-41d4-a716-446655440001",
          action,
          entityType: EntityType.TASK,
          entityId: "550e8400-e29b-41d4-a716-446655440002",
        });

        const errors = await validate(dto);
        expect(errors).toHaveLength(0);
      }
    });

    it("should fail with invalid action value", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: "INVALID_ACTION",
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const actionError = errors.find((e) => e.property === "action");
      expect(actionError?.constraints?.isEnum).toBeDefined();
    });

    it("should pass with all valid EntityType values", async () => {
      const entityTypes = Object.values(EntityType);

      for (const entityType of entityTypes) {
        const dto = plainToInstance(CreateActivityLogDto, {
          workspaceId: "550e8400-e29b-41d4-a716-446655440000",
          userId: "550e8400-e29b-41d4-a716-446655440001",
          action: ActivityAction.CREATED,
          entityType,
          entityId: "550e8400-e29b-41d4-a716-446655440002",
        });

        const errors = await validate(dto);
        expect(errors).toHaveLength(0);
      }
    });

    it("should fail with invalid entityType value", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: "INVALID_TYPE",
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const entityTypeError = errors.find((e) => e.property === "entityType");
      expect(entityTypeError?.constraints?.isEnum).toBeDefined();
    });
  });

  describe("optional fields validation", () => {
    it("should pass with valid details object", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.UPDATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
        details: {
          field: "status",
          oldValue: "TODO",
          newValue: "IN_PROGRESS",
        },
      });

      const errors = await validate(dto);
      expect(errors).toHaveLength(0);
    });

    it("should fail with non-object details", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.UPDATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
        details: "not an object",
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const detailsError = errors.find((e) => e.property === "details");
      expect(detailsError?.constraints?.isObject).toBeDefined();
    });

    it("should pass with valid ipAddress", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
        ipAddress: "192.168.1.1",
      });

      const errors = await validate(dto);
      expect(errors).toHaveLength(0);
    });

    it("should pass with valid IPv6 address", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
        ipAddress: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
      });

      const errors = await validate(dto);
      expect(errors).toHaveLength(0);
    });

    it("should fail when ipAddress exceeds max length", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
        ipAddress: "a".repeat(46),
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const ipError = errors.find((e) => e.property === "ipAddress");
      expect(ipError?.constraints?.maxLength).toBeDefined();
    });

    it("should pass with valid userAgent", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
        userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
      });

      const errors = await validate(dto);
      expect(errors).toHaveLength(0);
    });

    it("should fail when userAgent exceeds max length", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
        userAgent: "a".repeat(501),
      });

      const errors = await validate(dto);
      expect(errors.length).toBeGreaterThan(0);
      const userAgentError = errors.find((e) => e.property === "userAgent");
      expect(userAgentError?.constraints?.maxLength).toBeDefined();
    });

    it("should pass when optional fields are not provided", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.CREATED,
        entityType: EntityType.TASK,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
      });

      const errors = await validate(dto);
      expect(errors).toHaveLength(0);
    });
  });

  describe("complete validation", () => {
    it("should pass with all fields valid", async () => {
      const dto = plainToInstance(CreateActivityLogDto, {
        workspaceId: "550e8400-e29b-41d4-a716-446655440000",
        userId: "550e8400-e29b-41d4-a716-446655440001",
        action: ActivityAction.UPDATED,
        entityType: EntityType.PROJECT,
        entityId: "550e8400-e29b-41d4-a716-446655440002",
        details: {
          changes: ["status", "priority"],
          metadata: { source: "web-app" },
        },
        ipAddress: "10.0.0.1",
        userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
      });

      const errors = await validate(dto);
      expect(errors).toHaveLength(0);
    });
  });
});
