const smiLess = require('../less');

test('should resolve file import and compile css', async () => {
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `@import "../file-one.less";`
    },
    {
      name: '/file-one.less',
      content: `@import "./styles/content.less";`
    },
    {
      name: '/styles/content.less',
      content: `body {background: darken(#09F, 20%);}`
    }
  ]);
  expect(result.css).toEqual('body {\n  background: #005c99;\n}\n');
});

test('should resolve file import and compile css without leading slash', async () => {
  const result = await smiLess([
    {
      name: 'styles/main.less',
      content: `@import "../file-one.less";`
    },
    {
      name: 'file-one.less',
      content: `@import "./styles/content.less";`
    },
    {
      name: 'styles/content.less',
      content: `body {background: darken(#09F, 20%);}`
    }
  ]);
  expect(result.css).toEqual('body {\n  background: #005c99;\n}\n');
});

test('should throw file not found', () =>
  expect(
    smiLess([
      {
        name: '/styles/main.less',
        content: `@import "../styles/file-one.less";`
      }
    ])
  ).rejects.toThrow('File not found /styles/file-one.less'));

test('should leave full url import', async () => {
  await smiLess([
    {
      name: '/styles/main.less',
      content: `@import url("https://fonts.googleapis.com/css2?family=Dancing+Script&display=swap");`
    }
  ]);
});

test('should extract variables as CSS custom properties', async () => {
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `
        @color-primary: #39355b;
        @size-base: 16px;
        body { color: @color-primary; }
      `
    }
  ]);

  expect(result.css).toContain('og-smi {');
  expect(result.css).toContain('--og-smi-color-primary: #39355b;');
  expect(result.css).toContain('--og-smi-size-base: 16px;');
});

test('should resolve variable references to final values', async () => {
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `
        @color-tertiary: #17132f;
        @color-badge-text: @color-tertiary;
      `
    }
  ]);

  expect(result.css).toContain('--og-smi-color-tertiary: #17132f;');
  expect(result.css).toContain('--og-smi-color-badge-text: #17132f;');
});

test('should resolve derived variables using the override value', async () => {
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `
        @import './design-tokens.less';

        og-smi {
          @import './variables.less';
          color: @color-badge-text;
        }
      `
    },
    {
      name: '/styles/design-tokens.less',
      content: `
        @color-primary: #39355b;
        @color-badge-text: @color-primary;
      `
    },
    {
      name: '/styles/variables.less',
      content: `@color-primary: #ff0000;`
    }
  ]);

  // color-primary is overridden by variables.less
  expect(result.css).toContain('--og-smi-color-primary: #ff0000;');
  // color-badge-text references color-primary, so it should also resolve to the override value
  expect(result.css).toContain('--og-smi-color-badge-text: #ff0000;');
  // verify Less itself computes the same value when the variable is used in a rule
  expect(result.css).toContain('color: #ff0000;');
});

test.each([
  ['variables.less inside root block', 'og-smi { @import "./variables.less"; }'], // this is how the templates structure their main.less by default
  ['variables.less before root block', '@import "./variables.less";']
])('should resolve variables.less imports when %s', async (_, variablesContent) => {
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `
        @import './design-tokens.less';

        ${variablesContent}
      `
    },
    {
      name: '/styles/design-tokens.less',
      content: `@color-primary: #39355b;`
    },
    {
      name: '/styles/variables.less',
      content: `@color-primary: #ff0000;`
    }
  ]);

  // Should use the override value from variables.less
  expect(result.css).toContain('--og-smi-color-primary: #ff0000;');
  expect(result.css).not.toContain('--og-smi-color-primary: #39355b;');
});

test('should respect Less scoping when a nested selector re-declares a variable that og-smi already overrides', async () => {
  // og-smi overrides @color-primary to #ff0000. A deeper nested selector (.nested)
  // re-declares it as #00ff00, but that declaration is scoped to .nested and should
  // not affect the og-smi scope. #ff0000 should win for both the extracted value and
  // any derived variable (e.g. @color-badge-text: @color-primary).
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `
        @color-primary: #39355b;
        @color-badge-text: @color-primary;

        og-smi {
          @color-primary: #ff0000;

          .nested {
            @color-primary: #00ff00;
          }
        }
      `
    }
  ]);

  expect(result.css).toContain('--og-smi-color-primary: #ff0000;');
  expect(result.css).toContain('--og-smi-color-badge-text: #ff0000;');
});

test('should use only og-smi as override scope, ignoring other top-level blocks', async () => {
  // og-smi overrides @color-primary to #ff0000. A sibling block (other-block) overrides
  // it to #00ff00, but it is not og-smi so it should be ignored. #ff0000 should win for
  // both the extracted value and any derived variable (@color-badge-text).
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `
        @color-primary: #39355b;
        @color-badge-text: @color-primary;

        og-smi {
          @color-primary: #ff0000;
        }

        other-block {
          @color-primary: #00ff00;
        }
      `
    }
  ]);

  expect(result.css).toContain('--og-smi-color-primary: #ff0000;');
  expect(result.css).toContain('--og-smi-color-badge-text: #ff0000;');
});

test('should resolve color functions to computed values', async () => {
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `
        @base-color: #09F;
        @dark-color: darken(@base-color, 20%);
      `
    }
  ]);

  expect(result.css).toContain('--og-smi-dark-color: #005c99;');
});

test('should prepend og-smi block to CSS output', async () => {
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `
        @color-primary: #39355b;
        body { color: @color-primary; }
      `
    }
  ]);

  const rootIndex = result.css.indexOf('og-smi {');
  const bodyIndex = result.css.indexOf('body {');

  expect(rootIndex).toBeGreaterThan(-1);
  expect(bodyIndex).toBeGreaterThan(-1);
  expect(rootIndex).toBeLessThan(bodyIndex);
});

test('should apply smi- prefix to custom properties', async () => {
  const result = await smiLess([
    {
      name: '/styles/main.less',
      content: `@color-primary: #39355b;`
    }
  ]);

  expect(result.css).toContain('--og-smi-color-primary');
  expect(result.css).not.toContain('--color-primary:');
});
