import {CanvasTheme, EmotionCanvasTheme, useTheme} from '@workday/canvas-kit-react/common';
import {CSSProperties} from '@workday/canvas-kit-react/tokens';
import {cssVar} from '@workday/canvas-kit-styling';
import {brand, system} from '@workday/canvas-tokens-web';

type paletteSelection = Exclude<keyof EmotionCanvasTheme['canvas']['palette'], 'common'>;
interface ContrastColors {
  outer?: string;
  inner?: string;
}

const getPaletteColorsFromTheme = (
  palette: CanvasTheme,
  fallbackColors?: ContrastColors,
  errorType?: 'error' | 'alert'
): ContrastColors => {
  if (errorType === 'error') {
    return {
      outer: cssVar(brand.common.errorInner),
      inner: cssVar(brand.common.errorInner),
    };
  } else if (errorType === 'alert') {
    return {
      outer: cssVar(brand.common.alertOuter),
      inner: cssVar(brand.common.alertInner),
    };
  }

  // If specific fallback colors are provided (e.g., for success), prefer those
  if (fallbackColors && (fallbackColors.outer || fallbackColors.inner)) {
    return {
      outer: fallbackColors.outer ?? cssVar(brand.common.focusOutline),
      inner: fallbackColors.inner ?? fallbackColors.outer ?? cssVar(brand.common.focusOutline),
    };
  }

  return {
    outer: cssVar(brand.common.focusOutline),
    inner: cssVar(brand.common.focusOutline),
  };
};

/**
 * @deprecated ⚠️ `getPaletteColorsForFocusRing` is deprecated and will be removed in a future major version. Please use the `brand.common.focusRing` CSS variable to theme focus rings. For more information, view our [CSS tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-brand-tokens--docs).
 */
export function getPaletteColorsForFocusRing(
  type: paletteSelection,
  theme: EmotionCanvasTheme
): ContrastColors {
  switch (type) {
    case 'error': {
      return getPaletteColorsFromTheme(theme.canvas, {outer: brand.common.errorInner}, 'error');
    }
    case 'alert': {
      return getPaletteColorsFromTheme(theme.canvas, {outer: brand.common.alertInner}, 'alert');
    }
    case 'success': {
      return getPaletteColorsFromTheme(theme.canvas, {
        outer: cssVar(brand.success.dark),
        // The theme default for success.main is set to the darkest GreenApple
        // For our default ring, we need to override it so the inner ring is a bit lighter
        inner: cssVar(brand.success.base),
      });
    }
    default: {
      return getPaletteColorsFromTheme(theme.canvas);
    }
  }
}

/**
 * This is a way to automatically add themed colors to your input and is helpful when showing alerts, success or errors to users.
 * It supports `error`, `alert`, and `success` states. It will try and use the corresponding
 * `main` colors from your `CanvasThemePalette` unless they do not meet accessibility contrast, in
 * which case the outer ring will use the `darkest` color. This hook will also show a `focusOutline`
 * ring when the input is focused. Note: You should not rely on these colors alone to differentiate
 * alerts, but use them in combination with icons or hint text.
 * ```tsx
 * // Add here jsx pragma to use css
 * import {jsx} from '@emotion/react';
 * import React from 'react';
 * import {FormField} from '@workday/canvas-kit-react/form-field';
 * import {TextInput} from '@workday/canvas-kit-react/text-input';
 * import {useThemedRing} from '@workday/canvas-kit-react/common';
 *
 * export const MyInput = ({handleChange}) => {
 *  const [value, setValue] = React.useState('invalid@email');
 *  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
 *    setValue(event.target.value);
 *  };
 *
 *  const alertStyles = useThemedRing('alert');
 *
 *  return (
 *    <FormField>
 *      <FormField.Label>Email</FormField.Label>
 *      <FormField.Field css={alertStyles}>
 *        <FormField.Input as={TextInput} onChange={handleChange} value={value} />
 *        <FormField.Hint>Add a valid email</FormField.Hint>
 *      </FormField.Field>
 *    </FormField>
 *  );
 * };
 *```
 * @deprecated `useThemedRing` is deprecated and will be removed in a future major version. Please use `brand.common.focusOutline` CSS variable instead. View our [CSS tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-brand-tokens--docs) for more information.
 */
export const useThemedRing = (type: paletteSelection): CSSProperties => {
  const theme = useTheme();

  const paletteColors = getPaletteColorsForFocusRing(type, theme);

  if (!(paletteColors?.outer || paletteColors?.inner)) {
    return {};
  }
  const errorBoxShadow = `inset 0 0 0 ${paletteColors.outer === paletteColors.inner ? 1 : 2}px ${
    paletteColors.inner
  }`;

  return {
    borderColor: paletteColors.outer,
    transition: '100ms box-shadow',
    boxShadow: errorBoxShadow,
    '&:hover, &:disabled': {
      borderColor: paletteColors.outer,
    },
    '&:focus:not([disabled])': {
      borderColor: paletteColors.outer,
      boxShadow: `${errorBoxShadow},
        0 0 0 2px ${cssVar(system.color.border.input.inverse)},
        0 0 0 4px ${cssVar(brand.common.focusOutline)}`,
    },
  };
};
