import { Users } from './fixtures/userStates';
import { HomeChannel } from './page-objects';
import { createTargetChannel } from './utils';
import { expect, test } from './utils/test';

test.use({ storageState: Users.admin.state });
test.describe.serial('Threads', () => {
	let poHomeChannel: HomeChannel;
	let targetChannel: string;
	test.beforeAll(async ({ api }) => {
		targetChannel = await createTargetChannel(api);
	});
	test.beforeEach(async ({ page }) => {
		poHomeChannel = new HomeChannel(page);
		await page.goto('/home');
		await poHomeChannel.sidenav.openChat(targetChannel);
	});
	test('expect thread message preview if alsoSendToChannel checkbox is checked', async ({ page }) => {
		await poHomeChannel.content.sendMessage('this is a message for reply');
		await page.locator('[data-qa-type="message"]').last().hover();
		await page.locator('role=button[name="Reply in thread"]').click();

		await expect(page).toHaveURL(/.*thread/);

		await poHomeChannel.content.toggleAlsoSendThreadToChannel(true);
		await page.getByRole('dialog').locator('[name="msg"]').last().fill('This is a thread message also sent in channel');
		await page.keyboard.press('Enter');
		await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
		await expect(poHomeChannel.content.lastUserMessage).toContainText('This is a thread message also sent in channel');
	});
	test('expect open threads contextual bar when clicked on thread preview', async ({ page }) => {
		await poHomeChannel.content.lastThreadMessagePreviewText.click();
		await expect(page).toHaveURL(/.*thread/);
		await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
	});
	test.describe('hideFlexTab Preference enabled for threads', () => {
		test.beforeAll(async ({ api }) => {
			await expect(
				(await api.post('/users.setPreferences', { userId: 'rocketchat.internal.admin.test', data: { hideFlexTab: true } })).status(),
			).toBe(200);
		});
		test.afterAll(async ({ api }) => {
			await expect(
				(await api.post('/users.setPreferences', { userId: 'rocketchat.internal.admin.test', data: { hideFlexTab: false } })).status(),
			).toBe(200);
		});
		test('expect to close thread contextual bar on clicking outside', async ({ page }) => {
			await poHomeChannel.content.lastThreadMessagePreviewText.click();
			await expect(page).toHaveURL(/.*thread/);
			await poHomeChannel.content.lastUserMessageNotThread.click();
			await expect(page).not.toHaveURL(/.*thread/);
		});
		test('expect open threads contextual bar when clicked on thread preview', async ({ page }) => {
			await poHomeChannel.content.lastThreadMessagePreviewText.click();
			await expect(page).toHaveURL(/.*thread/);
			await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
		});
		test('expect not to close thread contextual bar when performing some action', async ({ page }) => {
			await poHomeChannel.content.lastThreadMessagePreviewText.click();
			await expect(page).toHaveURL(/.*thread/);
			await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');

			await poHomeChannel.content.openLastMessageMenu();
			await page.locator('role=menuitem[name="Copy text"]').click();

			await expect(page).toHaveURL(/.*thread/);
			await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
		});
	});
	test('expect upload a file attachment in thread with description', async ({ page }) => {
		await poHomeChannel.content.lastThreadMessagePreviewText.click();

		await expect(page).toHaveURL(/.*thread/);

		await poHomeChannel.content.dragAndDropTxtFileToThread();
		await poHomeChannel.content.descriptionInput.fill('any_description');
		await poHomeChannel.content.fileNameInput.fill('any_file1.txt');
		await poHomeChannel.content.btnModalConfirm.click();

		await expect(poHomeChannel.content.lastThreadMessageFileDescription).toHaveText('any_description');
		await expect(poHomeChannel.content.lastThreadMessageFileName).toContainText('any_file1.txt');
	});

	test.describe('thread message actions', () => {
		test.beforeEach(async ({ page }) => {
			poHomeChannel = new HomeChannel(page);
			await page.goto('/home');
			await poHomeChannel.sidenav.openChat(targetChannel);
			await poHomeChannel.content.sendMessage('this is a message for reply');
			await page.locator('[data-qa-type="message"]').last().hover();
			await page.locator('role=button[name="Reply in thread"]').click();
		});

		test('expect delete the thread message and close thread if has only one message', async ({ page }) => {
			await poHomeChannel.content.openLastThreadMessageMenu();
			await expect(page).toHaveURL(/.*thread/);

			await page.locator('role=menuitem[name="Delete"]').click();
			await page.locator('#modal-root .rcx-button-group--align-end .rcx-button--danger').click();

			await expect(page).not.toHaveURL(/.*thread/);
		});
		test('expect delete the thread message and keep thread open if has more than one message', async ({ page }) => {
			await page.locator('.rcx-vertical-bar').locator(`role=textbox[name="Message #${targetChannel}"]`).type('another reply message');
			await page.keyboard.press('Enter');
			await poHomeChannel.content.openLastThreadMessageMenu();
			await expect(page).toHaveURL(/.*thread/);

			await page.locator('role=menuitem[name="Delete"]').click();
			await page.locator('#modal-root .rcx-button-group--align-end .rcx-button--danger').click();

			await expect(page).toHaveURL(/.*thread/);
		});

		test('expect edit the thread message', async ({ page }) => {
			await poHomeChannel.content.openLastThreadMessageMenu();
			await page.locator('role=menuitem[name="Edit"]').click();
			await page.locator('[name="msg"]').last().fill('this message was edited');
			await page.keyboard.press('Enter');
			await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('this message was edited');
		});

		test('expect quote the thread message', async ({ page }) => {
			await page.getByRole('dialog').locator('[data-qa-type="message"]').last().hover();
			await page.locator('role=button[name="Quote"]').click();
			await page.locator('[name="msg"]').last().fill('this is a quote message');
			await page.keyboard.press('Enter');

			await expect(poHomeChannel.content.lastThreadMessageTextAttachmentEqualsText).toContainText('this is a message for reply');
		});

		test('expect star the thread message', async ({ page }) => {
			await poHomeChannel.content.openLastThreadMessageMenu();
			await page.locator('role=menuitem[name="Star"]').click();
			await page.getByRole('button').and(page.getByTitle('Options')).click();
			await page.locator('[data-key="starred-messages"]').click();
			await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('this is a message for reply');
		});

		test('expect copy the thread message content to clipboard', async ({ page, context }) => {
			await context.grantPermissions(['clipboard-read', 'clipboard-write']);
			await poHomeChannel.content.openLastThreadMessageMenu();
			await page.locator('role=menuitem[name="Copy text"]').click();

			const clipboardText = await page.evaluate('navigator.clipboard.readText()');
			expect(clipboardText).toBe('this is a message for reply');
		});

		test('expect copy the thread message link to clipboard', async ({ page, context }) => {
			await context.grantPermissions(['clipboard-read', 'clipboard-write']);
			await poHomeChannel.content.openLastThreadMessageMenu();
			await page.locator('role=menuitem[name="Copy link"]').click();

			const clipboardText = await page.evaluate('navigator.clipboard.readText()');
			expect(clipboardText).toContain('http');
		});

		test('expect close thread if has only one message and user press escape', async ({ page }) => {
			await expect(page).toHaveURL(/.*thread/);
			await expect(page.getByRole('dialog').locator('[data-qa-type="message"]')).toBeVisible();
			await expect(page.locator('[name="msg"]').last()).toBeFocused();
			await page.keyboard.press('Escape');
			await expect(page).not.toHaveURL(/.*thread/);
		});

		test('expect reset the thread composer to original message if user presses escape', async ({ page }) => {
			await expect(page).toHaveURL(/.*thread/);
			await expect(page.getByRole('dialog').locator('[data-qa-type="message"]')).toBeVisible();

			await expect(page.locator('[name="msg"]').last()).toBeFocused();
			await page.locator('[name="msg"]').last().fill('message to be edited');
			await page.keyboard.press('Enter');
			await page.keyboard.press('ArrowUp');

			await expect(page.locator('[name="msg"]').last()).toHaveValue('message to be edited');
			await page.locator('[name="msg"]').last().fill('this message was edited');

			await page.keyboard.press('Escape');
			await expect(page.locator('[name="msg"]').last()).toHaveValue('message to be edited');
			await expect(page).toHaveURL(/.*thread/);
		});

		test('expect clean composer and keep the thread open if user is editing message and presses escape', async ({ page }) => {
			await expect(page).toHaveURL(/.*thread/);
			await expect(page.getByRole('dialog').locator('[data-qa-type="message"]')).toBeVisible();
			await expect(page.locator('[name="msg"]').last()).toBeFocused();

			await page.locator('[name="msg"]').last().fill('message to be edited');
			await page.keyboard.press('Enter');

			await page.keyboard.press('ArrowUp');
			await expect(page.locator('[name="msg"]').last()).toHaveValue('message to be edited');

			await page.keyboard.press('Escape');
			await expect(page.locator('[name="msg"]').last()).toHaveValue('');
			await expect(page).toHaveURL(/.*thread/);
		});
	});
});