const schema = require('./data/eds-c-card-composable.schema.json');
const exampleJson = require('./data/eds-c-card-composable.example.json');
const fs = require('fs');
const path = require('path');
const Ajv = require('ajv');
const ajv = new Ajv();
const handlebars = require('handlebars');

const {findTemplates} = require('../../development/tests/templateLoader.js');
findTemplates(['eds-c-card-composable']).load(handlebars);

const journalCardTemplate = '{{> eds-c-card-journal }}';
const cardWithIconTemplate = '{{> eds-c-card-with-icon }}';
const cardWithImageTemplate = '{{> eds-c-card-with-image }}';
const cardWithMetadataTemplate = '{{> eds-c-card-with-metadata }}';


const journalCardHbs = handlebars.compile(journalCardTemplate);
const cardWithIconHbs = handlebars.compile(cardWithIconTemplate);
const cardWithImageHbs = handlebars.compile(cardWithImageTemplate);
const cardWithMetadataHbs = handlebars.compile(cardWithMetadataTemplate);

const renderedComponent = journalCardHbs(exampleJson);

describe('EDS Component Card', () => {
	test('docs file exists', () => {
		const exists = fs.existsSync(path.resolve(__dirname, 'docs.md'));
		expect(exists).toBe(true);
	});
});

describe('Card Schema Validation and Accessibility Test', () => {
	const {configureAxe, toHaveNoViolations} = require('jest-axe');
	expect.extend(toHaveNoViolations);

	const axe = configureAxe({
		rules: {
			region: {enabled: false}
		}
	});

	test('Example data matches schema', () => {
		const validate = ajv.compile(schema);
		const valid = validate(exampleJson);
		if (!valid) {
			// Extract and format the Ajv validation errors
			const errors = validate.errors.map((error) => ajv.errorsText([error])).join('\n');
			throw new Error(errors);
		}
		expect(valid).toBeTruthy();
	});

	test('Template passes basic HTML accessibility', async () => {
		expect(await axe(renderedComponent)).toHaveNoViolations();
	});
});

