/**
 * Integration Tests for Invitation Accept API Routes
 *
 * Tests the complete API layer for invitation acceptance.
 * - GET /api/organization/invitations/accept - Validate token
 * - POST /api/organization/invitations/accept - Accept invitation
 */

import { jest } from "@jest/globals";
import { NextRequest } from "next/server";

// Mock Prisma
const mockPrisma = {
  organization_invitations: {
    findUnique: jest.fn(),
    update: jest.fn(),
  },
  users: {
    findUnique: jest.fn(),
    create: jest.fn(),
  },
  organization_members: {
    findFirst: jest.fn(),
    create: jest.fn(),
  },
};

jest.mock("@/lib/db", () => ({
  prisma: mockPrisma,
}));

// Mock organization service
const mockOrganizationService = {
  acceptInvitation: jest.fn(),
};

jest.mock("@/lib/services/organization.service", () => ({
  organizationService: mockOrganizationService,
}));

// Mock logger
jest.mock("@/lib/logger", () => ({
  logger: {
    info: jest.fn(),
    error: jest.fn(),
    warn: jest.fn(),
  },
}));

// Route migrated to Convex - mocks need updating
describe.skip("Invitation Accept API Routes", () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe("GET /api/organization/invitations/accept", () => {
    it("should return invitation details for valid token", async () => {
      const { GET } =
        await import("@/app/api/organization/invitations/accept/route");

      const mockInvitation = {
        id: "invite_123",
        email: "newuser@example.com",
        name: "New User",
        role: "STAFF",
        token: "valid_token_123",
        status: "PENDING",
        expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
        organization: {
          id: "org_123",
          name: "Test Clinic",
        },
      };

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(
        mockInvitation,
      );
      mockPrisma.users.findUnique.mockResolvedValue(null);

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept?token=valid_token_123",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.success).toBe(true);
      expect(data.invitation.email).toBe("newuser@example.com");
      expect(data.invitation.organizationName).toBe("Test Clinic");
      expect(data.userExists).toBe(false);
    });

    it("should indicate userExists=true for existing users", async () => {
      const { GET } =
        await import("@/app/api/organization/invitations/accept/route");

      const mockInvitation = {
        id: "invite_123",
        email: "existing@example.com",
        role: "ADMIN",
        token: "valid_token_456",
        status: "PENDING",
        expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
        organization: {
          id: "org_123",
          name: "Test Clinic",
        },
      };

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(
        mockInvitation,
      );
      mockPrisma.users.findUnique.mockResolvedValue({
        id: "user_existing",
        email: "existing@example.com",
      });

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept?token=valid_token_456",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.userExists).toBe(true);
    });

    it("should return 400 if token not provided", async () => {
      const { GET } =
        await import("@/app/api/organization/invitations/accept/route");

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.error).toBe("Token is required");
    });

    it("should return 404 for invalid token", async () => {
      const { GET } =
        await import("@/app/api/organization/invitations/accept/route");

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(null);

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept?token=invalid_token",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(404);
      expect(data.error).toBe("Invalid invitation token");
    });

    it("should return 410 for expired invitation", async () => {
      const { GET } =
        await import("@/app/api/organization/invitations/accept/route");

      const mockInvitation = {
        id: "invite_123",
        email: "user@example.com",
        token: "expired_token",
        status: "PENDING",
        expiresAt: new Date(Date.now() - 24 * 60 * 60 * 1000), // Yesterday
        organization: { id: "org_123", name: "Test Clinic" },
      };

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(
        mockInvitation,
      );

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept?token=expired_token",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(410);
      expect(data.expired).toBe(true);
    });

    it("should return 409 for already accepted invitation", async () => {
      const { GET } =
        await import("@/app/api/organization/invitations/accept/route");

      const mockInvitation = {
        id: "invite_123",
        email: "user@example.com",
        token: "accepted_token",
        status: "ACCEPTED",
        expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
        organization: { id: "org_123", name: "Test Clinic" },
      };

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(
        mockInvitation,
      );

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept?token=accepted_token",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(409);
      expect(data.status).toBe("ACCEPTED");
    });
  });

  describe("POST /api/organization/invitations/accept", () => {
    it("should accept invitation for new user", async () => {
      const { POST } =
        await import("@/app/api/organization/invitations/accept/route");

      const mockInvitation = {
        id: "invite_123",
        email: "newuser@example.com",
        role: "STAFF",
        token: "valid_token_123",
        status: "PENDING",
        expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
      };

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(
        mockInvitation,
      );
      mockPrisma.users.findUnique.mockResolvedValue(null);

      const mockResult = {
        user: {
          id: "user_new",
          email: "newuser@example.com",
          name: "New User",
        },
        member: {
          organizationId: "org_123",
          role: "STAFF",
        },
      };

      mockOrganizationService.acceptInvitation.mockResolvedValue(mockResult);

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept",
        {
          method: "POST",
          body: JSON.stringify({
            token: "valid_token_123",
            password: "SecurePass123!",
            name: "New User",
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.success).toBe(true);
      expect(data.user.email).toBe("newuser@example.com");
      expect(data.member.role).toBe("STAFF");
    });

    it("should accept invitation for existing user without password", async () => {
      const { POST } =
        await import("@/app/api/organization/invitations/accept/route");

      const mockInvitation = {
        id: "invite_123",
        email: "existing@example.com",
        role: "ADMIN",
        token: "valid_token_456",
        status: "PENDING",
        expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
      };

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(
        mockInvitation,
      );
      mockPrisma.users.findUnique.mockResolvedValue({
        id: "user_existing",
        email: "existing@example.com",
      });

      const mockResult = {
        user: {
          id: "user_existing",
          email: "existing@example.com",
          name: "Existing User",
        },
        member: {
          organizationId: "org_123",
          role: "ADMIN",
        },
      };

      mockOrganizationService.acceptInvitation.mockResolvedValue(mockResult);

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept",
        {
          method: "POST",
          body: JSON.stringify({
            token: "valid_token_456",
            // No password needed for existing users
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.success).toBe(true);
    });

    it("should return 400 if token not provided", async () => {
      const { POST } =
        await import("@/app/api/organization/invitations/accept/route");

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept",
        {
          method: "POST",
          body: JSON.stringify({}),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.error).toBe("Token is required");
    });

    it("should return 400 if password too short for new user", async () => {
      const { POST } =
        await import("@/app/api/organization/invitations/accept/route");

      const mockInvitation = {
        id: "invite_123",
        email: "newuser@example.com",
        token: "valid_token_123",
        status: "PENDING",
        expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
      };

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(
        mockInvitation,
      );
      mockPrisma.users.findUnique.mockResolvedValue(null); // New user

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept",
        {
          method: "POST",
          body: JSON.stringify({
            token: "valid_token_123",
            password: "123", // Too short
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.error).toContain("Password is required");
    });

    it("should return 404 for invalid token", async () => {
      const { POST } =
        await import("@/app/api/organization/invitations/accept/route");

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(null);

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept",
        {
          method: "POST",
          body: JSON.stringify({
            token: "invalid_token",
            password: "SecurePass123!",
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(404);
      expect(data.error).toBe("Invalid invitation token");
    });

    it("should return 410 for expired invitation", async () => {
      const { POST } =
        await import("@/app/api/organization/invitations/accept/route");

      mockOrganizationService.acceptInvitation.mockRejectedValue(
        new Error("Invitation has expired"),
      );

      const mockInvitation = {
        id: "invite_123",
        email: "user@example.com",
        token: "expired_token",
        status: "PENDING",
        expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
      };

      mockPrisma.organization_invitations.findUnique.mockResolvedValue(
        mockInvitation,
      );
      mockPrisma.users.findUnique.mockResolvedValue({
        id: "user_1",
        email: "user@example.com",
      });

      const request = new NextRequest(
        "http://localhost:9000/api/organization/invitations/accept",
        {
          method: "POST",
          body: JSON.stringify({
            token: "expired_token",
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(410);
      expect(data.error).toContain("expired");
    });
  });
});
