import {expect} from 'chai';
import {convertToPixels, getDeviceDPI} from "../../../source/dom/dimension.mjs";
import {getWindow} from "../../../source/dom/util.mjs";
import {initJSDOM, isBrowser, JSDOMExport as JSDOM} from "../../util/jsdom.mjs";
import {getGlobal} from "../../../source/types/global.mjs";
import {detectRuntimeEnvironment} from "../../../source/util/runtime.mjs";


function getMockWindow(dpi) {

    if(detectRuntimeEnvironment() === 'browser') {
        return getWindow();
    }
    
    
    const dom = new JSDOM('', {
        pretendToBeVisual: true,
        resources: 'usable',
    });

    dom.window.matchMedia = (query) => {
        const dpiRegex = /\(max-resolution: (\d+)dpi\)/;
        const match = query.match(dpiRegex);

        if (match) {
            const maxDpi = parseInt(match[1], 10);
            return {matches: dpi <= maxDpi};
        }

        return {matches: false};
    };

    return dom.window;
}

describe('dimension', () => {
    let currentEnvironment;

    before(function (done) {
        initJSDOM().then(() => {
            //chaiDom(getDocument());
            done();
        });
    })

    beforeEach(() => {

        const testDpi = 96;
        const testWindow = getMockWindow(testDpi);
        getGlobal().window = testWindow;

    });

    afterEach(() => {
        delete getGlobal().window;
    });

    describe('convertToPixels', () => {
        it('should correctly convert px values', () => {
            const result = convertToPixels('100px');
            expect(result).to.equal(100);
        });

        it("should throw an error when the input value has an invalid format", () => {
            const invalidValue = "invalid_value";

            const errorFn = () => {
                convertToPixels(invalidValue);
            };

            expect(errorFn).to.throw(Error, `Invalid value format: ${invalidValue}`);
        });

        it("should handle negative values correctly", () => {
            const negativeValue = "-10px";
            const expectedResult = -10;

            const result = convertToPixels(negativeValue);

            expect(result).to.equal(expectedResult);
        });

        it('should correctly convert em values', () => {
            const testElement = document.createElement('div');
            testElement.style.fontSize = '16px';
            document.body.appendChild(testElement);

            const result = convertToPixels('2em', testElement, testElement);
            expect(result).to.equal(32);

            document.body.removeChild(testElement);
        });

        it('should correctly convert rem values', () => {
            const testElement = document.createElement('div');
            testElement.style.fontSize = '16px';
            document.documentElement.appendChild(testElement);

            const result = convertToPixels('2rem', testElement);
            expect(result).to.equal(32);

            document.documentElement.removeChild(testElement);
        });

        it('should correctly convert percentage values', () => {
            const testElement = document.createElement('div');
            testElement.style.width = '500px';
            document.body.appendChild(testElement);

            const result = convertToPixels('50%', testElement);
            expect(result).to.equal(250);

            document.body.removeChild(testElement);
        });

        it('should throw an error for unsupported units', () => {
            expect(() => convertToPixels('10unsupportedUnit')).to.throw('Unsupported unit: unsupportedUnit');
        });
    });


    describe('getDeviceDPI', () => {
        it('should return the correct device DPI', () => {
            const testDpi = 96;
            const testWindow = getMockWindow(testDpi);
            getGlobal().window = testWindow;

            const deviceDpi = getDeviceDPI();
            expect(deviceDpi).to.equal(testDpi * testWindow.devicePixelRatio);

            delete getGlobal().window;
        });

        it('should cache the result and return the same value', () => {
            const testDpi = 96;
            const testWindow = getMockWindow(testDpi);
            getGlobal().window = testWindow;

            const deviceDpi1 = getDeviceDPI();
            const deviceDpi2 = getDeviceDPI();
            expect(deviceDpi1).to.equal(deviceDpi2);

            delete getGlobal().window;
        });
    });

});