/**
 * @vitest-environment jsdom
 */
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const __dirname = dirname(fileURLToPath(import.meta.url));
const SCRIPT_PATH = join(__dirname, '../../static/assets/js/cookie-consent.js');

function createBannerDOM() {
    const banner = document.createElement('div');
    banner.id = 'cookie-banner';

    const acceptBtn = document.createElement('button');
    acceptBtn.type = 'button';
    acceptBtn.dataset.consent = 'accept';

    const rejectBtn = document.createElement('button');
    rejectBtn.type = 'button';
    rejectBtn.dataset.consent = 'reject';

    banner.appendChild(acceptBtn);
    banner.appendChild(rejectBtn);
    document.body.appendChild(banner);

    return { banner, acceptBtn, rejectBtn };
}

describe('cookie-consent.js', () => {
    const STORAGE_KEY = 'mifi-ventures-cookie-consent';
    let dom: ReturnType<typeof createBannerDOM>;

    beforeEach(() => {
        // Ensure a fresh DOM and storage for each test
        document.body.innerHTML = '';
        window.localStorage.clear();
        dom = createBannerDOM();

        const code = readFileSync(SCRIPT_PATH, 'utf8');
        eval(code);
        document.dispatchEvent(new Event('DOMContentLoaded'));
    });

    afterEach(() => {
        dom.banner.remove();
        vi.restoreAllMocks();
        window.localStorage.clear();
    });

    it('shows banner when no preference is stored', () => {
        expect(dom.banner.classList.contains('is-visible')).toBe(true);
    });

    it('hides banner and loads analytics when preference is "accept"', () => {
        document.body.innerHTML = '';
        window.localStorage.setItem(STORAGE_KEY, 'accept');
        dom = createBannerDOM();

        const appendChildSpy = vi.spyOn(document.head, 'appendChild');

        const code = readFileSync(SCRIPT_PATH, 'utf8');
        eval(code);
        document.dispatchEvent(new Event('DOMContentLoaded'));

        expect(dom.banner.classList.contains('is-visible')).toBe(false);
        expect(appendChildSpy).toHaveBeenCalled();
        const urls = appendChildSpy.mock.calls
            .map((args) => (args[0] as HTMLScriptElement).src)
            .filter(Boolean);
        expect(urls.some((src) => src.includes('googletagmanager.com'))).toBe(true);
    });

    it('hides banner when preference is "reject" and does not load analytics', () => {
        document.body.innerHTML = '';
        window.localStorage.setItem(STORAGE_KEY, 'reject');
        dom = createBannerDOM();

        const appendChildSpy = vi.spyOn(document.head, 'appendChild');

        const code = readFileSync(SCRIPT_PATH, 'utf8');
        eval(code);
        document.dispatchEvent(new Event('DOMContentLoaded'));

        expect(dom.banner.classList.contains('is-visible')).toBe(false);
        const urls = appendChildSpy.mock.calls
            .map((args) => (args[0] as HTMLScriptElement).src)
            .filter(Boolean);
        expect(urls.some((src) => src.includes('googletagmanager.com'))).toBe(false);
    });

    it('stores "accept" in localStorage, hides banner, and loads analytics on accept click', () => {
        const appendChildSpy = vi.spyOn(document.head, 'appendChild');

        dom.acceptBtn.click();

        expect(window.localStorage.getItem(STORAGE_KEY)).toBe('accept');
        expect(dom.banner.classList.contains('is-visible')).toBe(false);
        expect(appendChildSpy).toHaveBeenCalled();
    });

    it('stores "reject" in localStorage and hides banner on reject click', () => {
        const appendChildSpy = vi.spyOn(document.head, 'appendChild');

        dom.rejectBtn.click();

        expect(window.localStorage.getItem(STORAGE_KEY)).toBe('reject');
        expect(dom.banner.classList.contains('is-visible')).toBe(false);
        const urls = appendChildSpy.mock.calls
            .map((args) => (args[0] as HTMLScriptElement).src)
            .filter(Boolean);
        expect(urls.some((src) => src.includes('googletagmanager.com'))).toBe(false);
    });
});

