import fs from 'fs'
import path from 'path'
import postcss from 'postcss'
import tailwind from '../src/index'
import { cjsConfigFile, defaultConfigFile } from '../src/constants'
import inTempDirectory from '../jest/runInTempDirectory'

test('it uses the values from the custom config file', () => {
  return postcss([tailwind(path.resolve(`${__dirname}/fixtures/custom-config.js`))])
    .process(
      `
        @responsive {
          .foo {
            color: blue;
          }
        }
      `,
      { from: undefined }
    )
    .then((result) => {
      const expected = `
        .foo {
          color: blue;
        }
        @media (min-width: 400px) {
          .mobile\\:foo {
            color: blue;
          }
        }
      `
      expect(result.css).toMatchCss(expected)
    })
})

test('custom config can be passed as an object', () => {
  return postcss([
    tailwind({
      theme: {
        screens: {
          mobile: '400px',
        },
      },
    }),
  ])
    .process(
      `
        @responsive {
          .foo {
            color: blue;
          }
        }
      `,
      { from: undefined }
    )
    .then((result) => {
      const expected = `
        .foo {
          color: blue;
        }
        @media (min-width: 400px) {
          .mobile\\:foo {
            color: blue;
          }
        }
      `

      expect(result.css).toMatchCss(expected)
    })
})

test('custom config path can be passed using `config` property in an object', () => {
  return postcss([tailwind({ config: path.resolve(`${__dirname}/fixtures/custom-config.js`) })])
    .process(
      `
        @responsive {
          .foo {
            color: blue;
          }
        }
      `,
      { from: undefined }
    )
    .then((result) => {
      const expected = `
        .foo {
          color: blue;
        }
        @media (min-width: 400px) {
          .mobile\\:foo {
            color: blue;
          }
        }
      `
      expect(result.css).toMatchCss(expected)
    })
})

test('custom config can be passed under the `config` property', () => {
  return postcss([
    tailwind({
      config: {
        theme: {
          screens: {
            mobile: '400px',
          },
        },
      },
    }),
  ])
    .process(
      `
        @responsive {
          .foo {
            color: blue;
          }
        }
      `,
      { from: undefined }
    )
    .then((result) => {
      const expected = `
        .foo {
          color: blue;
        }
        @media (min-width: 400px) {
          .mobile\\:foo {
            color: blue;
          }
        }
      `

      expect(result.css).toMatchCss(expected)
    })
})

test('tailwind.config.cjs is picked up by default', () => {
  return inTempDirectory(() => {
    fs.writeFileSync(
      path.resolve(cjsConfigFile),
      `module.exports = {
        theme: {
          screens: {
            mobile: '400px',
          },
        },
      }`
    )

    return postcss([tailwind])
      .process(
        `
          @responsive {
            .foo {
              color: blue;
            }
          }
        `,
        { from: undefined }
      )
      .then((result) => {
        expect(result.css).toMatchCss(`
          .foo {
            color: blue;
          }
          @media (min-width: 400px) {
            .mobile\\:foo {
              color: blue;
            }
          }
        `)
      })
  })
})

test('tailwind.config.js is picked up by default', () => {
  return inTempDirectory(() => {
    fs.writeFileSync(
      path.resolve(defaultConfigFile),
      `module.exports = {
        theme: {
          screens: {
            mobile: '400px',
          },
        },
      }`
    )

    return postcss([tailwind])
      .process(
        `
          @responsive {
            .foo {
              color: blue;
            }
          }
        `,
        { from: undefined }
      )
      .then((result) => {
        expect(result.css).toMatchCss(`
          .foo {
            color: blue;
          }
          @media (min-width: 400px) {
            .mobile\\:foo {
              color: blue;
            }
          }
        `)
      })
  })
})

test('tailwind.config.cjs is picked up by default when passing an empty object', () => {
  return inTempDirectory(() => {
    fs.writeFileSync(
      path.resolve(cjsConfigFile),
      `module.exports = {
        theme: {
          screens: {
            mobile: '400px',
          },
        },
      }`
    )

    return postcss([tailwind({})])
      .process(
        `
          @responsive {
            .foo {
              color: blue;
            }
          }
        `,
        { from: undefined }
      )
      .then((result) => {
        expect(result.css).toMatchCss(`
          .foo {
            color: blue;
          }
          @media (min-width: 400px) {
            .mobile\\:foo {
              color: blue;
            }
          }
        `)
      })
  })
})

test('tailwind.config.js is picked up by default when passing an empty object', () => {
  return inTempDirectory(() => {
    fs.writeFileSync(
      path.resolve(defaultConfigFile),
      `module.exports = {
        theme: {
          screens: {
            mobile: '400px',
          },
        },
      }`
    )

    return postcss([tailwind({})])
      .process(
        `
          @responsive {
            .foo {
              color: blue;
            }
          }
        `,
        { from: undefined }
      )
      .then((result) => {
        expect(result.css).toMatchCss(`
          .foo {
            color: blue;
          }
          @media (min-width: 400px) {
            .mobile\\:foo {
              color: blue;
            }
          }
        `)
      })
  })
})

