import {IconUser, IconUsersGroup} from '@tabler/icons-react-native';
import type {Conversation, HuDataMember} from '@modules/chats/interfaces';
import {ChatUserStatus} from '@modules/chats/interfaces';

const mockGetCompleteName = jest.fn();
const mockGetUserInfo = jest.fn();
const mockSaveUserUpdates = jest.fn();
const mockTranslate = jest.fn();

jest.mock('@components', () => ({}));
jest.mock('@config/i18n', () => ({
  __esModule: true,
  default: {
    t: (...args: unknown[]) => mockTranslate(...args),
  },
}));
jest.mock('@shared/utils', () => ({
  getCompleteName: (...args: unknown[]) => mockGetCompleteName(...args),
}));
jest.mock('@modules/chats/services/usersServices', () => ({
  getUserInfo: (...args: unknown[]) => mockGetUserInfo(...args),
}));
jest.mock('@modules/chats/instances/updaters/UsersUpdaterService', () => ({
  UsersUpdaterService: {
    saveUsers: (...args: unknown[]) => mockSaveUserUpdates(...args),
  },
}));

let getChannelAvatar: typeof import('../avatar').getChannelAvatar;
let getChatAvatar: typeof import('../avatar').getChatAvatar;
let getUserAvatar: typeof import('../avatar').getUserAvatar;

describe('avatar utils', () => {
  const CURRENT_USER_ID = 10;
  const OTHER_USER_ID = 99;
  const BASE_USER: HuDataMember = {
    id: CURRENT_USER_ID,
    first_name: 'John',
    last_name: 'Doe',
    employee_internal_id: 'EMP-10',
    picture_asset_url: 'https://cdn.test/avatar.png',
    status: ChatUserStatus.Active,
    email: 'john@company.test',
    version: 1,
  };

  const buildUser = (overrides: Partial<HuDataMember> = {}): HuDataMember => ({
    ...BASE_USER,
    ...overrides,
  });

  beforeEach(() => {
    jest.resetModules();
    mockGetCompleteName.mockReset();
    mockGetUserInfo.mockReset();
    mockSaveUserUpdates.mockReset();
    mockTranslate.mockReset();

    mockGetCompleteName.mockReturnValue('John Doe');
    mockTranslate.mockReturnValue('you');

    jest.isolateModules(() => {
      // eslint-disable-next-line @typescript-eslint/no-var-requires
      const avatar = require('../avatar') as typeof import('../avatar');
      ({getChannelAvatar, getChatAvatar, getUserAvatar} = avatar);
    });
  });

  it('returns fallback avatar when user is missing', () => {
    const avatar = getUserAvatar();

    expect(avatar).toEqual({
      title: '',
      name: '',
      Icon: IconUser,
    });
  });

  it('builds avatar data for active users', () => {
    const avatar = getUserAvatar(BASE_USER, CURRENT_USER_ID);

    expect(avatar.title).toBe('John Doe (you)');
    expect(avatar.name).toBe('John Doe (you)');
    expect(avatar.Icon).toBeUndefined();
    expect(avatar.url).toBe(BASE_USER.picture_asset_url);
    expect(avatar.variant).toBeUndefined();
    expect(avatar.withAuthHeader).toBe(true);
    expect(avatar.enableCache).toBe(true);
    expect(avatar.loaderType).toBe('skeleton');

    avatar.onImageError?.();
    expect(mockGetUserInfo).not.toHaveBeenCalled();
  });

  it('does not append "you" when user differs from current user', () => {
    const avatar = getUserAvatar(BASE_USER, OTHER_USER_ID);

    expect(avatar.title).toBe('John Doe');
    expect(avatar.name).toBe('John Doe');
  });

  it('fetches user info when the avatar is missing', async () => {
    const user = buildUser({picture_asset_url: null});
    const userInfo = buildUser({
      id: user.id,
      picture_asset_url: 'asset://new',
    });

    mockGetUserInfo.mockResolvedValue([userInfo]);

    const avatar = getUserAvatar(user, OTHER_USER_ID);
    avatar.onImageError?.();

    const userInfoPromise = mockGetUserInfo.mock.results[0]?.value;

    await (userInfoPromise as Promise<HuDataMember[]>);

    expect(mockGetUserInfo).toHaveBeenCalledWith({
      user: user.id,
      fromServer: true,
    });
    expect(mockSaveUserUpdates).toHaveBeenCalledWith([userInfo], {
      updateStore: true,
    });
  });

  it('marks deleted users with error styling', () => {
    const user = buildUser({deleted_at: 1704067200});

    const avatar = getUserAvatar(user, OTHER_USER_ID);

    expect(avatar.Icon).toBe(IconUser);
    expect(avatar.url).toBeUndefined();
    expect(avatar.variant).toBe('error');
    expect(avatar.withAuthHeader).toBe(true);
  });

  it('builds channel avatar data', () => {
    const conversation = {
      name: 'General',
      picture_url: 'https://cdn.test/channel.png',
      is_im: false,
    } as Conversation;

    const avatar = getChannelAvatar(conversation);

    expect(avatar.title).toBe('General');
    expect(avatar.Icon).toBe(IconUsersGroup);
    expect(avatar.url).toBe(conversation.picture_url);
    expect(avatar.variant).toBe('default');
    expect(avatar.withAuthHeader).toBe(true);
    expect(avatar.enableCache).toBe(true);
    expect(avatar.loaderType).toBe('skeleton');
  });

  it('routes chat avatar based on conversation type', () => {
    const imConversation = {
      is_im: true,
      other_user: BASE_USER,
    } as Conversation;
    const channelConversation = {
      is_im: false,
      name: 'Channel',
    } as Conversation;

    const imAvatar = getChatAvatar(imConversation, CURRENT_USER_ID);
    const userAvatar = getUserAvatar(BASE_USER, CURRENT_USER_ID);
    const channelAvatar = getChatAvatar(channelConversation, CURRENT_USER_ID);

    expect(imAvatar).toMatchObject({
      title: userAvatar.title,
      name: userAvatar.name,
      Icon: userAvatar.Icon,
      url: userAvatar.url,
      variant: userAvatar.variant,
      withAuthHeader: userAvatar.withAuthHeader,
      enableCache: userAvatar.enableCache,
      loaderType: userAvatar.loaderType,
    });
    expect(imAvatar.onImageError).toEqual(expect.any(Function));
    expect(channelAvatar).toEqual(getChannelAvatar(channelConversation));
  });
});
