import { describe, expect, it } from 'vitest'

import formatTailwindPreset from './tailwind-preset.mjs'

const testTokens = [
  {
    name: 'color-primary',
    attributes: {
      category: 'colors',
      tailwindPath: ['colors', 'primary'],
    },
    $value: '#FF0000',
  },
  {
    name: 'font-family-sans',
    attributes: {
      category: 'font',
      type: 'family',
      item: 'sans',
    },
    path: ['font', 'family', 'sans'],
    $value: ['Arial', 'Segoe UI', 'sans-serif'],
    $type: 'fontFamily',
  },
  {
    name: 'spacing-small',
    attributes: {
      category: 'spacing',
      type: 'small',
    },
    path: ['spacing', 'small'],
    $value: '8px',
  },
  {
    name: 'radius-large',
    attributes: {
      category: 'radius',
      type: 'large',
    },
    path: ['radius', 'large'],
    $value: '16px',
  },
  {
    name: 'shadow-box',
    attributes: {
      category: 'shadow',
      type: 'box',
    },
    $value: '0 2px 4px rgba(0, 0, 0, 0.1)',
  },
  {
    name: 'typography-h1',
    attributes: {
      category: 'typography',
      type: 'typography',
      tailwindPath: ['typography', 'h1'],
    },
    path: ['typography', 'h1'],
    $type: 'typography',
    $value: {
      fontFamily: 'Inter',
      fontSize: '12px',
      fontWeight: 700,
      lineHeight: 1.104,
    },
  },
  {
    name: 'screens-md',
    attributes: {
      category: 'screens',
      type: 'md',
      tailwindPath: ['screens', 'md'],
    },
    path: ['screens', 'md'],
    $value: '768px',
    original: { $value: '768px' },
    $type: 'dimension',
  },
  {
    name: 'sizes-1/2',
    attributes: {
      category: 'sizes',
      type: '1/2',
      tailwindPath: ['sizes', '1/2'],
    },
    path: ['sizes', '1/2'],
    $value: '50%',
    original: { $value: '50%' },
    $type: 'dimension',
  },
  {
    name: 'uy-animations-spin',
    $type: 'animation',
    $value: {
      name: 'spin',
      duration: { value: 2, unit: 's' },
      timingFunction: 'linear',
      iterationCount: 'infinite',
    },
    attributes: {
      category: 'animations',
      type: 'spin',
    },
    path: ['animations', 'spin'],
  },
  {
    name: 'uy-keyframes-spin',
    $type: 'keyframes',
    $value: {
      '0%': {
        transform: 'rotate(0deg)',
      },
      '100%': {
        transform: 'rotate(360deg)',
      },
    },
    attributes: {
      category: 'animations',
      type: 'spin',
    },
    path: ['keyframes', 'spin'],
  },
]

