import { testSuite, expect } from 'manten';
import { createFixture } from 'fs-fixture';
import { createTsconfigJson } from '../../../../utils/fixture-helpers.js';
import { getTscTsconfig } from '../../../../utils/typescript-helpers.js';
import { parseTsconfig } from '#get-tsconfig';

export default testSuite(({ describe }) => {
	describe('resolves', ({ test, describe, runTestSuite }) => {
		test('handles missing extends', async () => {
			await using fixture = await createFixture({
				'file.ts': '',
				'tsconfig.json': createTsconfigJson({
					extends: 'missing-package',
				}),
			});

			expect(
				() => parseTsconfig(fixture.getPath('tsconfig.json')),
			).toThrow('File \'missing-package\' not found.');
		});

		describe('circularity', ({ test }) => {
			test('self extend', async ({ onTestFinish }) => {
				await using fixture = await createFixture({
					'tsconfig.json': createTsconfigJson({
						extends: './tsconfig.json',
					}),
					'file.ts': '',
				});
				onTestFinish(() => fixture.rm());

				const errorMessage = 'Circularity detected while resolving configuration';
				await expect(
					getTscTsconfig(fixture.path),
				).rejects.toThrow(errorMessage);
				expect(
					() => parseTsconfig(fixture.getPath('tsconfig.json')),
				).toThrow(errorMessage);
			});

			test('recursive', async ({ onTestFinish }) => {
				await using fixture = await createFixture({
					'base.json': createTsconfigJson({
						extends: './tsconfig.json',
					}),
					'tsconfig.json': createTsconfigJson({
						extends: './base.json',
					}),
				});
				onTestFinish(() => fixture.rm());

				expect(
					() => parseTsconfig(fixture.getPath('tsconfig.json')),
				).toThrow('Circularity detected while resolving configuration:');
			});
		});

		test('extends array with common base', async ({ onTestFinish }) => {
			await using fixture = await createFixture({
				'base.json': createTsconfigJson({}),
				'tsconfig-b.json': createTsconfigJson({
					extends: './base.json',
				}),
				'tsconfig-a.json': createTsconfigJson({
					extends: './base.json',
				}),
				'tsconfig.json': createTsconfigJson({
					extends: [
						'./tsconfig-a.json',
						'./tsconfig-b.json',
					],
				}),
				'file.ts': '',
			});
			onTestFinish(() => fixture.rm());

			const expectedTsconfig = await getTscTsconfig(fixture.path);
			delete expectedTsconfig.files;

			const tsconfig = parseTsconfig(fixture.getPath('tsconfig.json'));
			expect(tsconfig).toStrictEqual(expectedTsconfig);
		});

		runTestSuite(import('./relative-path.spec.js'));
		runTestSuite(import('./absolute-path.spec.js'));
		runTestSuite(import('./node-modules.spec.js'));
		runTestSuite(import('./symbolic-link.spec.js'));
	});
});