test('the default config can be overridden using the presets key', () => {
  return postcss([
    tailwind({
      presets: [
        {
          theme: {
            extend: {
              minHeight: {
                24: '24px',
              },
            },
          },
          corePlugins: ['minHeight'],
          variants: { minHeight: [] },
        },
      ],
      theme: {
        extend: { minHeight: { 48: '48px' } },
      },
    }),
  ])
    .process(
      `
        @tailwind utilities
      `,
      { from: undefined }
    )
    .then((result) => {
      const expected = `
        .min-h-0 {
          min-height: 0px;
        }
        .min-h-24 {
          min-height: 24px;
        }
        .min-h-48 {
          min-height: 48px;
        }
        .min-h-full {
          min-height: 100%;
        }
        .min-h-screen {
          min-height: 100vh;
        }
      `

      expect(result.css).toMatchCss(expected)
    })
})

test('presets can be functions', () => {
  return postcss([
    tailwind({
      presets: [
        () => ({
          theme: {
            extend: {
              minHeight: {
                24: '24px',
              },
            },
          },
          corePlugins: ['minHeight'],
          variants: { minHeight: [] },
        }),
      ],
      theme: {
        extend: { minHeight: { 48: '48px' } },
      },
    }),
  ])
    .process(
      `
        @tailwind utilities
      `,
      { from: undefined }
    )
    .then((result) => {
      const expected = `
        .min-h-0 {
          min-height: 0px;
        }
        .min-h-24 {
          min-height: 24px;
        }
        .min-h-48 {
          min-height: 48px;
        }
        .min-h-full {
          min-height: 100%;
        }
        .min-h-screen {
          min-height: 100vh;
        }
      `

      expect(result.css).toMatchCss(expected)
    })
})

test('the default config can be removed by using an empty presets key in a preset', () => {
  return postcss([
    tailwind({
      presets: [
        {
          presets: [],
          theme: {
            extend: {
              minHeight: {
                24: '24px',
              },
            },
          },
          corePlugins: ['minHeight'],
          variants: { minHeight: [] },
        },
      ],
      theme: {
        extend: { minHeight: { 48: '48px' } },
      },
    }),
  ])
    .process(
      `
        @tailwind utilities
      `,
      { from: undefined }
    )
    .then((result) => {
      const expected = `
        .min-h-24 {
          min-height: 24px;
        }
        .min-h-48 {
          min-height: 48px;
        }
      `

      expect(result.css).toMatchCss(expected)
    })
})

test('presets can have their own presets', () => {
  return postcss([
    tailwind({
      presets: [
        {
          presets: [],
          theme: {
            colors: { red: '#dd0000' },
          },
        },
        {
          presets: [
            {
              presets: [],
              theme: {
                colors: {
                  transparent: 'transparent',
                  red: '#ff0000',
                },
              },
            },
          ],
          theme: {
            extend: {
              colors: {
                black: 'black',
                red: '#ee0000',
              },
              backgroundColor: (theme) => theme('colors'),
            },
          },
          corePlugins: ['backgroundColor'],
        },
      ],
      theme: {
        extend: { colors: { white: 'white' } },
      },
    }),
  ])
    .process(
      `
        @tailwind utilities
      `,
      { from: undefined }
    )
    .then((result) => {
      const expected = `
        .bg-transparent {
          background-color: transparent;
        }
        .bg-red {
          background-color: #ee0000;
        }
        .bg-black {
          background-color: black;
        }
        .bg-white {
          background-color: white;
        }
      `

      expect(result.css).toMatchCss(expected)
    })
})

test('function presets can be mixed with object presets', () => {
  return postcss([
    tailwind({
      presets: [
        () => ({
          presets: [],
          theme: {
            colors: { red: '#dd0000' },
          },
        }),
        {
          presets: [
            () => ({
              presets: [],
              theme: {
                colors: {
                  transparent: 'transparent',
                  red: '#ff0000',
                },
              },
            }),
          ],
          theme: {
            extend: {
              colors: {
                black: 'black',
                red: '#ee0000',
              },
              backgroundColor: (theme) => theme('colors'),
            },
          },
          corePlugins: ['backgroundColor'],
        },
      ],
      theme: {
        extend: { colors: { white: 'white' } },
      },
    }),
  ])
    .process(
      `
        @tailwind utilities
      `,
      { from: undefined }
    )
    .then((result) => {
      const expected = `
        .bg-transparent {
          background-color: transparent;
        }
        .bg-red {
          background-color: #ee0000;
        }
        .bg-black {
          background-color: black;
        }
        .bg-white {
          background-color: white;
        }
      `

      expect(result.css).toMatchCss(expected)
    })
})