describe('format/TailwindPreset', () => {
  it('should output the formatted preset', async () => {
    const args = {
      dictionary: {
        allTokens: testTokens,
      },
      options: {
        name: 'myTheme',
        extend: true,
        outputReferences: false,
        injectCssVariables: false,
        usesDtcg: true,
      },
    }
    const result = await formatTailwindPreset(args as any)

    expect(result).toMatchInlineSnapshot(`
      "const preset = {
        theme: {
          extend: {
            colors: {
              primary: "rgb(#FF0000 / <alpha-value>)",
            },
            fontFamily: {
              sans: ["Arial", "Segoe UI", "sans-serif"],
            },
            spacing: {
              small: "8px",
            },
            size: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            width: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vw",
              svw: "100svw",
              lvw: "100lvw",
              dvw: "100dvw",
            },
            height: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vh",
              svh: "100svh",
              lvh: "100lvh",
              dvh: "100dvh",
            },
            minWidth: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            minHeight: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vh",
              svh: "100svh",
              lvh: "100lvh",
              dvh: "100dvh",
            },
            maxWidth: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            maxHeight: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vh",
              svh: "100svh",
              lvh: "100lvh",
              dvh: "100dvh",
            },
            flexBasis: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            borderRadius: {
              large: "16px",
            },
            boxShadow: {
              box: "0 2px 4px rgba(0, 0, 0, 0.1)",
            },
            fontSize: {
              h1: [
                "12px",
                {
                  lineHeight: 1.104,
                  fontWeight: 700,
                  fontFamily: "Inter",
                },
              ],
            },
            screens: {
              md: "768px",
            },
            animation: {
              spin: "spin 2s linear infinite",
            },
            keyframes: {
              spin: {
                "0%": {
                  transform: "rotate(0deg)",
                },
                "100%": {
                  transform: "rotate(360deg)",
                },
              },
            },
          },
        },
      };

      export default {
        ...preset,
      };
      "
    `)
  })

  it('should output preset with injected plugin variables', async () => {
    const args = {
      dictionary: {
        allTokens: testTokens,
      },
      options: {
        name: 'myTheme',
        extend: true,
        outputReferences: false,
        injectCssVariables: true,
        usesDtcg: true,
      },
    }
    const result = await formatTailwindPreset(args as any)

    expect(result).toMatchInlineSnapshot(`
      "import plugin from "tailwindcss/plugin";

      const myThemeTailwindPlugin = plugin(({ addBase, addComponents }) => {
        // Add CSS variables
        addBase({
          ":root": {
            "--color-primary": "#FF0000",
            "--font-family-sans": '"Arial", "Segoe UI", sans-serif',
            "--spacing-small": "8px",
            "--radius-large": "16px",
            "--shadow-box": "0 2px 4px rgba(0, 0, 0, 0.1)",
            "--typography-h1__font-family": "Inter",
            "--typography-h1__font-size": "12px",
            "--typography-h1__font-weight": "700",
            "--typography-h1__line-height": "1.104",
            "--screens-md": "768px",
            "--sizes-1-of-2": "50%",
            "--uy-animations-spin-duration": "2s",
            "--uy-animations-spin-timing-function": "linear",
            "--uy-animations-spin-iteration-count": "infinite",
          },
        });

        // Add base styles
        addBase({
          "@keyframes spin": {
            "0%": { transform: "rotate(0deg)" },
            "100%": { transform: "rotate(360deg)" },
          },
          "b, strong": { fontWeight: "var(--uy-font-weight-bold)" },
          ol: { listStyleType: "decimal" },
          ul: { listStyleType: "disc" },
        });

        addComponents({
          ".typography-h1": {
            font: "normal var(--typography-h1__font-weight) var(--typography-h1__font-size) / var(--typography-h1__line-height) var(--typography-h1__font-family)",
          },
        });
      });

      const preset = {
        theme: {
          extend: {
            colors: {
              primary: "rgb(var(--color-primary) / <alpha-value>)",
            },
            fontFamily: {
              sans: "var(--font-family-sans)",
            },
            spacing: {
              small: "var(--spacing-small)",
            },
            size: {
              small: "var(--spacing-small)",
              "1/2": "var(--sizes-1-of-2)",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            width: {
              small: "var(--spacing-small)",
              "1/2": "var(--sizes-1-of-2)",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vw",
              svw: "100svw",
              lvw: "100lvw",
              dvw: "100dvw",
            },
            height: {
              small: "var(--spacing-small)",
              "1/2": "var(--sizes-1-of-2)",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vh",
              svh: "100svh",
              lvh: "100lvh",
              dvh: "100dvh",
            },
            minWidth: {
              small: "var(--spacing-small)",
              "1/2": "var(--sizes-1-of-2)",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            minHeight: {
              small: "var(--spacing-small)",
              "1/2": "var(--sizes-1-of-2)",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vh",
              svh: "100svh",
              lvh: "100lvh",
              dvh: "100dvh",
            },
            maxWidth: {
              small: "var(--spacing-small)",
              "1/2": "var(--sizes-1-of-2)",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            maxHeight: {
              small: "var(--spacing-small)",
              "1/2": "var(--sizes-1-of-2)",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vh",
              svh: "100svh",
              lvh: "100lvh",
              dvh: "100dvh",
            },
            flexBasis: {
              small: "var(--spacing-small)",
              "1/2": "var(--sizes-1-of-2)",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            borderRadius: {
              large: "var(--radius-large)",
            },
            boxShadow: {
              box: "var(--shadow-box)",
            },
            fontSize: {
              h1: [
                "var(--typography-h1__font-size)",
                {
                  lineHeight: "var(--typography-h1__line-height)",
                  fontWeight: "var(--typography-h1__font-weight)",
                  fontFamily: "var(--typography-h1__font-family)",
                },
              ],
            },
            screens: {
              md: "768px",
            },
            animation: {
              spin: "spin var(--uy-animations-spin-duration) var(--uy-animations-spin-timing-function) var(--uy-animations-spin-iteration-count)",
            },
            keyframes: {
              spin: {
                "0%": {
                  transform: "rotate(0deg)",
                },
                "100%": {
                  transform: "rotate(360deg)",
                },
              },
            },
          },
        },
      };

      export default {
        ...preset,
        plugins: [myThemeTailwindPlugin],
      };
      "
    `)
  })

  it('should output preset with prefix when available', async () => {
    const args = {
      dictionary: {
        allTokens: testTokens,
      },
      options: {
        name: 'myTheme',
        extend: true,
        outputReferences: false,
        injectCssVariables: false,
        usesDtcg: true,
      },
      platform: {
        prefix: 'foo',
      },
    }
    const result = await formatTailwindPreset(args as any)

    expect(result).toMatchInlineSnapshot(`
      "const preset = {
        prefix: "foo-",
        theme: {
          extend: {
            colors: {
              primary: "rgb(#FF0000 / <alpha-value>)",
            },
            fontFamily: {
              sans: ["Arial", "Segoe UI", "sans-serif"],
            },
            spacing: {
              small: "8px",
            },
            size: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            width: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vw",
              svw: "100svw",
              lvw: "100lvw",
              dvw: "100dvw",
            },
            height: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vh",
              svh: "100svh",
              lvh: "100lvh",
              dvh: "100dvh",
            },
            minWidth: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            minHeight: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vh",
              svh: "100svh",
              lvh: "100lvh",
              dvh: "100dvh",
            },
            maxWidth: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            maxHeight: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
              screen: "100vh",
              svh: "100svh",
              lvh: "100lvh",
              dvh: "100dvh",
            },
            flexBasis: {
              small: "8px",
              "1/2": "50%",
              auto: "auto",
              min: "min-content",
              max: "max-content",
              fit: "fit-content",
            },
            borderRadius: {
              large: "16px",
            },
            boxShadow: {
              box: "0 2px 4px rgba(0, 0, 0, 0.1)",
            },
            fontSize: {
              h1: [
                "12px",
                {
                  lineHeight: 1.104,
                  fontWeight: 700,
                  fontFamily: "Inter",
                },
              ],
            },
            screens: {
              md: "768px",
            },
            animation: {
              spin: "spin 2s linear infinite",
            },
            keyframes: {
              spin: {
                "0%": {
                  transform: "rotate(0deg)",
                },
                "100%": {
                  transform: "rotate(360deg)",
                },
              },
            },
          },
        },
      };

      export default {
        ...preset,
      };
      "
    `)
  })
})
