import { compile } from '@tsrx/ripple';

describe('CSS :global scoping verification', () => {
	it('verifies scoped styles are isolated', () => {
		const source = `
export function Test() @{
	<>
		<div class="scoped">{'content'}</div>

		<style>
			.scoped {
				color: red;
			}
		</style>
	</>
}`;
		const { css } = compile(source, 'test.tsrx');

		expect(css).toMatch(/\.scoped\.tsrx-[a-z0-9]+/);
		expect(css).not.toContain('.scoped {');
	});

	it('verifies :global styles bypass scoping', () => {
		const source = `
export function Test() @{
	<>
		<div class="global">{'content'}</div>

		<style>
			:global(.global) {
				color: red;
			}
		</style>
	</>
}`;
		const { css } = compile(source, 'test.tsrx');

		expect(css).toContain('.global {');
		expect(css).not.toMatch(/\.global\.tsrx-[a-z0-9]+/);
	});

	it('verifies mixed local and global maintain proper scoping', () => {
		const source = `
export function Test() @{
	<>
		<div class="outer">
			<span class="inner">{'content'}</span>
		</div>

		<style>
			.outer {
				color: red;
			}

			:global(.outer) {
				color: blue;
			}

			.outer .inner {
				color: green;
			}

			:global(.outer) .inner {
				color: yellow;
			}

			.outer :global(.inner) {
				color: purple;
			}
		</style>
	</>
}`;
		const { css } = compile(source, 'test.tsrx');

		expect(css).toMatch(/\.outer\.tsrx-[a-z0-9]+ {/);
		expect(css).toMatch(/\.outer {/);
		expect(css).toMatch(/\.outer\.tsrx-[a-z0-9]+ \.inner:where\(\.tsrx-[a-z0-9]+\) {/);
		expect(css).toMatch(/\.outer \.inner\.tsrx-[a-z0-9]+/);
		expect(css).toMatch(/\.outer\.tsrx-[a-z0-9]+ \.inner {/);
	});

	it('verifies :global blocks scope all nested selectors globally', () => {
		const source = `
export function Test() @{
	<>
		<div>
			<span>
				<button>{'click'}</button>
			</span>
		</div>

		<style>
			:global {
				div {
					color: red;
				}

				span {
					color: blue;
				}

				button {
					color: green;
				}
			}
		</style>
	</>
}`;
		const { css } = compile(source, 'test.tsrx');

		expect(css).toContain('div {');
		expect(css).toContain('span {');
		expect(css).toContain('button {');
		expect(css).not.toMatch(/div\.tsrx-[a-z0-9]+/);
		expect(css).not.toMatch(/span\.tsrx-[a-z0-9]+/);
		expect(css).not.toMatch(/button\.tsrx-[a-z0-9]+/);
	});

	it('verifies element selectors are scoped by default', () => {
		const source = `
export function Test() @{
	<>
		<div>
			<span>
				<button>{'click'}</button>
			</span>
		</div>

		<style>
			div {
				color: red;
			}

			span {
				color: blue;
			}

			button {
				color: green;
			}
		</style>
	</>
}`;
		const { css } = compile(source, 'test.tsrx');

		expect(css).toMatch(/div\.tsrx-[a-z0-9]+/);
		expect(css).toMatch(/span\.tsrx-[a-z0-9]+/);
		expect(css).toMatch(/button\.tsrx-[a-z0-9]+/);
	});

	it('verifies :global() escapes only the wrapped selector', () => {
		const source = `
export function Test() @{
	<>
		<div class="local">
			<span class="global">
				<button class="local">{'click'}</button>
			</span>
		</div>

		<style>
			.local :global(.global .local) {
				color: red;
			}
		</style>
	</>
}`;
		const { css } = compile(source, 'test.tsrx');

		expect(css).toMatch(/\.local\.tsrx-[a-z0-9]+ \.global \.local {/);
		expect(css).not.toMatch(/\.global\.tsrx-[a-z0-9]+/);
	});

	it('verifies multiple components have different scope hashes', () => {
		const source1 = `
export function Test1() @{
	<>
		<div class="test">{'one'}</div>

		<style>
			.test {
				color: red;
			}
		</style>
	</>
}`;
		const source2 = `
export function Test2() @{
	<>
		<div class="test">{'two'}</div>

		<style>
			.test {
				color: blue;
			}
		</style>
	</>
}`;
		const { css: css1 } = compile(source1, 'test1.tsrx');
		const { css: css2 } = compile(source2, 'test2.tsrx');

		expect(css1).toMatch(/\.test\.tsrx-[a-z0-9]+/);
		expect(css2).toMatch(/\.test\.tsrx-[a-z0-9]+/);

		const hash1Match = css1.match(/\.test\.tsrx-([a-z0-9]+)/);
		const hash2Match = css2.match(/\.test\.tsrx-([a-z0-9]+)/);

		expect(hash1Match).toBeTruthy();
		expect(hash2Match).toBeTruthy();

		if (hash1Match && hash2Match) {
			expect(hash1Match[1]).not.toBe(hash2Match[1]);
		}
	});

	it('verifies :global styles are consistent across components', () => {
		const source1 = `
export function Test1() @{
	<>
		<div class="global">{'one'}</div>

		<style>
			:global(.global) {
				color: red;
			}
		</style>
	</>
}`;
		const source2 = `
export function Test2() @{
	<>
		<div class="global">{'two'}</div>

		<style>
			:global(.global) {
				color: blue;
			}
		</style>
	</>
}`;
		const { css: css1 } = compile(source1, 'test1.tsrx');
		const { css: css2 } = compile(source2, 'test2.tsrx');

		expect(css1).toContain('.global {');
		expect(css1).not.toMatch(/\.global\.tsrx-[a-z0-9]+/);
		expect(css2).toContain('.global {');
		expect(css2).not.toMatch(/\.global\.tsrx-[a-z0-9]+/);
	});
});
