<script setup lang="ts">
import type { CSSProperties, Component } from 'vue'
import type { PlatformTransformType } from '#layers/types/api/gameData'
import type {
  DownloadButtonType,
  ButtonVariant,
  Platform,
} from '#layers/types/components/button'

interface Props {
  platform: Platform
  type?: DownloadButtonType
  variant?: ButtonVariant
  backgroundColor?: string
  textColor?: string
  iconComponent?: Component
  iconProps?: Record<string, any>
  disabled?: boolean
  useGameFont?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  type: 'default',
  variant: 'filled',
  disabled: false,
  useGameFont: false,
})

const runtimeConfig = useRuntimeConfig()
const { tm } = useI18n()
const device = useDevice()
const gameDataStore = useGameDataStore()
const modalStore = useModalStore()
const { isProcessing, validateLauncher } = useCheckGameStart()

const { gameName, platformType, osType, marketJson, fontFamily } =
  storeToRefs(gameDataStore)

const PLATFORM_ICON_MAP: Record<Platform, string> = {
  google_play: 'AtomsIconsLogoGoogle',
  app_store: 'AtomsIconsLogoApple',
  pc: 'AtomsIconsLogoWindow',
  stove: 'AtomsIconsLogoStove',
} as const
const DUP_IMAGE_MAP: Record<Platform, string> = {
  google_play: '/images/common/btn_launcher/btn_logo-google.svg',
  app_store: '/images/common/btn_launcher/btn_logo-app.svg',
  pc: '/images/common/btn_launcher/btn_logo-pc.svg',
  stove: '/images/common/btn_launcher/btn_logo-stove.svg',
} as const

const componentTag = computed(() => {
  if (props.platform === 'stove' && props.type !== 'duplication') {
    return 'a'
  }
  return 'button'
})
const shouldShowPlatformIcon = computed(
  () =>
    (props.type === 'default' && props.variant !== 'custom') ||
    props.type === 'single'
)
const shouldShowDownloadIcon = computed(
  () =>
    props.platform === 'pc' &&
    props.type === 'default' &&
    props.variant !== 'custom'
)
const supportedPlatforms = computed(
  () =>
    getSupportedPlatforms(
      platformType.value,
      osType.value
    ) as PlatformTransformType[]
)
const platformIcon = computed(() => PLATFORM_ICON_MAP[props.platform])
const buttonStyle = computed<CSSProperties>(() => {
  const style: CSSProperties = {}

  if (props.backgroundColor) {
    style.backgroundColor = props.backgroundColor
  }
  if (props.type === 'duplication') {
    style.backgroundImage = `url(${formatPathHost(DUP_IMAGE_MAP[props.platform], { imageType: 'common' })})`
  }

  return style
})
const textStyle = computed<CSSProperties>(() => {
  const style: CSSProperties = {}
  if (props.textColor) {
    style.color = props.textColor
  }
  if (props.useGameFont && fontFamily.value) {
    style.fontFamily = fontFamily.value
  }

  return style
})

const highlight = (text: string) => `<span class="highlight">${text}</span>`

const tmWithGameName = (key: string): string => {
  const raw = tm(key)
  if (typeof raw !== 'string') return ''

  const withName = raw.replace(/%게임명%/g, highlight(gameName.value))
  const platformLines = supportedPlatforms.value
    .map(platform => highlight(formatSnakeToTitle(platform)))
    .filter(Boolean)

  return platformLines.length
    ? `${withName}<br><br>${platformLines.join('<br>')}`
    : withName
}

const handleClick = () => {
  if (props.platform === 'stove') {
    if (props.type === 'duplication') return

    const stoveClientDownloadUrl = runtimeConfig.public.stoveClientDownloadUrl
    location.href = stoveClientDownloadUrl
    return
  }

  if (props.platform === 'pc') {
    if (device.isDesktop && platformType.value !== '2') {
      // 디바이스 pc 환경이면서 모바일 스토어 전용이 아니면 런처 실행
      validateLauncher()
      return
    } else {
      const target = device.isAndroid
        ? 'google_play'
        : device.isApple
          ? 'app_store'
          : null

      if (!target || !supportedPlatforms.value.includes(target)) {
        modalStore.handleOpenAlert({
          contentText: tmWithGameName('Alert_Not_SupportedOS'),
        })
        return
      }

      const url = marketJson.value?.[target]?.url ?? ''
      window.open(url, '_blank')
      return
    }
  }

  const url = marketJson.value?.[props.platform]?.url ?? ''
  if (url) window.open(url, '_blank')
}
</script>

