import type { Config } from 'tailwindcss';
import { colors, typography, spacing, borderRadius, shadows, breakpoints } from './src/styles/design-tokens';

// Branding runtime: resolve a colour from a CSS variable (RGB triplet) with
// Tailwind opacity-modifier support, e.g. `bg-primary/10`. Driven by
// brandingStore → ThemeProvider, so these tokens retheme the whole app live.
const v = (name: string) => `rgb(var(${name}) / <alpha-value>)`;
// A full scale whose shades all resolve to one brand variable — keeps existing
// `-400/-500/...` classes working while making them dynamic.
const scaleV = (name: string) => ({
  DEFAULT: v(name), 50: v(name), 100: v(name), 200: v(name), 300: v(name),
  400: v(name), 500: v(name), 600: v(name), 700: v(name), 800: v(name), 900: v(name), 950: v(name),
});

// Branding runtime: rescale a token scale by a CSS variable so Branding
// Settings (Density / Border Radius / Font Size) resize the whole app live.
// Only `rem` tokens are wrapped — `0`, `1px` and `9999px` (rounded-full,
// hairlines) must stay fixed or they would collapse/round wrongly. The
// variables default to 1, so an untouched app renders byte-identical CSS values.
const rescale = (varName: string, scale: Record<string, string>): Record<string, string> =>
  Object.fromEntries(
    Object.entries(scale).map(([k, val]) => [k, val.endsWith('rem') ? `calc(${val} * var(${varName}, 1))` : val])
  );

// Density drives inner spacing only (padding / gap / margin), never width,
// height or inset — icons and fixed rails must keep their size.
const densitySpacing = rescale('--app-density-scale', spacing);
const scaledRadius = rescale('--app-radius-scale', borderRadius);
const scaledFontSize = rescale('--app-font-scale', typography.fontSize);

