import componentMap from '..'
import { useProjectStore } from '@/store/modules/project'
import { assign } from 'lodash-es'
import { ref, watch } from 'vue'
import { generateCssGradient } from '@/utils'
import { DEFAULT_THEME_KEY } from '@/constants'

import type { IStyleConfig, PartItem } from '../type'
import type { CSSProperties } from 'vue'
import { klona } from 'klona'

type StyleParam = {
  widget: keyof typeof componentMap
  props: {
    part?: string
    state?: string
    styles: IStyleConfig[]
    [key: string]: any
  }
}

type StyleMap = Record<
  string,
  CSSProperties & {
    imageSrc?: string
    // 背景图样式
    imageStyle?: CSSProperties
    // 图片样式
    image?: CSSProperties
    line?: {
      color: string
      width: number
      radius: boolean
      imageSrc?: string
      // 背景图样式
      opacity?: number
    }
    curve?: {
      color: string
      width: number
      radius: boolean
      imageSrc?: string
      // 背景图样式
      opacity?: number
    }
  }
>

/**
 * 获取样式
 * @param key
 * @param value
 * @returns
 */
export const getStyle = (key, value, options?: any) => {
  const style: CSSProperties = {}
  switch (key) {
    // 背景样式
    case 'background': {
      if (typeof value?.color === 'object') {
        // 渐变颜色
        style.background = generateCssGradient(value?.color, options?.width, options?.height)
      } else if (typeof value?.color === 'string') {
        style.backgroundColor = value?.color
      }
      break
    }
    // 文字样式
    case 'text': {
      style.color = value?.color
      style.fontSize = `${value?.size}px`
      // style.fontFamily = value?.family
      style.textAlign = value?.align

      // 处理字体
      if (value?.family && value?.family !== 'montserratMedium') {
        const font = useProjectStore().project?.resources?.fonts?.find(
          (item) => item.id === value.family
        )
        style.fontFamily = `'${font?.fileName}'`
      } else {
        style.fontFamily = 'montserratMedium'
      }

      style.fontStyle = value?.italic ? 'italic' : 'normal'
      // 装饰
      style.textDecoration = value?.decoration

      // 字形
      switch (value?.weight) {
        case 'normal':
          style.fontWeight = 'normal'
          break
        case 'bold':
          style.fontWeight = 'bold'
          break
        case 'italic':
          style.fontWeight = 'normal'
          style.fontStyle = 'italic'
          break
        case 'bold italic':
          style.fontWeight = 'bold'
          style.fontStyle = 'italic'
          break
      }
      break
    }
    // 边框样式
    case 'border': {
      style.borderColor = 'transparent'
      style.borderWidth = 0
      style.borderRadius = `${value?.radius}px`
      style.borderStyle = 'solid'
      if (value?.side?.includes('all') || value?.side?.includes('top')) {
        style.borderTopColor = value?.color
        style.borderTopWidth = `${value?.width || 0}px`
      }
      if (value?.side?.includes('all') || value?.side?.includes('right')) {
        style.borderRightColor = value?.color
        style.borderRightWidth = `${value?.width || 0}px`
      }
      if (value?.side?.includes('all') || value?.side?.includes('bottom')) {
        style.borderBottomColor = value?.color
        style.borderBottomWidth = `${value?.width || 0}px`
      }
      if (value?.side?.includes('all') || value?.side?.includes('left')) {
        style.borderLeftColor = value?.color
        style.borderLeftWidth = `${value?.width || 0}px`
      }
      break
    }
    // 外边框样式
    case 'outline': {
      style.outlineColor = value?.color
      style.outlineWidth = `${value?.width}px`
      style.outlineStyle = 'solid'
      style.outlineOffset = `${value?.pad || 0}px`
      break
    }
    // 阴影样式
    case 'shadow': {
      style.boxShadow =
        value?.width > 0
          ? `${value?.offsetX}px ${value?.offsetY}px ${value?.width}px ${value?.spread}px ${value?.color}`
          : 'none'
      break
    }
    // 内边距样式
    case 'padding': {
      style.padding = `${value?.top || 0}px ${value?.right || 0}px ${value?.bottom || 0}px ${value?.left || 0}px`
      if (value?.row) {
        style.rowGap = `${value?.row}px`
      }
      if (value?.column) {
        style.columnGap = `${value?.column}px`
      }
      break
    }
    // 外边距样式
    case 'margin': {
      style.margin = `${value?.top || 0}px ${value?.right || 0}px ${value?.bottom || 0}px ${value?.left || 0}px`
      break
    }
    // 间距样式
    case 'spacer': {
      style.letterSpacing = `${value?.letterSpacing}px`
      break
    }
    // 变化样式
    case 'transform': {
      const rotate = (value?.rotate || 0) / 10
      const scale = (value?.scale || 0) / 256
      const offsetWidth = value?.width || 0
      const offsetHeight = value?.height || 0
      style.width = `calc(100% + ${offsetWidth * 2}px)`
      style.height = `calc(100% + ${offsetHeight * 2}px)`
      style.transform = `translate(${(value?.translateX || 0) - offsetWidth}px, ${(value?.translateY || 0) - offsetHeight}px) scale(${scale}) rotate(${rotate}deg)`
      style.transformOrigin = `${value?.originX || 0}px ${value?.originY || 0}px`
      break
    }
  }

  return style
}

/**
 * 根据控件part、state获取控件样式
 * @param param - StyleParam
 * @returns
 */
