<script setup lang="ts">
import { getGoodsByIdApi } from '@/api/goods'
import { onLoad } from '@dcloudio/uni-app'
import { ref, watchEffect, reactive, computed } from 'vue'
import type { goodsResult, goodsServiceItem, skuItem } from '@/types/goods'
import type {
  SkuPopupEvent,
  SkuPopupInstance,
  SkuPopupLocaldata,
} from '@/components/vk-data-goods-sku-popup/vk-data-goods-sku-popup'
import { addCartApi } from '@/api/cart'
import { useAddressStore } from '@/stores/modules/address'
import { previewImg, fullUrl, arrayFullUrl, onShowRefreshData } from '@/utils/common'
import { pageUrl, safeBottom, pageMateStyle, isIOSWithHomeIndicator } from '@/utils/constants'
import { useCartStore } from '@/stores'
import { postAddFavoriteApi, postCancelFavoriteApi } from '@/api/favorite'
import _, { debounce } from 'lodash'
import { onShareAppMessage } from '@dcloudio/uni-app'
import { useMemberStore } from '@/stores'
import { getAddressApi } from '@/api/address'
import type { addressItem } from '@/types/address'
import { computeConversion } from '@/utils/common'
import servicePanel from './components/servicePanel.vue'
import addressPanel from './components/addressPanel.vue'
import sharePanel from './components/sharePanel.vue'
import sharePoster from './components/sharePoster.vue'
import { usePopupStore } from '@/stores'

const props = defineProps<{
  id: string | number
  scene?: string
}>()

//接收参数
const query = reactive({
  id: props.id,
  scene: props.scene,
})

const cartStore = useCartStore()

//商品sku弹窗
const isShowSku = ref(false)
//商品sku数据
const skuData = ref({} as SkuPopupLocaldata)
//sku按钮模式
enum skuskuModeType {
  both = 1,
  cart = 2,
  buy = 3,
}
const skuMode = ref<skuskuModeType>(skuskuModeType.both)
//sku弹窗ref实例
const skuPopupRef = ref<SkuPopupInstance>()
//sku中被选中的值
const selectAttrText = computed(() => {
  return skuPopupRef.value?.selectArr?.join(' ').trim() || '请选择商品规格'
})
// 计算当前显示的价格
const selectedPrice = ref(0)
const currentPrice = computed(() => selectedPrice.value || goods.value?.min_price || 0)
// 计算当前显示的划线价
const selectedOriginPrice = ref(0)
const currentOriginPrice = computed(
  () => selectedOriginPrice.value || goods.value?.max_origin_price || 0,
)

//打开sku弹窗
const openSkuPopup = (mode: skuskuModeType) => {
  isShowSku.value = true
  skuMode.value = mode
}

const goodsServiceList = ref<goodsServiceItem[]>([])
const goodsServiceText = ref('')
//商品详情
const goods = ref<goodsResult>()
const getGoodsDataById = async () => {
  const res = await getGoodsByIdApi(Number(query.id))
  goods.value = res.result

  //设置sku组件所需数据
  skuData.value = {
    _id: res.result.id.toString(),
    name: res.result.name,
    goods_thumb: fullUrl(res.result.images[0]),
    spec_list: res.result.spec_list.map((spec) => {
      return {
        name: spec.name,
        list: spec.value,
      }
    }),
    sku_list: res.result.sku_list.map((sku) => {
      return {
        _id: sku.id.toString(),
        goods_id: res.result.id.toString(),
        goods_name: res.result.name,
        image: fullUrl(sku.image),
        price: sku.price,
        origin_price: sku.origin_price,
        sku_name_arr: sku.spec?.map((sku_name) => sku_name.value),
        stock: sku.stock,
      }
    }),
  }

  //服务与承诺
  goodsServiceList.value = goods.value.goods_service
  goodsServiceText.value = goods.value.goods_service.map((item) => item.name).join(' ')
}

//更新轮播图下标
const currentIndex = ref(0)
const updateIndex: UniHelper.SwiperOnChange = (event) => {
  currentIndex.value = event.detail.current
}
//弹出层ref
const popup = ref<{
  open: (type?: UniHelper.UniPopupType) => void
  close: () => void
}>()
//调用弹出层
const popupName = ref<'address' | 'service' | 'share' | 'sharePoster'>()
const openPopup = (name: typeof popupName.value) => {
  popupName.value = name
  popup.value?.open()
}

