import postcss from 'postcss'
import { runWithSourceMaps as run, html, css, map } from './util/run'
import { parseSourceMaps } from './util/source-maps'

it('apply generates source maps', async () => {
  let config = {
    content: [
      {
        raw: html`
          <div class="with-declaration"></div>
          <div class="with-comment"></div>
          <div class="just-apply"></div>
        `,
      },
    ],
    corePlugins: { preflight: false },
  }

  let input = css`
    .with-declaration {
      background-color: red;
      @apply h-4 w-4 bg-green-500;
    }

    .with-comment {
      /* sourcemap will work here too */
      @apply h-4 w-4 bg-red-500;
    }

    .just-apply {
      @apply h-4 w-4 bg-black;
    }
  `

  let result = await run(input, config)
  let { sources, annotations } = parseSourceMaps(result)

  // All CSS generated by Tailwind CSS should be annotated with source maps
  // And always be able to point to the original source file
  expect(sources).not.toContain('<no source>')
  expect(sources.length).toBe(1)

  expect(annotations).toMatchSnapshot()
})

it('preflight + base have source maps', async () => {
  let config = {
    content: [],
  }

  let input = css`
    @tailwind base;
  `

  let result = await run(input, config)
  let { sources, annotations } = parseSourceMaps(result)

  // All CSS generated by Tailwind CSS should be annotated with source maps
  // And always be able to point to the original source file
  expect(sources).not.toContain('<no source>')
  expect(sources.length).toBe(1)

  expect(annotations).toMatchSnapshot()
})

it('utilities have source maps', async () => {
  let config = {
    content: [{ raw: `text-red-500` }],
  }

  let input = css`
    @tailwind utilities;
  `

  let result = await run(input, config)
  let { sources, annotations } = parseSourceMaps(result)

  // All CSS generated by Tailwind CSS should be annotated with source maps
  // And always be able to point to the original source file
  expect(sources).not.toContain('<no source>')
  expect(sources.length).toBe(1)

  expect(annotations).toStrictEqual(['2:4 -> 1:0', '2:4-23 -> 2:4-24', '2:4 -> 3:4', '2:23 -> 4:0'])
})

it('components have source maps', async () => {
  let config = {
    content: [{ raw: `container` }],
  }

  let input = css`
    @tailwind components;
  `

  let result = await run(input, config)
  let { sources, annotations } = parseSourceMaps(result)

  // All CSS generated by Tailwind CSS should be annotated with source maps
  // And always be able to point to the original source file
  expect(sources).not.toContain('<no source>')
  expect(sources.length).toBe(1)

  expect(annotations).toMatchSnapshot()
})

it('source maps for layer rules are not rewritten to point to @tailwind directives', async () => {
  let config = {
    content: [{ raw: `font-normal foo hover:foo` }],
  }

  let utilitiesFile = postcss.parse(
    css`
      @tailwind utilities;
    `,
    { from: 'components.css', map: { prev: map } }
  )

  let mainCssFile = postcss.parse(
    css`
      @layer utilities {
        .foo {
          background-color: red;
        }
      }
    `,
    { from: 'input.css', map: { prev: map } }
  )

  // Just pretend that there's an @import in `mainCssFile` that imports the nodes from `utilitiesFile`
  let input = postcss.root({
    nodes: [...utilitiesFile.nodes, ...mainCssFile.nodes],
    source: mainCssFile.source,
  })

  let result = await run(input, config)

  let { sources, annotations } = parseSourceMaps(result)

  // All CSS generated by Tailwind CSS should be annotated with source maps
  // And always be able to point to the original source file
  expect(sources).not.toContain('<no source>')

  // And we should see that the source map for the layer rule is not rewritten
  // to point to the @tailwind directive but instead points to the original
  expect(sources.length).toBe(2)
  expect(sources).toEqual(['components.css', 'input.css'])

  expect(annotations).toMatchSnapshot()
})