describe('EDS Component Card Composable render', () => {
	test('Template can be compiled and rendered', () => {
		document.body.innerHTML = renderedComponent;
		const container = document.querySelectorAll('.eds-c-card-composable');
		expect(container).toBeDefined();
		expect(container.length).toBe(1);
	});

	test('Card label can be compiled and rendered', () => {
		const testData = {...exampleJson, 'cardLabel': 'Journal'};
		const renderedComponent = journalCardHbs(testData);
		document.body.innerHTML = renderedComponent;
		const journalLabel = document.querySelector('.eds-c-card-composable__label');
		expect(journalLabel).toBeTruthy();
		expect(journalLabel.textContent.trim()).toBe('Journal');
	});

	test('Card highlight text can be compiled and rendered', () => {
		document.body.innerHTML = renderedComponent;
		const highlightText = document.querySelector('.u-hide-sr-only');
		expect(highlightText).toBeTruthy();
		expect(highlightText.textContent.trim()).toBe('New content');
	});

	test('Data attributes on container are present', () => {
		document.body.innerHTML = renderedComponent;
		const container = document.querySelector('.eds-c-card-composable');
		expect(container.getAttribute('data-test')).toEqual('yes-test');
	});

	test('Highlight template can be compiled and rendered', () => {
		const testData = {...exampleJson, 'isHighlight': true};
		const renderedComponent = journalCardHbs(testData);

		document.body.innerHTML = renderedComponent;
		const container = document.querySelectorAll('.eds-c-card-composable--highlight-default');

		expect(container).toBeDefined();
		expect(container.length).toBe(1);
	});

	test('Highlight action template can be compiled and rendered', () => {
		const testData = {...exampleJson, 'isHighlightAction': true};
		const renderedComponent = journalCardHbs(testData);

		document.body.innerHTML = renderedComponent;
		const container = document.querySelectorAll('.eds-c-card-composable--highlight-action');

		expect(container).toBeDefined();
		expect(container.length).toBe(1);
	});

	test('Faux link template can be compiled and rendered', () => {
		const testData = {...exampleJson, 'isFauxLink': true};
		const renderedComponent = journalCardHbs(testData);

		document.body.innerHTML = renderedComponent;
		const container = document.querySelectorAll('.eds-c-card-composable--faux-link');

		expect(container).toBeDefined();
		expect(container.length).toBe(1);
	});

	test('Horizontal behaviour active and template can be compiled and rendered', () => {
		const testData = {...exampleJson, 'isHorizontal': true};
		const renderedComponent = journalCardHbs(testData);

		document.body.innerHTML = renderedComponent;
		const container = document.querySelectorAll('.eds-c-card-composable--horizontal');

		expect(container).toBeDefined();
		expect(container.length).toBe(1);
	});

	test('Title is rendered', () => {
		document.body.innerHTML = renderedComponent;
		const title = document.querySelector('.eds-c-card-composable__title');
		const titleSmall = document.querySelector('.eds-c-card-composable__title--small');
		expect(titleSmall).toBeFalsy();
		expect(title && (title.tagName === 'H2' || title.nodeName === 'H2')).toBeTruthy();
		expect(title.textContent.trim()).toBe('Language quality checker');
	});

	test('Title small is rendered', () => {
		const testData = {...exampleJson, "title": {
				"headingLevel": "2",
				"text": "Language quality checker smaller font size",
				"linkUrl": "https://example.com",
				"isSmall": true
			}};
		const renderedComponent = journalCardHbs(testData);

		document.body.innerHTML = renderedComponent;
		const title = document.querySelector('.eds-c-card-composable__title--small');
		expect(title).toBeDefined();
		expect(title.textContent.trim()).toBe('Language quality checker smaller font size');
	});

	test('Link data attributes are correct', () => {
		document.body.innerHTML = renderedComponent;

		const link = document.querySelector('.eds-c-card-composable__title a');
		expect(link.getAttribute('data-track-context')).toEqual('springer-link');
		expect(link.getAttribute('data-track-content-type')).toEqual('collection');
		expect(link.getAttribute('data-track-label')).toEqual('collection');
	});

	test('Card summary text can be compiled and rendered', () => {
		document.body.innerHTML = renderedComponent;
		const summary = document.querySelector('.eds-c-card-composable__summary');
		expect(summary).toBeTruthy();
		expect(summary.textContent.trim()).toBe('Help journal editors understand your manuscript, by making sure your writing is of good quality and clearly communicates what you have done');
	});

	test('Card summary text is not displayed', () => {
		const testData = {
			'dataAttributes': [
				{'name': 'test', 'value': 'yes-test'}
			],
			'srOnlyHighlightText': 'New content',
			'truncateSummary': true,
			'title': {
				'headingLevel': '2',
				'text': 'Language quality checker',
				'linkUrl': 'https://example.com',
				'dataAttributes': [
					{'name': 'track-context', 'value': 'springer-link'},
					{'name': 'track-content-type', 'value': 'collection'},
					{'name': 'track-label', 'value': 'collection'}
				]
			}
		};

		const renderedComponent = journalCardHbs(testData);

		document.body.innerHTML = renderedComponent;

		const summary = document.querySelector('.eds-c-card-composable__summary');
		expect(summary).toBeFalsy();
	});

	test('Card summary truncation text can be compiled and rendered', () => {
		document.body.innerHTML = renderedComponent;
		const summary = document.querySelector('.eds-c-card-composable__summary--truncate-text');
		expect(summary).toBeTruthy();
	});

	describe('EDS Component Card Composable Journal render', () => {
		test('Image attributes are correct', () => {
			const testData = {
				...exampleJson,
				"picture": {
					"sources": [
						{
							"media": "(min-width: 480px)",
							"dimensions": {
								"width": "115px",
								"height": "152px"
							},
							"srcsetUrls": "https://media.springernature.com/w115/springer-static/cover-hires/journal/42452?as=webp, https://media.springernature.com/w230/springer-static/cover-hires/journal/42452?as=webp 2x"
						}
					],
					"img": {
						"src": "https://media.springernature.com/w184/springer-static/cover-hires/journal/42452?as=webp",
						"dimensions": {
							"width": "60px",
							"height": "80px"
						},
						"srcset": "https://media.springernature.com/w184/springer-static/cover-hires/journal/42452?as=webp 2x",
						"alt": "Discover Artificial Intelligence"
					}
				}
			};
			const renderedComponent = journalCardHbs(testData);

			document.body.innerHTML = renderedComponent;

			const picture = document.querySelector('.eds-c-card-composable__journal-cover picture');
			const source = document.querySelector('source');
			const image = picture.querySelector('img');
			expect(source.getAttribute('media')).toBe('(min-width: 480px)');
			expect(source.getAttribute('srcset')).toBe('https://media.springernature.com/w115/springer-static/cover-hires/journal/42452?as=webp, https://media.springernature.com/w230/springer-static/cover-hires/journal/42452?as=webp 2x');
			expect(image.getAttribute('alt')).toEqual('Discover Artificial Intelligence');
			expect(image.getAttribute('src')).toEqual('https://media.springernature.com/w184/springer-static/cover-hires/journal/42452?as=webp');
		});

		test('Card metadata can be compiled and rendered horizontal', () => {
			const testData = {
				...exampleJson,
				"metadata": [
					{
						"title": "Publishing model",
						"text": "Open access"
					},
					{
						"title": "Impact factor",
						"text": "1.456 (2023)"
					},
					{
						"title": "Download",
						"text": "23,789 (2022)"
					},
					{
						"title": "Submission to first decision (median)",
						"text": "Not available"
					}
				]
			};
			const renderedComponent = journalCardHbs(testData);

			document.body.innerHTML = renderedComponent;

			const metadata = document.querySelector('.eds-c-card-composable__metadata-list');
			expect(metadata).toBeTruthy();
			expect(metadata.classList.contains('eds-c-card-composable__metadata-list-horizontal')).toBe(true);
		});

		test('Card metadata can be compiled and rendered multiple data', () => {
			const testData = {
				...exampleJson,
				"metadata": [
					{
						"title": "Publishing model",
						"text": "Open access"
					},
					{
						"title": "Impact factor",
						"text": "1.456 (2023)"
					},
					{
						"title": "Download",
						"text": "23,789 (2022)"
					},
					{
						"title": "Submission to first decision (median)",
						"text": "Not available"
					}
				]
			};
			const renderedComponent = journalCardHbs(testData);

			document.body.innerHTML = renderedComponent;

			const metadataTitles = document.querySelectorAll('.eds-c-card-composable__metadata-list-title');
			const metadataDescriptions = document.querySelectorAll('.eds-c-card-composable__metadata-list-description');
			expect(metadataTitles.length).toEqual(4);
			expect(metadataDescriptions.length).toEqual(4);

			metadataTitles.forEach((metadataTitle, index) => {
				expect(metadataTitle.textContent.trim()).toEqual(testData.metadata[index].title);
			});

			metadataDescriptions.forEach((metadataDescription, index) => {
				expect(metadataDescription.textContent.trim()).toEqual(testData.metadata[index].text);
			});
		});

		test('Card metadata can be compiled and rendered multiple data', () => {
			const renderedComponent = journalCardHbs(exampleJson);

			document.body.innerHTML = renderedComponent;

			const sidebar = document.querySelector('.eds-c-card-composable__sidebar.eds-c-card-composable__sidebar--with-separator');
			const metadataDescriptions = document.querySelector('.eds-c-card-composable__metadata-list.eds-c-card-composable__metadata-list-horizontal');
			expect(sidebar).toBeFalsy();
			expect(metadataDescriptions).toBeFalsy();

		});
	});

	describe('EDS Component Card Composable With Icon render', () => {
		test('Icon is rendered', () => {
			const testData = {
				...exampleJson,
				"iconURL": "/img/icons/eds-i-book-medium.svg#eds-i-book-medium",
			};
			const renderedComponent = cardWithIconHbs(testData);

			document.body.innerHTML = renderedComponent;

			const icon = document.querySelector('.eds-c-card-composable__icon');
			const xlinkHref = icon.querySelector('use').getAttribute('xlink:href');
			expect(icon).toBeDefined();
			expect(xlinkHref).toBe('/img/icons/eds-i-book-medium.svg#eds-i-book-medium');

		});
	});

	describe('EDS Component Card Composable With Metadata render', () => {
		test('Card metadata can be compiled and rendered multiple data', () => {
			const testData = {
				...exampleJson,
				"metadata": [
					{
						"title": "Publishing model",
						"text": "Open access"
					}
				]
			};
			const renderedComponent = cardWithMetadataHbs(testData);

			document.body.innerHTML = renderedComponent;

			const metadata = document.querySelector('.eds-c-card-composable__metadata-list');
			expect(metadata).toBeTruthy();
			expect(metadata.classList.contains('eds-c-card-composable__metadata-list-horizontal')).toBe(false);
		});

		test('Card metadata can be compiled and rendered without sidebar', () => {

			const renderedComponent = cardWithMetadataHbs(exampleJson);

			document.body.innerHTML = renderedComponent;

			const sidebar = document.querySelector('.eds-c-card-composable__sidebar.eds-c-card-composable__sidebar--with-separator');
			const metadata = document.querySelector('.eds-c-card-composable__metadata-list');
			expect(sidebar).toBeFalsy();
			expect(metadata).toBeFalsy();
		});
	});

	describe('EDS Component Card Composable With Image render', () => {
		test('Card Image is rendered', () => {
			const testData = {
				...exampleJson,
				"picture": {
					"sources": [
						{
							"media": "(min-width: 768px)",
							"dimensions": {
								"width": "400px",
								"height": "200px"
							},
							"srcsetUrls": "https://picsum.photos/id/704/400/200?as=webp, https://picsum.photos/id/704/800/400?as=webp 2x, https://picsum.photos/id/704/1200/800?as=webp 3x"
						},
						{
							"media": "(min-width: 1024px)",
							"dimensions": {
								"width": "600px",
								"height": "400px"
							},
							"srcsetUrls": "https://picsum.photos/id/704/600/400?as=webp, https://picsum.photos/id/704/1200/800?as=webp 2x, https://picsum.photos/id/704/1800/1200?as=webp 3x"
						}
					],
					"img": {
						"src": "https://picsum.photos/id/704/600/400?as=webp",
						"dimensions": {
							"width": "600px",
							"height": "400px"
						},
						"srcset": "https://picsum.photos/id/704/1200/800?as=webp 2x",
						"alt": "Image alternate text"
					}
				}
			};
			const renderedComponent = cardWithImageHbs(testData);

			document.body.innerHTML = renderedComponent;

			const picture = document.querySelector('.eds-c-card-composable__picture');
			const pictureTag = picture.querySelector('picture');
			expect(picture).toBeDefined();
			expect(pictureTag && (pictureTag.tagName === 'PICTURE' || pictureTag.nodeName === 'PICTURE')).toBeTruthy();

		});

		test('Card image is rendered', () => {
			const testData = {
				...exampleJson,
				"image": {
					"src": "https://picsum.photos/id/704/400/400",
					"alt": "descriptive alternative text",
					"aspectRatio": "4/3"
				}
			};
			const renderedComponent = cardWithImageHbs(testData);

			document.body.innerHTML = renderedComponent;

			const imageContainer = document.querySelector('.eds-c-card-composable__image');
			const image = imageContainer.querySelector('img')
			expect(imageContainer).toBeDefined();
			expect(image.getAttribute('src')).toBe("https://picsum.photos/id/704/400/400");

		});
	});
});