//添加购物车
const onAddCart = (event: SkuPopupEvent) => {
  addCartApi({
    sku_id: event._id,
    num: event.buy_num,
  }).then((res) => {
    cartStore.setCartTotalNum(res.result.total_num)
    cartInfo.value = res.result.total_num
    isShowSku.value = false
    uni.showToast({
      title: '加入购物车成功',
      icon: 'success',
      mask: true,
    })
  })
}

//跳转下单页
const onBuyNow = (event: SkuPopupEvent) => {
  console.log(event)
  isShowSku.value = false
  uni.navigateTo({
    url: `${pageUrl['order-create']}?sku_id=${event._id}&count=${event.buy_num}`,
  })
}

//规格选择后处理
const onSpecSelected = (skuData: skuItem) => {
  selectedPrice.value = skuData.price
  selectedOriginPrice.value = skuData.origin_price
}

// 收货地址
const addressStore = useAddressStore()
const selectAddressText = computed(() => {
  return addressStore.selectedAddress
    ? addressStore.selectedAddress.full_location
    : '请选择收货地址'
})

const addressList = ref<addressItem[]>([])
const openAddressPopup = () => {
  getAddressApi().then((res) => {
    addressList.value = res.result.data
    openPopup('address')
  })
}

const getMoreEvaluate = () => {
  uni.navigateTo({
    url: `${pageUrl['shopping-mall-goods-evaluate']}?goods_id=${query.id}`,
  })
}

const cartInfo = ref(0)
const menuButtons = computed<UniHelper.UniGoodsNavOption[]>(() => [
  {
    icon: 'shop',
    text: '商城',
  },
  {
    icon: 'cart',
    text: '购物车',
    info: cartInfo.value,
  },
  {
    icon: 'redo',
    text: '分享',
  },
])
const menuClick = (event: UniHelper.UniGoodsNavOnClickEvent) => {
  switch (event.index) {
    case 0:
      uni.redirectTo({
        url: `${pageUrl['shopping-mall']}`,
      })
      break
    case 1:
      uni.redirectTo({
        url: `${pageUrl['shopping-mall-cart']}`,
      })
      break
    case 2:
      showSharePopup()
      break
  }
}

const operateButtons: UniHelper.UniGoodsNavButton[] = [
  {
    text: '加入购物车',
    backgroundColor: '#ffa200',
    color: '#fff',
  },
  {
    text: '立即购买',
    backgroundColor: '#ff0000',
    color: '#fff',
  },
]
const buttonClick = (event: UniHelper.UniGoodsNavOnButtonClickEvent) => {
  switch (event.index) {
    case 0:
      openSkuPopup(skuskuModeType.cart)
      break
    case 1:
      openSkuPopup(skuskuModeType.buy)
      break
  }
}

const changeFavoriteStatus = debounce((goods) => {
  if (goods.favorite === true) {
    postCancelFavoriteApi({
      goods_id: goods.id,
    }).then((res) => {
      if (res.result) {
        goods.favorite = false
        uni.showToast({
          title: '商品取消收藏',
          icon: 'none',
        })
      }
    })
  } else {
    postAddFavoriteApi({
      goods_id: goods.id,
    })
      .then((res) => {
        if (res.result) {
          goods.favorite = true
          uni.showToast({
            title: '商品收藏成功',
            icon: 'none',
          })
        }
      })
      .catch((err) => {
        console.log(err)
      })
  }
}, 500)

watchEffect(() => {
  cartInfo.value = useCartStore().cartTotalNum
})

const sharePopupRef = ref()
// 分享弹窗
const showSharePopup = () => {
  if (!useMemberStore().profile?.id) {
    return uni.showModal({
      title: '温馨提示',
      content: '登录解锁更多精彩,是否继续?',
      confirmText: '去登录',
      cancelText: '再看看',
      success: function (res) {
        if (res.confirm) {
          uni.navigateTo({ url: pageUrl['login'] })
        }
      },
    })
  }

  openPopup('share')
}

const sharePosterRef = ref()
const goodsImage = ref('')
const onShowPoster = () => {
  sharePosterRef.value.open()
  goodsImage.value = goods.value!.images[currentIndex.value] || goods.value!.images[0]
}

