import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
import { getActorFromRequestContext } from './getActorFromRequestContext';

// Mock the http adapter
vi.mock('@adapters/http/RequestContext', () => ({
  getHttpRequestContext: vi.fn(),
}));

import { getHttpRequestContext } from '@adapters/http/RequestContext';

describe('getActorFromRequestContext', () => {
  const mockGetHttpRequestContext = vi.mocked(getHttpRequestContext);

  beforeEach(() => {
    vi.clearAllMocks();
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('should return actor with userId and driverId from request', () => {
    const mockContext = {
      req: {
        user: {
          userId: 'user-123',
        },
      },
    };

    mockGetHttpRequestContext.mockReturnValue(mockContext as never);

    const actor = getActorFromRequestContext();

    expect(actor).toEqual({
      userId: 'user-123',
      driverId: 'user-123',
      role: undefined,
    });
  });

  it('should include role from request when available', () => {
    const mockContext = {
      req: {
        user: {
          userId: 'user-123',
          role: 'admin',
        },
      },
    };

    mockGetHttpRequestContext.mockReturnValue(mockContext as never);

    const actor = getActorFromRequestContext();

    expect(actor).toEqual({
      userId: 'user-123',
      driverId: 'user-123',
      role: 'admin',
    });
  });

  it('should throw error when userId is missing', () => {
    const mockContext = {
      req: {
        user: {},
      },
    };

    mockGetHttpRequestContext.mockReturnValue(mockContext as never);

    expect(() => getActorFromRequestContext()).toThrow('Unauthorized');
  });

  it('should throw error when user object is missing', () => {
    const mockContext = {
      req: {},
    };

    mockGetHttpRequestContext.mockReturnValue(mockContext as never);

    expect(() => getActorFromRequestContext()).toThrow('Unauthorized');
  });

  it('should throw error when request is missing', () => {
    const mockContext = {};

    mockGetHttpRequestContext.mockReturnValue(mockContext as never);

    expect(() => getActorFromRequestContext()).toThrow('Unauthorized');
  });

  it('should handle userId as empty string', () => {
    const mockContext = {
      req: {
        user: {
          userId: '',
        },
      },
    };

    mockGetHttpRequestContext.mockReturnValue(mockContext as never);

    expect(() => getActorFromRequestContext()).toThrow('Unauthorized');
  });

  it('should map userId to driverId correctly', () => {
    const mockContext = {
      req: {
        user: {
          userId: 'driver-456',
        },
      },
    };

    mockGetHttpRequestContext.mockReturnValue(mockContext as never);

    const actor = getActorFromRequestContext();

    expect(actor.driverId).toBe('driver-456');
    expect(actor.userId).toBe('driver-456');
  });

  it('should handle role as undefined when not provided', () => {
    const mockContext = {
      req: {
        user: {
          userId: 'user-123',
        },
      },
    };

    mockGetHttpRequestContext.mockReturnValue(mockContext as never);

    const actor = getActorFromRequestContext();

    expect(actor.role).toBeUndefined();
  });

  it('should handle role as null', () => {
    const mockContext = {
      req: {
        user: {
          userId: 'user-123',
          role: null,
        },
      },
    };

    mockGetHttpRequestContext.mockReturnValue(mockContext as never);

    const actor = getActorFromRequestContext();

    expect(actor.role).toBeNull();
  });
});
