import { resetComponent } from '../../style';
import { initZoomMotion } from '../../style/motion';
import type { ArrowOffsetToken } from '../../style/placementArrow';
import getArrowStyle, { getArrowOffsetToken } from '../../style/placementArrow';
import type { ArrowToken } from '../../style/roundedArrow';
import { getArrowToken } from '../../style/roundedArrow';
import type {
  FullToken,
  GenerateStyle,
  GetDefaultToken,
  PresetColorType,
} from '../../theme/internal';
import { genStyleHooks, mergeToken, PresetColors } from '../../theme/internal';

export interface ComponentToken extends ArrowToken, ArrowOffsetToken {
  /**
   * @deprecated Please use `titleMinWidth` instead
   * @desc 气泡卡片宽度
   * @descEN Width of Popover
   */
  width?: number | string;
  /**
   * @deprecated Please use `titleMinWidth` instead
   * @desc 气泡卡片最小宽度
   * @descEN Min width of Popover
   */
  minWidth?: number | string;
  /**
   * @desc 气泡卡片标题最小宽度
   * @descEN Min width of Popover title
   */
  titleMinWidth: number | string;
  /**
   * @desc 气泡卡片 z-index
   * @descEN z-index of Popover
   */
  zIndexPopup: number;
  /** @internal */
  innerPadding: number;
  /** @internal */
  titlePadding: number | string;
  /** @internal */
  titleMarginBottom: number;
  /** @internal */
  titleBorderBottom: string;
  /** @internal */
  innerContentPadding: number | string;
}

/**
 * @desc Popover 组件的 Token
 * @descEN Token for Popover component
 */
export type PopoverToken = FullToken<'Popover'> & {
  /**
   * @desc 气泡卡片背景色
   * @descEN Background color of Popover
   */
  popoverBg: string;
  /**
   * @desc 气泡卡片文字颜色
   * @descEN Text color of Popover
   */
  popoverColor: string;
};

const genBaseStyle: GenerateStyle<PopoverToken> = (token) => {
  const {
    componentCls,
    popoverColor,
    titleMinWidth,
    fontWeightStrong,
    innerPadding,
    boxShadowSecondary,
    colorTextHeading,
    borderRadiusLG,
    zIndexPopup,
    titleMarginBottom,
    colorBgElevated,
    popoverBg,
    titleBorderBottom,
    innerContentPadding,
    titlePadding,
  } = token;

  return [
    {
      [componentCls]: {
        ...resetComponent(token),
        position: 'absolute',
        top: 0,
        // use `left` to fix https://github.com/ant-design/ant-design/issues/39195
        left: {
          _skip_check_: true,
          value: 0,
        },
        zIndex: zIndexPopup,
        fontWeight: 'normal',
        whiteSpace: 'normal',
        textAlign: 'start',
        cursor: 'auto',
        userSelect: 'text',

        // When use `autoArrow`, origin will follow the arrow position
        '--valid-offset-x': 'var(--arrow-offset-horizontal, var(--arrow-x))',
        transformOrigin: [`var(--valid-offset-x, 50%)`, `var(--arrow-y, 50%)`].join(' '),

        '--antd-arrow-background-color': colorBgElevated,
        width: 'max-content',
        maxWidth: '100vw',

        '&-rtl': {
          direction: 'rtl',
        },

        '&-hidden': {
          display: 'none',
        },

        [`${componentCls}-content`]: {
          position: 'relative',
        },

        [`${componentCls}-inner`]: {
          backgroundColor: popoverBg,
          backgroundClip: 'padding-box',
          borderRadius: borderRadiusLG,
          boxShadow: boxShadowSecondary,
          padding: innerPadding,
        },

        [`${componentCls}-title`]: {
          minWidth: titleMinWidth,
          marginBottom: titleMarginBottom,
          color: colorTextHeading,
          fontWeight: fontWeightStrong,
          borderBottom: titleBorderBottom,
          padding: titlePadding,
        },

        [`${componentCls}-inner-content`]: {
          color: popoverColor,
          padding: innerContentPadding,
        },
      },
    },

    // Arrow Style
    getArrowStyle(token, 'var(--antd-arrow-background-color)'),

    // Pure Render
    {
      [`${componentCls}-pure`]: {
        position: 'relative',
        maxWidth: 'none',
        margin: token.sizePopupArrow,
        display: 'inline-block',

        [`${componentCls}-content`]: {
          display: 'inline-block',
        },
      },
    },
  ];
};

const genColorStyle: GenerateStyle<PopoverToken> = (token) => {
  const { componentCls } = token;

  return {
    [componentCls]: PresetColors.map((colorKey: keyof PresetColorType) => {
      const lightColor = token[`${colorKey}6`];
      return {
        [`&${componentCls}-${colorKey}`]: {
          '--antd-arrow-background-color': lightColor,
          [`${componentCls}-inner`]: {
            backgroundColor: lightColor,
          },
          [`${componentCls}-arrow`]: {
            background: 'transparent',
          },
        },
      };
    }),
  };
};

export const prepareComponentToken: GetDefaultToken<'Popover'> = (token) => {
  const {
    lineWidth,
    controlHeight,
    fontHeight,
    padding,
    wireframe,
    zIndexPopupBase,
    borderRadiusLG,
    marginXS,
    lineType,
    colorSplit,
    paddingSM,
  } = token;

  const titlePaddingBlockDist = controlHeight - fontHeight;
  const popoverTitlePaddingBlockTop = titlePaddingBlockDist / 2;
  const popoverTitlePaddingBlockBottom = titlePaddingBlockDist / 2 - lineWidth;
  const popoverPaddingHorizontal = padding;

  return {
    titleMinWidth: 177,
    zIndexPopup: zIndexPopupBase + 30,
    ...getArrowToken(token),
    ...getArrowOffsetToken({
      contentRadius: borderRadiusLG,
      limitVerticalRadius: true,
    }),

    // internal
    innerPadding: wireframe ? 0 : 12,
    titleMarginBottom: wireframe ? 0 : marginXS,
    titlePadding: wireframe
      ? `${popoverTitlePaddingBlockTop}px ${popoverPaddingHorizontal}px ${popoverTitlePaddingBlockBottom}px`
      : 0,
    titleBorderBottom: wireframe ? `${lineWidth}px ${lineType} ${colorSplit}` : 'none',
    innerContentPadding: wireframe ? `${paddingSM}px ${popoverPaddingHorizontal}px` : 0,
  };
};

export default genStyleHooks(
  'Popover',
  (token) => {
    const { colorBgElevated, colorText } = token;

    const popoverToken = mergeToken<PopoverToken>(token, {
      popoverBg: colorBgElevated,
      popoverColor: colorText,
    });

    return [
      genBaseStyle(popoverToken),
      genColorStyle(popoverToken),
      initZoomMotion(popoverToken, 'zoom-big'),
    ];
  },
  prepareComponentToken,
  {
    resetStyle: false,
    deprecatedTokens: [
      ['width', 'titleMinWidth'],
      ['minWidth', 'titleMinWidth'],
    ],
  },
);
