import React from 'react';
import {render} from '@testing-library/react-native';
import {IconBan} from '@tabler/icons-react-native';
import type {Asset, MediaEntity} from '@modules/chats/interfaces';
import {MediaType} from '@modules/chats/interfaces';
import {getAssetsLabel} from '@modules/chats/utils/files';

import {usePrefixIconAndText} from '../usePrefixIconAndText';

jest.mock('@modules/chats/utils/files', () => ({
  getAssetsLabel: jest.fn(),
}));

const mockGetAssetsLabel = getAssetsLabel as jest.Mock;

const renderHook = (props: Parameters<typeof usePrefixIconAndText>[0]) => {
  let result: ReturnType<typeof usePrefixIconAndText> | undefined;

  const HookWrapper = () => {
    result = usePrefixIconAndText(props);
    return null;
  };

  render(React.createElement(HookWrapper));

  return result!;
};

const createAsset = (
  format: Asset['metadata']['format'],
  filename = 'file.ext',
): Asset =>
  ({
    id: 1,
    mimetype: 'image/png',
    filename,
    metadata: {format},
  } as Asset);

const createPendingAsset = (
  type: MediaType,
  name = 'pending.ext',
): MediaEntity =>
  ({
    id: 'media-1',
    type,
    fileAsset: null,
    status: 'idle',
    contentType: 'image/png',
    localUri: 'file://local',
    name,
    sizeInBytes: 10,
  } as MediaEntity);

describe('usePrefixIconAndText', () => {
  beforeEach(() => {
    mockGetAssetsLabel.mockReset();
  });

  it('returns deleted state when message is deleted', () => {
    const result = renderHook({isDeleted: true});

    expect(result).toEqual({
      PrefixIcon: IconBan,
      defaultText: '',
    });
  });

  it('returns empty values when there are no assets', () => {
    const result = renderHook({});

    expect(result).toEqual({
      PrefixIcon: null,
      defaultText: '',
    });
  });

  it('returns mixed images and videos label', () => {
    const mockIcon = 'MockIconCamera';
    const mockLabel = '1 imagen, 2 Videos';
    mockGetAssetsLabel.mockReturnValue({Icon: mockIcon, label: mockLabel});

    const assets = [
      createAsset('image'),
      createAsset('video'),
      createAsset('video'),
    ];
    const result = renderHook({assets});

    expect(mockGetAssetsLabel).toHaveBeenCalledWith([
      {format: 'image', filename: 'file.ext'},
      {format: 'video', filename: 'file.ext'},
      {format: 'video', filename: 'file.ext'},
    ]);
    expect(result).toEqual({
      PrefixIcon: mockIcon,
      defaultText: mockLabel,
    });
  });

  it('returns images label when only images exist', () => {
    const mockIcon = 'MockIconCamera';
    const mockLabel = '2 Imágenes';
    mockGetAssetsLabel.mockReturnValue({Icon: mockIcon, label: mockLabel});

    const assets = [createAsset('image'), createAsset('image')];
    const result = renderHook({assets});

    expect(mockGetAssetsLabel).toHaveBeenCalledWith([
      {format: 'image', filename: 'file.ext'},
      {format: 'image', filename: 'file.ext'},
    ]);
    expect(result).toEqual({
      PrefixIcon: mockIcon,
      defaultText: mockLabel,
    });
  });

  it('returns videos label when only videos exist', () => {
    const mockIcon = 'MockIconVideo';
    const mockLabel = 'Video';
    mockGetAssetsLabel.mockReturnValue({Icon: mockIcon, label: mockLabel});

    const assets = [createAsset('video')];
    const result = renderHook({assets});

    expect(mockGetAssetsLabel).toHaveBeenCalledWith([
      {format: 'video', filename: 'file.ext'},
    ]);
    expect(result).toEqual({
      PrefixIcon: mockIcon,
      defaultText: mockLabel,
    });
  });

  it('returns filename for file assets', () => {
    const mockIcon = 'MockIconFile';
    const mockLabel = 'report.pdf';
    mockGetAssetsLabel.mockReturnValue({Icon: mockIcon, label: mockLabel});

    const assets = [createAsset('file', 'report.pdf')];
    const result = renderHook({assets});

    expect(mockGetAssetsLabel).toHaveBeenCalledWith([
      {format: 'file', filename: 'report.pdf'},
    ]);
    expect(result).toEqual({
      PrefixIcon: mockIcon,
      defaultText: mockLabel,
    });
  });

  it('returns audio label for audio assets', () => {
    const mockIcon = 'MockIconMicrophone';
    const mockLabel = 'Mensaje de voz';
    mockGetAssetsLabel.mockReturnValue({Icon: mockIcon, label: mockLabel});

    const assets = [createAsset('audio')];
    const result = renderHook({assets});

    expect(mockGetAssetsLabel).toHaveBeenCalledWith([
      {format: 'audio', filename: 'file.ext'},
    ]);
    expect(result).toEqual({
      PrefixIcon: mockIcon,
      defaultText: mockLabel,
    });
  });

  it('returns gif label for gif assets', () => {
    const mockIcon = 'MockIconGif';
    const mockLabel = 'GIF';
    mockGetAssetsLabel.mockReturnValue({Icon: mockIcon, label: mockLabel});

    const assets = [createAsset('gif')];
    const result = renderHook({assets});

    expect(mockGetAssetsLabel).toHaveBeenCalledWith([
      {format: 'gif', filename: 'file.ext'},
    ]);
    expect(result).toEqual({
      PrefixIcon: mockIcon,
      defaultText: mockLabel,
    });
  });

  it('uses pending assets when assets are missing', () => {
    const mockIcon = 'MockIconCamera';
    const mockLabel = 'Imagen';
    mockGetAssetsLabel.mockReturnValue({Icon: mockIcon, label: mockLabel});

    const pendingAssets = [createPendingAsset(MediaType.IMAGE, 'pending.jpg')];
    const result = renderHook({pendingAssets});

    expect(mockGetAssetsLabel).toHaveBeenCalledWith([
      {format: 'image', filename: 'pending.jpg'},
    ]);
    expect(result).toEqual({
      PrefixIcon: mockIcon,
      defaultText: mockLabel,
    });
  });
});
