// @vitest-environment jsdom
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, fireEvent, waitFor, cleanup } from '@testing-library/react';
import { AvatarUpload } from './AvatarUpload';
import type { WidgetTranslations } from '../i18n';

const { fileToBase64, resizeAvatarImage } = vi.hoisted( () => ( {
	fileToBase64: vi.fn(),
	resizeAvatarImage: vi.fn(),
} ) );

vi.mock( '../imageUtils', () => ( {
	fileToBase64,
	resizeAvatarImage,
	// Real class so `instanceof` works in the component.
	UndecodableImageError: class UndecodableImageError extends Error {},
} ) );

// Minimal `upload` translations for the component under test.
const T = {
	invalidFile: 'INVALID',
	processingFailed: 'PROC_FAILED',
	unreadableImage: 'UNREADABLE',
} as unknown as WidgetTranslations[ 'upload' ];

function selectFile( type = 'image/png' ): void {
	const input = document.querySelector( 'input[type="file"]' ) as HTMLInputElement;
	const file = new File( [ 'bytes' ], 'photo', { type } );
	fireEvent.change( input, { target: { files: [ file ] } } );
}

beforeEach( () => {
	fileToBase64.mockReset().mockResolvedValue( 'data:image/png;base64,SRC' );
	resizeAvatarImage.mockReset();
} );

afterEach( () => {
	cleanup();
} );

describe( 'AvatarUpload accepts anything decodable, refuses only undecodable', () => {
	it( 'shows the unreadable message when decode fails', async () => {
		const { UndecodableImageError } = await import( '../imageUtils' );
		resizeAvatarImage.mockRejectedValue( new ( UndecodableImageError as any )() );
		render( <AvatarUpload onAvatarSaved={ vi.fn() } t={ T } /> );

		selectFile( 'application/octet-stream' ); // odd type must still be attempted

		await waitFor( () => expect( screen.getByText( 'UNREADABLE' ) ).toBeTruthy() );
		expect( resizeAvatarImage ).toHaveBeenCalled(); // no MIME gate blocked it
	} );

	it( 'processes a decodable file without a size/format refusal', async () => {
		resizeAvatarImage.mockResolvedValue( 'data:image/jpeg;base64,SMALL' );
		render( <AvatarUpload onAvatarSaved={ vi.fn() } t={ T } /> );

		selectFile( 'image/webp' );

		await waitFor( () => expect( resizeAvatarImage ).toHaveBeenCalledWith( 'data:image/png;base64,SRC' ) );
		expect( screen.queryByText( 'INVALID' ) ).toBeNull();
	} );
} );
