const fs = require('node:fs');
const path = require('node:path');
const schema = require('./data/eds-c-checkbox.schema.json');
const dataAttributesSchema = require('../eds-c-data-attributes/data/eds-c-data-attributes.schema.json');
const exampleJson = require('./data/eds-c-checkbox.example.json');
const inputSchema = require('../eds-c-input/data/eds-c-input.schema.json');
const hintSchema = require('../eds-c-hint/data/eds-c-hint.schema.json');
const labelSchema = require('../eds-c-label/data/eds-c-label.schema.json');
const errorMessageSchema = require('../eds-c-error-message/data/eds-c-error-message.schema.json');
const handlebars = require('handlebars');

const {findTemplates} = require('../../development/tests/templateLoader.js');
const { validateSchema } = require('../../development/tests/validate-schema');
findTemplates(['eds-c-checkbox', 'eds-c-hint', 'eds-c-label', 'eds-c-error-message', 'eds-c-data-attributes']).load(handlebars);

const componentTemplate = '{{> eds-c-checkbox}}';
const componentHbs = handlebars.compile(componentTemplate);
const renderedComponent = componentHbs(exampleJson);

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

describe('Label 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 valid = validateSchema(schema, exampleJson, [
            { name: 'eds-c-data-attributes', schema: dataAttributesSchema },
            { name: 'eds-c-input', schema: inputSchema },
            { name: 'eds-c-label', schema: labelSchema },
            { name: 'eds-c-hint', schema: hintSchema },
            { name: 'eds-c-error-message', schema: errorMessageSchema }
        ]);
        expect(valid).toBeTruthy();
    });
    
    test('Title text can be compiled and rendered', () => {
        const testData = { ...exampleJson, checkboxTitleText: 'Checkbox title text' };
        document.body.innerHTML = componentHbs(testData);
        const titleText = document.querySelector('.eds-c-checkbox__title');
        expect(titleText).not.toBeNull();
        expect(titleText.textContent.trim()).toBe('Checkbox title text');
    });

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

        const checkboxElement = document.querySelector('input[type="checkbox"]');
        expect(checkboxElement.getAttribute('id')).toEqual('eds-checkbox');
        expect(checkboxElement.getAttribute('name')).toEqual('checkbox');
    });

    test('Checkbox attributes are correct', () => {
        const testData = { ...exampleJson, value: 'checkbox-value' };
        document.body.innerHTML = componentHbs(testData);

        const checkboxElement = document.querySelector('input[type="checkbox"]');
        expect(checkboxElement.getAttribute('value')).toEqual('checkbox-value');
    });

    test('Checkbox label is rendered', () => {
        document.body.innerHTML = renderedComponent;

        const labelElement = document.querySelector('input[type="checkbox"] + label');
        expect(labelElement).not.toBeNull();
        expect(labelElement.textContent.trim()).toContain('Agree to our terms');
    });

    test('Checkbox hint is rendered', () => {
        document.body.innerHTML = renderedComponent;

        const hintElement = document.querySelector('.eds-c-hint');
        expect(hintElement).not.toBeNull();
        expect(hintElement.textContent.trim()).toBe('You should have read these. Read them, then agree to them.');
    });

    test('Checkbox error is rendered', () => {
        document.body.innerHTML = renderedComponent;

        const errorElement = document.querySelector('.eds-c-error-message');
        const checkboxElement = document.querySelector('input[type="checkbox"]');
        expect(errorElement).not.toBeNull();
        expect(errorElement.textContent.trim()).toBe('Agree to the terms to continue');
        expect(checkboxElement.hasAttribute('invalid')).toBeTruthy();
        expect(checkboxElement.getAttribute('aria-invalid')).toBeTruthy();
        expect(checkboxElement.getAttribute('aria-describedby')).toBe('error-eds-checkbox-one');
    });

    test('Checkbox required is rendered', () => {
        const testData = { ...exampleJson, required: true };
        document.body.innerHTML = componentHbs(testData);

        const checkboxElement = document.querySelector('input[type="checkbox"]');
        expect(checkboxElement.hasAttribute('required')).toBeTruthy();
        expect(checkboxElement.getAttribute('aria-required')).toBeTruthy();
    });

    test('Checkbox disabled is rendered', () => {
        const testData = { ...exampleJson, disabled: true };
        document.body.innerHTML = componentHbs(testData);

        const checkboxElement = document.querySelector('input[type="checkbox"]');
        expect(checkboxElement.hasAttribute('disabled')).toBeTruthy();
    });

    test('Checkbox checked is rendered', () => {
        const testData = { ...exampleJson, checked: true };
        document.body.innerHTML = componentHbs(testData);

        const checkboxElement = document.querySelector('input[type="checkbox"]');
        expect(checkboxElement.hasAttribute('checked')).toBeTruthy();
    });

    test('Checkbox tabindex is rendered', () => {
        const testData = { ...exampleJson, tabindex: 1 };
        document.body.innerHTML = componentHbs(testData);

        const checkboxElement = document.querySelector('input[type="checkbox"]');
        expect(checkboxElement.getAttribute('tabindex')).toBe('1');
    });

    test('Checkbox title is rendered', () => {
        const testData = { ...exampleJson, title: 'checkbox title' };
        document.body.innerHTML = componentHbs(testData);

        const checkboxElement = document.querySelector('input[type="checkbox"]');
        expect(checkboxElement.getAttribute('title')).toBe('checkbox title');
    });

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

        const checkboxElement = document.querySelector('input[type="checkbox"]');
        expect(checkboxElement.getAttribute('data-test')).toEqual('checkbox-test');
        expect(checkboxElement.getAttribute('data-track-context')).toEqual('springer-link');
        expect(checkboxElement.getAttribute('data-track-content-type')).toEqual('collection');
        expect(checkboxElement.getAttribute('data-track-label')).toEqual('collection');
    });

    test('Checkbox link is rendered with correct attributes', () => {
        const testData = { 
            ...exampleJson, 
            checkboxLink: {
                url: 'https://example.com/terms',
                text: 'Terms and Conditions'
            }
        };
        document.body.innerHTML = componentHbs(testData);

        const linkElement = document.querySelector('.eds-c-checkbox__link');
        expect(linkElement).not.toBeNull();
        expect(linkElement.getAttribute('href')).toBe('https://example.com/terms');
        expect(linkElement.textContent.trim()).toBe('Terms and Conditions');
    });

    test('Checkbox link renders with data attributes', () => {
        const testData = { 
            ...exampleJson, 
            checkboxLink: {
                url: 'https://example.com/terms',
                text: 'Terms and Conditions',
                dataAttributes: [
                    { name: 'track-context', value: 'checkbox-link' },
                    { name: 'track-content-type', value: 'link' },
                    { name: 'test', value: 'checkbox-link-test' }
                ]
            }
        };
        document.body.innerHTML = componentHbs(testData);

        const linkElement = document.querySelector('.eds-c-checkbox__link');
        expect(linkElement).not.toBeNull();
        expect(linkElement.getAttribute('data-track-context')).toBe('checkbox-link');
        expect(linkElement.getAttribute('data-track-content-type')).toBe('link');
        expect(linkElement.getAttribute('data-test')).toBe('checkbox-link-test');
    });

    test('Checkbox link is not rendered when checkboxLink is not provided', () => {
        const testData = { ...exampleJson };
        delete testData.checkboxLink;
        document.body.innerHTML = componentHbs(testData);

        const linkElement = document.querySelector('.eds-c-checkbox__link');
        expect(linkElement).toBeNull();
    });

    test('Checkbox small variant applies correct class', () => {
        const testData = { 
            ...exampleJson, 
            small: true,
            label: {
                ...exampleJson.label,
                cssClass: "eds-c-checkbox__label eds-c-checkbox__label--small"
            }
        };
        document.body.innerHTML = componentHbs(testData);

        const labelElement = document.querySelector('label');
        expect(labelElement.classList.contains('eds-c-checkbox__label--small')).toBeTruthy();
        expect(labelElement.classList.contains('eds-c-checkbox__label')).toBeTruthy();
    });

    test('Checkbox default variant does not have small class', () => {
        const testData = { ...exampleJson, small: false };
        document.body.innerHTML = componentHbs(testData);

        const labelElement = document.querySelector('label');
        expect(labelElement.classList.contains('eds-c-checkbox__label--small')).toBeFalsy();
        expect(labelElement.classList.contains('eds-c-checkbox__label')).toBeTruthy();
    });
    
    test('Template passes basic HTML accessibility', async () => {
        expect(await axe(renderedComponent)).toHaveNoViolations();
    });
});