<template>
  <component
    :is="componentTag"
    v-bind="$attrs"
    :class="['btn-base', props.type, { 'no-text': !$slots.default }]"
    :data-variant="props.variant"
    :data-platform="props.platform"
    :style="buttonStyle"
    :disabled="disabled || isProcessing"
    @click="handleClick"
  >
    <span class="btn-content">
      <span v-if="shouldShowPlatformIcon" class="icon-platform">
        <component :is="platformIcon" />
      </span>
      <span class="text" :style="textStyle">
        <slot />
      </span>
      <component
        :is="props.iconComponent"
        v-if="props.iconComponent"
        v-bind="props.iconProps"
      />
      <span v-if="shouldShowDownloadIcon" class="icon-download">
        <AtomsIconsDownloadLine />
      </span>
    </span>
  </component>
</template>

<style scoped>
.btn-base {
  @apply overflow-hidden inline-flex relative font-medium rounded-lg cursor-pointer;
}
.btn-content {
  @apply relative flex items-center w-full z-[1];
}
.icon-platform {
  @apply w-5 h-5 mr-2 flex-shrink-0;
}
.icon-download {
  @apply ml-auto pl-4;
}

.btn-base[data-variant='filled'] {
  @apply bg-[#383838] text-[#ffffff]
  before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-white/10 before:rounded-lg
  after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:transition-opacity after:duration-300 after:ease-in-out after:opacity-0 after:rounded-lg
  hover:after:opacity-20;
}

.btn-base[data-variant='outlined'] {
  @apply bg-white text-[#1F1F1F]
  before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-black/10 before:rounded-lg;
}
.btn-base[data-variant='outlined'][data-platform='app_store'] svg,
.btn-base[data-variant='outlined'][data-platform='pc'] svg,
.btn-base[data-variant='outlined'][data-platform='stove'] svg {
  @apply fill-[#1F1F1F];
}

/* default */
.btn-base.default {
  @apply justify-center py-3.5 px-5
  md:py-4 md:px-6;
}
.btn-base.default .btn-content {
  @apply justify-center;
}
.btn-base.default .text {
  @apply line-clamp-2 text-[14px]
  md:text-[16px];
}

.btn-base.default[data-variant='outlined'] .icon-download {
  @apply border-black/10;
}
.btn-base.default[data-variant='outlined'] .icon-download svg {
  @apply fill-[#1F1F1F];
}

/* duplication */
.btn-base.duplication {
  @apply bg-[16px_50%] bg-[length:auto_28px] bg-no-repeat backdrop-blur-[15px]
  pt-[25px] pl-[47px] pr-[22px] pb-[7px] text-[11px]
  md:h-[64px] md:pt-[30px] md:pl-[64px] md:pr-[28px] md:pb-[11px] md:text-[12px] md:bg-[20px_50%] md:bg-[length:auto_40px];
}
.btn-base.duplication[data-platform='google_play'] {
  @apply min-w-[148px] md:min-w-[194px];
}
.btn-base.duplication[data-platform='app_store'] {
  @apply min-w-[132px] md:min-w-[174px];
}
.btn-base.duplication[data-platform='pc'] {
  @apply min-w-[113px] md:min-w-[150px];
}
.btn-base.duplication[data-platform='stove'] {
  @apply min-w-[113px] md:min-w-[150px];
}
.btn-base.duplication .text {
  @apply line-clamp-1;
}

/* single */
.btn-base.single {
  @apply justify-center items-center text-[14px]
  h-[40px] px-3.5
  md:h-[48px];
}
.btn-base.single .btn-content {
  @apply justify-center;
}
.btn-base.single.no-text {
  @apply min-w-[40px] px-0 md:min-w-[48px];
}
.btn-base.single.no-text .icon-platform {
  @apply mx-auto;
}

.btn-base[data-variant='outlined'] {
  @apply hover:before:border-[#999];
}
</style>