onShareAppMessage(() => {
  sharePopupRef.value.close()

  const sharePath = `${pageUrl['shopping-mall-goods-detail']}?id=${goods.value?.id}&sharer=${
    useMemberStore().profile?.id
  }`
  console.log(sharePath)

  return {
    title: goods.value?.name,
    path: sharePath,
    imageUrl: fullUrl(goods.value!.images[0]),
  }
})

onShowRefreshData(() => {
  if (props.scene) {
    const params = decodeURIComponent(props.scene)
      .split('&')
      .reduce((acc: { [key: string]: any }, curr) => {
        const [key, value] = curr.split('=')
        acc[key] = value
        return acc
      }, {})
    console.log('解析scene', params)
    if (params.id) {
      query.id = params.id
    }
  }

  getGoodsDataById()
})

onLoad(() => {
  // #ifdef WEB
  // 兼容带有底部导航的IOS设备
  if (isIOSWithHomeIndicator()) {
    document.documentElement.classList.add('ios-device')
  }
  // #endif

  // #ifdef MP-WEIXIN
  uni.showShareMenu({
    withShareTicket: true,
    menus: ['shareAppMessage'],
  })
  // #endif
})
</script>

<template>
  <!-- #ifdef MP-WEIXIN -->
  <page-meta :page-style="pageMateStyle">
    <!-- #endif -->
    <scroll-view scroll-y class="viewport" :style="safeBottom" v-if="goods">
      <!-- 基本信息 -->
      <view class="goods">
        <!-- 商品主图 -->
        <view class="preview">
          <swiper circular @change="updateIndex" autoplay>
            <swiper-item v-for="item in goods?.images" :key="item">
              <image
                class="image"
                :src="fullUrl(item)"
                @tap="previewImg(item, arrayFullUrl(goods!.images))"
              />
            </swiper-item>
          </swiper>
          <view class="indicator">
            <text class="current">{{ currentIndex + 1 }}</text>
            <text class="split">/</text>
            <text class="total">{{ goods?.images.length }}</text>
          </view>
        </view>
      </view>

      <view class="panel">
        <view class="meta">
          <view class="meta-top">
            <view class="price">
              <view class="origin">¥{{ currentOriginPrice }} </view>
              <view class="current">
                <text class="symbol">¥</text>
                <text class="number">{{ currentPrice }}</text>
              </view>
            </view>
            <view class="operate">
              <view class="operate-item" @tap="changeFavoriteStatus(goods!)" v-if="goods.favorite">
                <button class="operate-item-btn">
                  <text class="icon icon-favorite-checked" />
                </button>
                <text class="icon-text">已收藏</text>
              </view>
              <view class="operate-item" @tap="changeFavoriteStatus(goods!)" v-else>
                <button class="operate-item-btn">
                  <text class="icon icon-favorite-default" />
                </button>
                <text class="icon-text">收藏</text>
              </view>
              <!-- #ifdef MP-WEIXIN -->
              <view class="operate-item">
                <button open-type="contact" class="operate-item-btn">
                  <text class="icon-handset"></text>
                </button>
                <view class="icon-text">
                  <text>客服</text>
                </view>
              </view>
              <!-- #endif -->
            </view>
          </view>
          <view class="name-box">
            <view class="name ellipsis">{{ goods?.name }} </view>
            <view class="sales">
              已售{{ computeConversion(goods.sales_init + goods.sales_real) }}</view
            >
          </view>
        </view>
      </view>

      <view class="panel">
        <view class="action">
          <view class="item arrow" @tap="openSkuPopup(skuskuModeType.both)">
            <text class="label">已选</text>
            <text class="text ellipsis">{{ selectAttrText }}</text>
          </view>
          <view class="item arrow" @tap="openAddressPopup">
            <text class="label">送至</text>
            <text class="text ellipsis">{{ selectAddressText }}</text>
          </view>
          <view class="item arrow" @tap="openPopup('service')">
            <text class="label">服务</text>
            <text class="text ellipsis">{{ goodsServiceText }}</text>
          </view>
        </view>
        <!-- 弹出层 -->
        <uni-popup
          ref="popup"
          type="bottom"
          background-color="#fff"
          @change="usePopupStore().onChangePopupProps"
        >
          <address-panel
            v-if="popupName === 'address'"
            @close="popup?.close()"
            :list="addressList"
          />
          <service-panel
            v-if="popupName === 'service'"
            :list="goodsServiceList"
            @close="popup?.close()"
          />
          <share-panel
            v-if="popupName === 'share'"
            @close="popup?.close()"
            @showPoster="onShowPoster"
            :goods="goods"
          />
        </uni-popup>
      </view>

      <!-- 商品评价 -->
      <view class="panel">
        <view v-if="goods?.evaluate_count > 0" @click="getMoreEvaluate">
          <uni-section :title="`评价 (${computeConversion(goods?.evaluate_count)})`" type="line">
            <template #right>
              <view class="tip">
                <text> 好评率 {{ goods?.positive_rate }}%</text>
                <uni-icons type="forward" size="14" color="#909399" class="icon"></uni-icons>
              </view>
            </template>
            <view class="eva-box" v-for="(evaluate, index) in goods?.evaluate" :key="index">
              <view class="top">
                <shop-user-avatar
                  :url="evaluate.user_avatar"
                  width="50"
                  style="padding-right: 10rpx"
                />
                <text class="name">{{ evaluate.user_name }}</text>
                <view class="rate">
                  <uni-rate :value="evaluate.score" :size="20" readonly />
                </view>
              </view>
              <text class="content">{{ evaluate.content }}</text>
              <scroll-view class="scroll-view-container" :scroll-x="true">
                <image
                  class="content-img"
                  mode="aspectFill"
                  v-for="(item, index) in arrayFullUrl(evaluate.images)"
                  :key="index"
                  :src="item"
                  @click.stop="previewImg(item, evaluate.images)"
                />
              </scroll-view>
              <view class="bot"> </view>
            </view>
          </uni-section>
        </view>
        <view v-else>
          <uni-section title="评价 (0)" type="line">
            <z-paging-empty-view empty-view-text="期待您的评价" :empty-view-fixed="false" />
          </uni-section>
        </view>
      </view>

      <view class="panel">
        <uni-section title="详情" type="line">
          <view class="properties">
            <view class="item" v-for="item in goods?.params" :key="item.key">
              <text class="label">{{ item.key }}</text>
              <text class="value">{{ item.value }}</text>
            </view>
          </view>
        </uni-section>
        <view v-if="goods.detail_images.length > 0">
          <shop-image :src="goods?.detail_images" />
        </view>
      </view>

      <view :style="{ paddingBottom: '5rpx' }"> </view>

      <!-- sku弹窗 -->
      <vk-data-goods-sku-popup
        v-model="isShowSku"
        :localdata="skuData"
        :mode="skuMode"
        buy-now-background-color="#ff0000"
        add-cart-background-color="#ffa200"
        :amountType="0"
        ref="skuPopupRef"
        :actived-style="{
          color: '#ff0000',
          backgroundColor: '#fee8e6',
          borderColor: '#ff0000',
        }"
        @add-cart="onAddCart"
        @buy-now="onBuyNow"
        @spec-selected="onSpecSelected"
        class="sku-popup"
      />

      <!-- 海报弹窗 -->
      <sharePoster
        ref="sharePosterRef"
        :goods="goods"
        :currentPrice="currentPrice"
        :currentOriginPrice="currentOriginPrice"
        :goodsImage="goodsImage"
      />

      <!-- 用户操作 -->
      <view class="goods-nav" :style="safeBottom" v-show="goods">
        <uni-goods-nav
          :fill="true"
          :options="menuButtons"
          :buttonGroup="operateButtons"
          @click="menuClick"
          @buttonClick="buttonClick"
        />
      </view>
    </scroll-view>
    <!-- #ifdef MP-WEIXIN -->
  </page-meta>
  <!-- #endif -->