const config: Config = {
  content: [
    './src/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  darkMode: 'class',
  theme: {
    extend: {
      // Colors — CSS-variable-backed so Branding Settings retheme the whole app
      // at runtime. Defaults (globals.css :root) equal the previous static
      // values, so the dark default look is unchanged until an admin edits.
      colors: {
        // Brand scale → --primary (all shades resolve to the brand colour)
        primary: scaleV('--primary'),
        // Readable text/icon colour to place ON a primary or accent fill. The
        // branding runtime sets both to the palette background, so a lime-on-black
        // theme gets dark text and a green-on-white theme gets white text without
        // the call site hardcoding either.
        'primary-foreground': v('--primary-foreground'),
        'accent-foreground': v('--accent-foreground'),
        // Semantic destructive fill (delete / danger actions).
        destructive: v('--destructive'),
        // Surfaces / text / accent tokens (used by the migrated classes)
        canvas: v('--background'),
        card: v('--card'),
        surface: v('--card'),
        // Floating-panel surface (dropdowns, menus, popovers). Registered as a
        // COLOUR here — `popover` also exists under zIndex, and without this key
        // `bg-popover` silently emitted nothing and left panels transparent.
        popover: v('--popover'),
        'popover-foreground': v('--popover-foreground'),
        elevated: v('--elevated'),
        muted: v('--muted-foreground'),
        faint: v('--faint'),
        subtle: v('--subtle'),
        accent: v('--accent'),
        foreground: v('--foreground'),
        line: v('--line'),
        // Background object keeps its shade keys (in active use) but each maps to
        // a brand variable so they retheme too.
        background: {
          DEFAULT: v('--background'),
          primary: v('--background'),
          secondary: v('--card'),
          tertiary: v('--elevated'),
          subtle: v('--faint'),
        },
        // Left static (grays / status) — migrating these is a separate slice.
        secondary: colors.secondary,
        neutral: colors.neutral,
        success: colors.success,
        warning: colors.warning,
        error: colors.error,
      },

      // Typography
      fontFamily: {
        sans: typography.fontFamily.sans.split(', '),
        mono: typography.fontFamily.mono.split(', '),
      },
      fontSize: scaledFontSize,
      lineHeight: typography.lineHeight,
      fontWeight: typography.fontWeight,
      letterSpacing: typography.letterSpacing,

      // Spacing — the raw scale still backs width/height/inset/translate, while
      // padding/margin/gap/space follow the Branding density setting. Margin is
      // included so `-mx-*` bleeds still cancel their parent's `px-*` exactly.
      spacing: spacing,
      padding: densitySpacing,
      margin: densitySpacing,
      gap: densitySpacing,
      space: densitySpacing,

      // Border radius — follows the Branding border-radius setting.
      borderRadius: scaledRadius,

      // Shadows (MENGO Theme)
      boxShadow: {
        sm: shadows.sm,
        DEFAULT: shadows.DEFAULT,
        md: shadows.md,
        lg: shadows.lg,
        xl: shadows.xl,
        inner: shadows.inner,
        'glow-sm': shadows.glow.sm,
        'glow-md': shadows.glow.md,
        'glow-lg': shadows.glow.lg,
      },

      // Breakpoints
      screens: breakpoints,

      // Transitions
      transitionDuration: {
        fast: '150ms',
        normal: '200ms',
        slow: '300ms',
      },
      transitionTimingFunction: {
        'ease-default': 'cubic-bezier(0.4, 0, 0.2, 1)',
      },

      // Animation
      keyframes: {
        'fade-in': {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        'fade-out': {
          '0%': { opacity: '1' },
          '100%': { opacity: '0' },
        },
        'slide-in-right': {
          '0%': { transform: 'translateX(100%)' },
          '100%': { transform: 'translateX(0)' },
        },
        'slide-out-right': {
          '0%': { transform: 'translateX(0)' },
          '100%': { transform: 'translateX(100%)' },
        },
        'slide-in-up': {
          '0%': { transform: 'translateY(10px)', opacity: '0' },
          '100%': { transform: 'translateY(0)', opacity: '1' },
        },
        'scale-in': {
          '0%': { transform: 'scale(0.95)', opacity: '0' },
          '100%': { transform: 'scale(1)', opacity: '1' },
        },
        'skeleton': {
          '0%': { backgroundPosition: '200% 0' },
          '100%': { backgroundPosition: '-200% 0' },
        },
        'shimmer': {
          '0%': { transform: 'translateX(-100%)' },
          '100%': { transform: 'translateX(200%)' },
        },
        'fadeInUp': {
          '0%': { opacity: '0', transform: 'translateY(8px)' },
          '100%': { opacity: '1', transform: 'translateY(0)' },
        },
      },
      animation: {
        'fade-in': 'fade-in 200ms ease-out',
        'fade-out': 'fade-out 150ms ease-in',
        'slide-in-right': 'slide-in-right 300ms ease-out',
        'slide-out-right': 'slide-out-right 200ms ease-in',
        'slide-in-up': 'slide-in-up 200ms ease-out',
        'scale-in': 'scale-in 150ms ease-out',
        'skeleton': 'skeleton 1.5s ease-in-out infinite',
        'shimmer': 'shimmer 2s ease-in-out infinite',
        'fadeInUp': 'fadeInUp 0.5s ease-in forwards',
      },

      // Z-index
      zIndex: {
        hide: '-1',
        dropdown: '1000',
        sticky: '1100',
        banner: '1200',
        overlay: '1300',
        modal: '1400',
        popover: '1500',
        skipLink: '1600',
        toast: '1700',
        tooltip: '1800',
      },
    },
  },
  plugins: [
    // Custom plugin for scrollbar styling
    function ({ addUtilities }: { addUtilities: Function }) {
      addUtilities({
        // Fully-hidden scrollbar (touch/mobile, tab strips). `.scrollbar-none`
        // is an alias so both class names behave identically.
        '.scrollbar-hide, .scrollbar-none': {
          '-ms-overflow-style': 'none',
          'scrollbar-width': 'none',
          '&::-webkit-scrollbar': {
            display: 'none',
          },
        },
        // Thinner variant of the standard scrollbar. Reads the same design
        // tokens as the global scrollbar (see globals.css :root) so it shares
        // the app's thumb colour, radius and hover/active behaviour — only the
        // thickness differs. This is the SINGLE definition of `.scrollbar-thin`
        // (it was previously also declared in globals.css with conflicting,
        // near-invisible black colours).
        '.scrollbar-thin': {
          'scrollbar-width': 'thin',
          'scrollbar-color': 'var(--scrollbar-thumb) var(--scrollbar-track)',
          '&::-webkit-scrollbar': {
            width: 'var(--scrollbar-size-thin)',
            height: 'var(--scrollbar-size-thin)',
          },
          '&::-webkit-scrollbar-track': {
            background: 'var(--scrollbar-track)',
          },
          '&::-webkit-scrollbar-thumb': {
            backgroundColor: 'var(--scrollbar-thumb)',
            borderRadius: 'var(--scrollbar-radius)',
          },
          '&::-webkit-scrollbar-thumb:hover, &::-webkit-scrollbar-thumb:active': {
            backgroundColor: 'var(--scrollbar-thumb-hover)',
          },
        },
        '.text-balance': {
          'text-wrap': 'balance',
        },
        '.gpu-accelerate': {
          'transform': 'translateZ(0)',
          'backface-visibility': 'hidden',
        },
      });
    },
  ],
};

export default config;