export const useWidgetStyle = (param: StyleParam) => {
  const projectStore = useProjectStore()

  const widget = param.widget
  // 全局默认样式
  const widgetDefaultStyle = componentMap[widget]?.defaultStyle
  // 控件模块状态
  const parts = componentMap[widget].parts
  // 控件样式集合
  const styleMap = ref<StyleMap>({})

  /**
   * 获取控件兜底预设样式
   */
  const getPresetDefaultStyle = (partItem: PartItem) => {
    const { part, state } = param.props

    const defaultStyle = widgetDefaultStyle?.part?.find(
      (item) => item.partName === partItem.name
    )?.defaultStyle

    const stateStyle = widgetDefaultStyle?.part
      ?.find((item) => item.partName === partItem.name)
      ?.state?.find(
        (s) => s.state === (part === partItem.name ? state : partItem.stateList?.[0])
      )?.style

    return klona(assign({}, defaultStyle, stateStyle))
  }

  /**
   * 获取控件默认样式
   */
  const getWidgetDefaultStyle = (partName: string, stateName?: string) => {
    const widgetType = widget

    const state = projectStore.globalStyle
      ?.find((item) => item.widget === widgetType)
      ?.part?.find((item) => item.partName === partName)?.state

    const defaultStyle =
      projectStore.globalStyle
        ?.find((item) => item.widget === widgetType)
        ?.part?.find((item) => item.partName === partName)?.defaultStyle || {}

    const stateStyle = state?.find((item) => item.state === stateName)?.style || {}

    return klona(assign({}, defaultStyle, stateStyle))
  }

  const getImageSrc = (imgId: string | undefined) => {
    if (!imgId) return ''
    const basePath = projectStore?.projectPath
    const imagePath = projectStore?.project?.resources.images.find(
      (item) => item.id === imgId
    )?.path
    if (basePath && imagePath) {
      return `local:///${(basePath + imagePath).replaceAll('\\', '/')}`
    }
    return ''
  }

  const handleStyle = () => {
    const { part, state, styles = [], props } = param.props
    const currentTheme = projectStore.project?.currentTheme || DEFAULT_THEME_KEY
    const getStyleTheme = (styleItem: any) => styleItem?.theme || DEFAULT_THEME_KEY
    parts.forEach((partItem) => {
      styleMap.value[`${partItem.name}Style`] = {}
      // 从控件配置的样式列表查找对应样式

      let style = styles.find(
        // part为当前part时，根据state获取 否则取第一个state样式
        (s) =>
          s.part?.name === partItem.name &&
          s.part?.state === (part === partItem.name ? state : partItem.stateList?.[0]) &&
          getStyleTheme(s) === currentTheme
      )

      if (!style && currentTheme !== DEFAULT_THEME_KEY) {
        style = styles.find(
          (s) =>
            s.part?.name === partItem.name &&
            s.part?.state === (part === partItem.name ? state : partItem.stateList?.[0]) &&
            getStyleTheme(s) === DEFAULT_THEME_KEY
        )
      }

      const presetStyle = getPresetDefaultStyle(partItem)
      const defaultStyle = getWidgetDefaultStyle(
        partItem.name,
        part === partItem.name ? state : partItem.stateList?.[0]
      )

      // 合并到预设样式
      style = assign({}, presetStyle || {}, defaultStyle || {}, style || {})

      // 遍历style 获取样式
      Object.keys(style || {}).forEach((key) => {
        // 合并样式
        assign(
          styleMap.value[`${partItem.name}Style`],
          getStyle(key, style?.[key], {
            width: props?.width,
            height: props?.height
          })
        )

        // 获取背景图片src及颜色
        if (key === 'background' && style?.[key]?.image?.imgId) {
          styleMap.value[`${partItem.name}Style`].imageSrc = getImageSrc(style?.[key]?.image?.imgId)
          styleMap.value[`${partItem.name}Style`].imageStyle = {
            backgroundColor: style?.[key]?.image?.recolor,
            opacity: (style?.[key]?.image?.alpha || 255) / 255
          }
        }
        // 图片样式
        if (key === 'imageStyle') {
          styleMap.value[`${partItem.name}Style`].image = {
            backgroundColor: style?.[key]?.recolor,
            opacity: (style?.[key]?.alpha || 255) / 255
          }
        }
        // 线段返回原本值，并解析 image 为 imageSrc/imageAlpha
        if (key === 'line') {
          const lineData = style?.line
          styleMap.value[`${partItem.name}Style`].line = {
            color: lineData?.color ?? '',
            width: lineData?.width ?? 0,
            radius: lineData?.radius ?? false,
            imageSrc: getImageSrc(lineData?.image),
            opacity: (lineData?.alpha ?? 255) / 255
          }
        }
        if (key === 'curve') {
          const curveData = style?.curve
          styleMap.value[`${partItem.name}Style`].curve = {
            color: curveData?.color ?? '',
            width: curveData?.width ?? 0,
            radius: curveData?.radius ?? false,
            imageSrc: getImageSrc(curveData?.image),
            opacity: (curveData?.alpha ?? 255) / 255
          }
        }
      })
      // 处理行高 默认行高为1.2倍
      if (style?.spacer?.lineHeight && style?.text?.size) {
        const baseHeight = style.text.size * 1.2
        styleMap.value[`${partItem.name}Style`].lineHeight =
          `${baseHeight + style.spacer.lineHeight}px`
      }
    })
  }

  watch(() => param.props, handleStyle, {
    deep: true,
    immediate: true
  })

  watch(
    () => projectStore.project?.currentTheme,
    () => {
      handleStyle()
    }
  )

  return styleMap
}