</template>

<style lang="scss">
swiper {
  height: 100%;
}

page {
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.viewport {
  background-color: #f4f4f4;
  z-index: 999;
  margin-bottom: 40px;
}

.panel {
  background-color: #fff;
  border-radius: 10rpx;
  margin: 15rpx 15rpx 20rpx;
  padding: 10rpx;
}

.arrow {
  &::after {
    position: absolute;
    top: 50%;
    right: 30rpx;
    content: '\e6c2';
    color: #ccc;
    font-family: 'iconfont' !important;
    font-size: 32rpx;
    transform: translateY(-50%);
  }
}

/* 商品信息 */
.goods {
  background-color: #fff;
  margin: 15rpx 15rpx 20rpx;

  .preview {
    height: 750rpx;
    position: relative;
    .image {
      width: 750rpx;
      height: 750rpx;
    }
    .indicator {
      height: 40rpx;
      padding: 0 24rpx;
      line-height: 40rpx;
      border-radius: 30rpx;
      color: #fff;
      font-family: Arial, Helvetica, sans-serif;
      background-color: rgba(0, 0, 0, 0.3);
      position: absolute;
      bottom: 30rpx;
      right: 30rpx;
      .current {
        font-size: 26rpx;
      }
      .split {
        font-size: 24rpx;
        margin: 0 1rpx 0 2rpx;
      }
      .total {
        font-size: 24rpx;
      }
    }
  }
}

.meta {
  .meta-top {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
  }

  .operate {
    display: flex;

    .operate-item {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;

      .operate-item-btn {
        width: 80rpx;
        height: 80rpx;
        background-color: transparent;

        &::after {
          border: none;
        }
      }

      .icon {
        text-align: center;
      }

      .icon-text {
        font-size: 20rpx;
        color: #9a9a9a;
      }

      .icon-favorite-checked {
        color: red;
      }
    }
  }

  .price {
    height: 130rpx;
    padding: 0rpx 20rpx;
    color: red;
    font-size: 34rpx;
    box-sizing: border-box;
    background-color: #fff;
    display: flex;
    flex-direction: column;

    .origin {
      margin-top: 15rpx;
      color: #888;
      text-decoration: line-through;

      ::after {
        content: ￥;
      }
    }
  }
  .number {
    font-size: 50rpx;
  }
  .brand {
    width: 160rpx;
    height: 80rpx;
    overflow: hidden;
    position: absolute;
    top: 26rpx;
    right: 30rpx;
  }
  .name {
    max-height: 88rpx;
    line-height: 1.4;
    margin: 20rpx;
    font-size: 32rpx;
    color: #333;
  }
  .desc {
    line-height: 1;
    padding: 0 20rpx 30rpx;
    font-size: 24rpx;
    color: #cf4444;
  }
  .sales {
    margin: 20rpx;
    font-size: 24rpx;
    color: #888;
  }
}

.action {
  padding-left: 10rpx;
  background: #fff;

  .item {
    height: 90rpx;
    padding-right: 60rpx;
    border-bottom: 1rpx solid #eaeaea;
    font-size: 26rpx;
    color: #333;
    position: relative;
    display: flex;
    align-items: center;
    &:last-child {
      border-bottom: 0 none;
    }
  }
  .label {
    width: 60rpx;
    color: #898b94;
    margin: 0 16rpx 0 10rpx;
  }
  .text {
    flex: 1;
    -webkit-line-clamp: 1;
  }
}

.tip {
  font-size: 24rpx;
  color: #9a9a9a;

  .icon {
    padding-left: 10rpx;
  }
}

.eva-box {
  padding: 10rpx;

  .top {
    display: flex;
    align-items: center;
    padding-bottom: 20rpx;

    .name {
      flex: 1;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      font-size: 26rpx;
      padding-bottom: 10rpx;
    }
  }

  .rate {
    margin-right: 10rpx;
  }

  .content {
    margin: 0rpx 10rpx 10rpx;
    max-height: 100rpx;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    font-size: 24rpx;
  }

  .scroll-view-container {
    width: 100%;
    white-space: nowrap;
    overflow-x: scroll;
    -webkit-overflow-scrolling: touch;

    .content-img {
      margin-left: 10rpx;
      height: 150rpx;
      width: 150rpx;
      margin-bottom: 10rpx;
      margin-right: 10rpx;
      border-radius: 10rpx;
      margin-top: 10rpx;
      scroll-snap-align: start;
    }
  }
}

.properties {
  padding: 0 20rpx;

  .item {
    display: flex;
    line-height: 2;
    padding: 10rpx;
    font-size: 26rpx;
    color: #333;
    border-bottom: 1rpx dashed #ccc;
  }
  .label {
    width: 200rpx;
  }
  .value {
    flex: 1;
  }
}

/* 底部工具栏 */
.goods-nav {
  position: fixed;
  bottom: 0;
  width: 100%;
  background-color: #fff;
}

/* #ifdef WEB */
// 当根元素有 ios-device 类时，兼容底部样式
.ios-device {
  .viewport {
    padding-bottom: 34px !important;
  }

  .goods-nav {
    padding-bottom: 34px !important;
  }
}
/* #endif */
</style>
