<script setup>
import { computed, ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import Signin from "@/components/Signin.vue";
import { virtualPayOrderAPI, getAppConfig, getHomeData, getOrderDetailAPI } from "@/apis";
import { capsuleHeight, wxLogin } from "@/util";
import useStore from "@/store";
import { storeToRefs } from "pinia";

const store = useStore();
const { user, config } = storeToRefs(store);
const { updateConfig, updateUser } = store;

const currentTypeIndex = ref(1);
const selectedPackageIndex = ref(0);
const showModal = ref(false);
const loadingConfig = ref(false);
const paying = ref(false);
const refreshing = ref(false);

// 会员页核心展示数据：视觉、权益按蓝湖当前两张设计稿拆分，套餐完全使用接口数据。
const memberTypes = [
  {
    key: "normal",
    tab: "VIP",
    title: "普通会员",
    prefix: "成为射灵星球",
    desc: "特享约战竞技次数包、专属会员标识",
    benefitTitle: "普通会员专属权益",
    themeClass: "vip-page--normal",
    heroCard: "https://static.shelingxingqiu.com/shootmini/static/vip/vip-title.png",
    activeHeroCard: "https://static.shelingxingqiu.com/shootmini/static/vip/vip-title2.png",
    orderIcon: "../../static/vip/vip-order.png",
    heroBadge: "../../static/vip/normal-hero-badge.png",
    buttonClass: "activate-btn--normal",
    benefits: [
      { label: "黄金昵称", icon: "../../static/vip/vip-badge.png" },
      { label: "教练点评", icon: "../../static/vip/vip-comment.png" },
      { label: "专享VIP客服", icon: "../../static/vip/vip-service.png" },
      { label: "排位赛\n每日+20次", icon: "../../static/vip/vip-rank.png" },
      { label: "约战\n每日+20次", icon: "../../static/vip/vip-battle.png" },
    ],
  },
  {
    key: "super",
    tab: "SVIP",
    title: "超级会员",
    prefix: "成为射灵星球",
    desc: "尊享专属特效、无限制约战竞技、专属会员标识",
    benefitTitle: "超级会员专属权益",
    themeClass: "vip-page--super",
    heroCard: "https://static.shelingxingqiu.com/shootmini/static/vip/svip-title.png",
    activeHeroCard: "https://static.shelingxingqiu.com/shootmini/static/vip/svip-title2.png",
    orderIcon: "../../static/vip/svip-order.png",
    heroBadge: "../../static/vip/super-hero-badge.png",
    buttonClass: "activate-btn--super",
    benefits: [
      { label: "专属落点标识", icon: "../../static/vip/svip-point.png" },
      { label: "专属命中效果", icon: "../../static/vip/svip-hit.png" },
      { label: "专属射箭效果", icon: "../../static/vip/svip-arrow.png" },
      { label: "炫彩昵称", icon: "../../static/vip/svip-badge.png" },
      { label: "教练点评", icon: "../../static/vip/svip-comment.png" },
      { label: "约战无限制", icon: "../../static/vip/svip-battle.png" },
      { label: "排位赛无限制", icon: "../../static/vip/svip-rank.png" },
      { label: "专享SVIP客服", icon: "../../static/vip/svip-service.png" },
    ],
  },
];

const currentType = computed(() => memberTypes[currentTypeIndex.value]);

// 后端到期时间可能是秒级时间戳、毫秒级时间戳或日期字符串，这里统一转成毫秒。
const toTimestamp = (value) => {
  if (!value) return 0;
  const numberValue = Number(value);
  if (!Number.isNaN(numberValue)) {
    return numberValue < 1000000000000 ? numberValue * 1000 : numberValue;
  }
  const time = new Date(value).getTime();
  return Number.isNaN(time) ? 0 : time;
};

// 当前卡片只关心本 tab 对应的会员到期时间，普通会员和超级会员互不兜底。
const getVipExpiredValue = (type, source = user.value) => {
  if (!source) return 0;
  return type.key === "super" ? source.superVipExpiredAt : source.normalVipExpiredAt;
};

// 未过期才展示“会员生效中”样式，已过期或无值继续展示未开通样式。
const isVipActive = (type) => {
  return toTimestamp(getVipExpiredValue(type)) > Date.now();
};

// 会员卡片展示完整到期时间。
const formatVipDate = (value) => {
  const timestamp = toTimestamp(value);
  if (!timestamp) return "";
  const date = new Date(timestamp);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  const hour = String(date.getHours()).padStart(2, "0");
  const minute = String(date.getMinutes()).padStart(2, "0");
  const second = String(date.getSeconds()).padStart(2, "0");
  return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
};

// 会员生效时使用 title2 切图，未生效时沿用原来的开通引导图。
const getHeroCard = (type) => {
  return isVipActive(type) ? type.activeHeroCard : type.heroCard;
};

const getActiveVipExpiredDate = (type) => {
  return formatVipDate(getVipExpiredValue(type));
};

// 设计稿里的“下期自动续费”按到期日前一天展示。
const getActiveVipRenewDate = (type) => {
  const timestamp = toTimestamp(getVipExpiredValue(type));
  if (!timestamp) return "";
  return formatVipDate(timestamp - 24 * 60 * 60 * 1000);
};

const configMenus = computed(() => {
  return config.value.vipMenus || [];
});

const getMenuName = (item) => {
  return item.name || item.vipName || item.title || "";
};

const formatPrice = (value) => {
  if (value === undefined || value === null || value === "") return "";
  return String(value).replace("￥", "").replace("¥", "");
};

const getMenuPrice = (item) => {
  return formatPrice(item && item.price);
};

const getMenuOriginalPrice = (item) => {
  return formatPrice(item && item.originalPrice);
};

const getMenuSortValue = (item) => {
  const value = item && item.sort;
  if (value === undefined || value === null || value === "") return Number.MAX_SAFE_INTEGER;
  const sort = Number(value);
  return Number.isFinite(sort) ? sort : Number.MAX_SAFE_INTEGER;
};

const sortMenusBySort = (menus = []) => {
  return menus
    .map((item, index) => ({ item, index }))
    .sort((a, b) => {
      const sortDiff = getMenuSortValue(a.item) - getMenuSortValue(b.item);
      return sortDiff || a.index - b.index;
    })
    .map(({ item }) => item);
};

const getMenuType = (item) => {
  const vipType = Number(item.vipType);
  if (vipType === 1) return "normal";
  if (vipType === 2) return "super";

  const type = String(item.type || "").toLowerCase();
  if (["super", "svip"].includes(type)) return "super";
  if (["normal", "vip"].includes(type)) return "normal";

  const name = getMenuName(item);
  if (/超级|SVIP/i.test(name)) return "super";
  if (/普通|VIP|会员/i.test(name)) return "normal";
  return "";
};

const getPackages = (type) => {
  return sortMenusBySort(configMenus.value)
    .filter((item) => getMenuType(item) === type.key)
    .map((item) => {
      return {
        source: item,
        id: item.id,
        name: getMenuName(item),
        price: getMenuPrice(item),
        originalPrice: getMenuOriginalPrice(item),
        icon: item.icon,
      };
    });
};

const currentPackages = computed(() => {
  return getPackages(currentType.value);
});

const selectedPackage = computed(() => {
  return currentPackages.value[selectedPackageIndex.value] || currentPackages.value[0];
});

const switchType = (index) => {
  currentTypeIndex.value = index;
  selectedPackageIndex.value = 0;
};

const onSwiperChange = (event) => {
  currentTypeIndex.value = event.detail.current;
  selectedPackageIndex.value = 0;
};

const selectPackage = (index) => {
  selectedPackageIndex.value = index;
};

const toPackageDesc = () => {
  uni.navigateTo({
    url: "/pages/member/vip-intro",
  });
};

const toOrderPage = () => {
  uni.navigateTo({
    url: "/pages/member/orders",
  });
};

const toAgreement = (type) => {
  uni.navigateTo({
    url: `/pages/member/agreement?type=${type}`,
  });
};

const loadVipConfig = async () => {
  if (loadingConfig.value || configMenus.value.length) return;
  loadingConfig.value = true;
  try {
    const result = await getAppConfig();
    if (result) updateConfig(result);
  } catch (error) {
    console.log("load vip config error", error);
  } finally {
    loadingConfig.value = false;
  }
};

const refreshUserAfterPay = async () => {
  refreshing.value = true;
  try {
    const result = await getHomeData();
    if (result.user) {
      updateUser(result.user);
    }
  } catch (error) {
    console.log("refresh user after pay error", error);
  } finally {
    refreshing.value = false;
  }
};

const getVirtualPaySignData = (result) => {
  // 后端可能返回字符串或对象，这里统一转成微信虚拟支付需要的 JSON 字符串。
  const signDataObj = typeof result?.signData === "string" ? JSON.parse(result.signData) : result?.signData;
  if (!signDataObj) return "";

  // 微信虚拟支付短剧/虚拟商品模式需要购买数量；后端未返回时使用订单数量兜底。
  if (!signDataObj.buyQuantity) {
    signDataObj.buyQuantity = result.quantity || 1;
  }
  return JSON.stringify(signDataObj);
};

const isVirtualPayCancel = (res = {}) => {
  const message = String(res.errMsg || res.message || "").toLowerCase();
  const errCode = Number(res.errCode);
  const errno = Number(res.errno);

  return message.includes("cancel") || errCode === -23 || errno === -2;
};

const onPay = async () => {
  if (paying.value || refreshing.value) return;
  if (!user.value.id) {
    showModal.value = true;
    return;
  }
  if (!configMenus.value.length) {
    await loadVipConfig();
  }
  const vipId = selectedPackage.value && selectedPackage.value.id;
  if (!vipId) {
    uni.showToast({
      title: loadingConfig.value ? "套餐配置加载中" : "套餐暂不可购买",
      icon: "none",
    });
    return;
  }
  if (typeof wx === "undefined" || !wx.requestVirtualPayment) {
    uni.showToast({
      title: "当前环境不支持微信虚拟支付",
      icon: "none",
    });
    return;
  }
  paying.value = true;
  let waitingPayment = false;
  let payToast = null;
  try {
    // 微信虚拟支付创建订单前需要登录 code，服务端用它换取本次支付签名参数。
    const wxResult = await wxLogin();
    const result = await virtualPayOrderAPI(vipId, wxResult.code);
    const finalSignData = getVirtualPaySignData(result);
    if (!finalSignData || !result?.paySig || !result?.signature) {
      uni.showToast({
        title: "支付参数生成失败",
        icon: "none",
      });
      refreshing.value = false;
      return;
    }
    wx.requestVirtualPayment({
      signData: finalSignData,
      paySig: result.paySig,
      signature: result.signature,
      mode: "short_series_goods",
      async success() {
        payToast = {
          title: "支付成功",
          icon: "success",
        };
        if (result?.outTradeNo) {
          try {
            const orderDetail = await getOrderDetailAPI(result.outTradeNo);
            console.log("virtual pay order detail", orderDetail);
          } catch (error) {
            console.log("virtual pay order detail error", error);
          }
        }
        // 客户端支付成功后，会员是否真正生效仍以服务端用户信息刷新结果为准。
        refreshUserAfterPay();
      },
      fail(res) {
        console.log("virtual pay error", res);
        if (isVirtualPayCancel(res)) {
          payToast = {
            title: "支付已取消",
            icon: "none",
          };
          return;
        }
        payToast = {
          title: res.message || "支付失败，请稍后重试",
          icon: "none",
        };
      },
      complete() {
        paying.value = false;
        if (payToast) {
          setTimeout(() => {
            uni.showToast(payToast);
          }, 200);
        }
      },
    });
    waitingPayment = true;
  } catch (error) {
    console.log("create virtual pay order error", error);
    uni.showToast({
      title: error.message || "下单失败",
      icon: "none",
    });
  } finally {
    if (!waitingPayment) paying.value = false;
  }
};

onShow(loadVipConfig);

</script>

<template>
  <Container title="" :bgType="10" :scroll="false" :showBottom="false">
    <view class="vip-page" :class="currentType.themeClass">
      <view class="type-tabs" :style="{ top: capsuleHeight + 'px' }">
        <view
          v-for="(item, index) in memberTypes"
          :key="item.key"
          class="type-tab"
          :class="{ 'type-tab--active': currentTypeIndex === index }"
          @click="switchType(index)"
        >
          <text>{{ item.tab }}</text>
          <view class="type-tab__indicator" />
        </view>
      </view>
      <swiper
        class="type-swiper"
        :current="currentTypeIndex"
        :duration="260"
        @change="onSwiperChange"
      >
        <swiper-item v-for="type in memberTypes" :key="type.key">
          <scroll-view scroll-y class="type-scroll" :show-scrollbar="false">
            <view class="vip-content">
              <view
                class="hero-card"
                :class="{ 'hero-card--active': isVipActive(type) }"
              >
                <image class="hero-card__bg" :src="getHeroCard(type)" mode="scaleToFill" />
                <!-- 生效态卡片使用 title2 底图，补充有效期和订单入口叠层。 -->
                <view v-if="isVipActive(type)" class="hero-card__content">
                  <text class="hero-card__date">
                    有效期至：{{ getActiveVipExpiredDate(type) }}
                  </text>
                  <!-- <text v-if="type.key === 'super'" class="hero-card__renew">
                    下期会员将于：{{ getActiveVipRenewDate(type) }}自动续费
                  </text> -->
                  <view class="hero-card__order" @click.stop="toOrderPage">
                    <image class="hero-card__order-icon" :src="type.orderIcon" mode="aspectFit" />
                    <text>订单管理</text>
                  </view>
                </view>
              </view>

              <view class="benefit-title">
                <view class="benefit-title__line" />
                <text>{{ type.benefitTitle }}</text>
                <view class="benefit-title__line" />
              </view>

              <view class="benefit-grid" :class="{ 'benefit-grid--normal': type.key === 'normal' }">
                <view
                  v-for="benefit in type.benefits"
                  :key="benefit.label"
                  class="benefit-item"
                >
                  <view class="benefit-icon">
                    <image class="benefit-icon__img" :src="benefit.icon" mode="aspectFit" />
                  </view>
                  <text class="benefit-item__label">{{ benefit.label }}</text>
                </view>
              </view>

              <view class="package-header">
                <text class="package-header__title">选择套餐</text>
                <view class="package-header__link" @click="toPackageDesc">
                  <text>套餐说明</text>
                  <image
                    class="package-header__icon"
                    src="../../static/enter.png"
                    mode="aspectFit"
                  />
                </view>
              </view>

              <scroll-view scroll-x class="package-scroll" :show-scrollbar="false">
                <view class="package-list">
                  <view
                    v-for="(pack, index) in getPackages(type)"
                    :key="`${type.key}-${pack.id || pack.name || index}`"
                    class="package-card"
                    :class="{ 'package-card--active': selectedPackageIndex === index }"
                    @click="selectPackage(index)"
                  >
                    <view class="package-card__inner">
                      <text class="package-name">{{ pack.name }}</text>
                      <view class="package-price">
                        <text class="package-price__symbol">¥</text>
                        <text class="package-price__value">{{ pack.price }}</text>
                      </view>
                      <view v-if="pack.originalPrice" class="package-origin">
                        <text>¥{{ pack.originalPrice }}</text>
                        <view class="package-origin__line" />
                      </view>
                    </view>
                  </view>
                </view>
              </scroll-view>

              <button
                hover-class="none"
                class="activate-btn"
                :class="type.buttonClass"
                :disabled="loadingConfig || paying || refreshing || !selectedPackage"
                @click="onPay"
              >
                <text v-if="loadingConfig">加载套餐中</text>
                <text v-else-if="paying">创建订单中</text>
                <text v-else-if="refreshing">刷新会员状态中</text>
                <text v-else-if="selectedPackage">¥ {{ selectedPackage.price }} 一键激活</text>
                <text v-else>套餐暂不可购买</text>
              </button>

              <view class="agreement">
                <text>支付即同意</text>
                《&nbsp;<text class="agreement__link" @click.stop="toAgreement('renew')">会员自动续费服务协议</text>》
                《&nbsp;<text class="agreement__link" @click.stop="toAgreement('deduct')">扣款授权服务协议</text>》
              </view>
            </view>
          </scroll-view>
        </swiper-item>
      </swiper>
      <Signin :show="showModal" :onClose="() => (showModal = false)" />
    </view>
  </Container>
</template>

<style scoped>
.vip-page {
  position: relative;
  width: 100%;
  height: 100%;
}
.type-tabs {
  position: fixed;
  left: 0;
  z-index: 998;
  width: 50%;
  height: 50px;
  margin-left: 50%;
  transform:translateX(-60%);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: auto;
}

.type-tab {
  width: 132rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.45);
  font-size: 34rpx;
  font-weight: 700;
  font-style: italic;
}

.type-tab__indicator {
  width: 40rpx;
  height: 4rpx;
  border-radius: 4rpx;
  margin-top: 8rpx;
  background-color: transparent;
}

.type-tab--active {
  color: #ffffff;
}

.vip-page--normal .type-tab--active .type-tab__indicator {
  background-color: #ffffff;
}

.vip-page--super .type-tab--active {
  color: #fedab5;
}

.vip-page--super .type-tab--active .type-tab__indicator {
  background-color: #fedab5;
}

.type-swiper {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
}

.type-scroll {
  width: 100%;
  height: 100%;
}

.vip-content {
  min-height: 100%;
  padding: 32rpx 24rpx 52rpx;
  box-sizing: border-box;
}

.hero-card {
  position: relative;
  width: 702rpx;
  height: 260rpx;
  overflow: hidden;
}

.hero-card__bg {
  position: absolute;
  left: 0;
  top: 0;
  width: 702rpx;
  height: 260rpx;
}

.hero-card__content {
  position: relative;
  z-index: 1;
  /* 对齐 title2 切图左侧预留文案区域。 */
  padding: 132rpx 0 0 44rpx;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  box-sizing: border-box;
}

.hero-card__date,
.hero-card__renew {
  color: #8d6d55;
  font-size: 24rpx;
  line-height: 34rpx;
}

.vip-page--normal .hero-card__date,
.vip-page--normal .hero-card__renew {
  color: #555555;
}

.hero-card__order {
  display: flex;
  align-items: center;
  margin-top: 10rpx;
  color: #6d5644;
  font-size: 24rpx;
  line-height: 34rpx;
  text-decoration: underline;
}

.vip-page--normal .hero-card__order {
  color: #555555;
}

.hero-card__order-icon {
  width: 28rpx;
  height: 32rpx;
  margin-right: 8rpx;
  flex-shrink: 0;
}

.benefit-title {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 38rpx;
  color: #ffffff;
  font-size: 24rpx;
  line-height: 34rpx;
}

.benefit-title__line {
  width: 14rpx;
  height: 2rpx;
  background-color: #ffffff;
  margin: 0 10rpx;
}

.benefit-grid {
  display: flex;
  flex-wrap: wrap;
  width: 622rpx;
  margin: 38rpx auto 0;
}

.benefit-grid--normal {
  width: 672rpx;
}

.benefit-item {
  width: 144rpx;
  height: 122rpx;
  margin-right: 94rpx;
  margin-bottom: 30rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.benefit-item:nth-child(3n) {
  margin-right: 0;
}

.benefit-grid--normal .benefit-item {
  margin-right: 120rpx;
}

.benefit-grid--normal .benefit-item:nth-child(3n) {
  margin-right: 0;
}

.benefit-icon {
  width: 80rpx;
  height: 80rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.benefit-icon__img {
  width: 80rpx;
  height: 80rpx;
  display: block;
}

.benefit-item__label {
  margin-top: 8rpx;
  color: #ffffff;
  opacity: 0.7;
  font-size: 24rpx;
  line-height: 34rpx;
  text-align: center;
  white-space: pre-line;
}

.package-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 56rpx;
  padding-right: 8rpx;
}

.benefit-grid--normal + .package-header {
  margin-top: 146rpx;
}

.package-header__title {
  color: #ffffff;
  font-size: 28rpx;
  line-height: 40rpx;
  font-weight: 500;
}

.vip-page--super .package-header__title {
  color: #e7ba80;
}

.package-header__link {
  display: flex;
  align-items: center;
  color: #999999;
  font-size: 22rpx;
  line-height: 32rpx;
}

.package-header__icon {
  width: 24rpx;
  height: 28rpx;
}

.package-scroll {
  width: 100%;
  margin-top: 40rpx;
  white-space: nowrap;
}

.package-list {
  display: inline-flex;
  min-width: 100%;
  padding: 6rpx 84rpx 6rpx 6rpx;
  box-sizing: border-box;
}

.package-card {
  position: relative;
  width: 264rpx;
  flex: 0 0 264rpx;
  height: 224rpx;
  border-radius: 16rpx;
  border: 2rpx solid #999999;
  margin-right: 32rpx;
  padding: 0;
  overflow: hidden;
  box-sizing: border-box;
  color: #999999;
}

.package-card__inner {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  border-radius: inherit;
}

.package-card--active {
  border-width: 6rpx;
  border-color: #fed847;
}

.vip-page--super .package-card--active {
  border: none;
  padding: 6rpx;
  background: linear-gradient(180deg, #fef3e6 0%, #f0c191 100%);
}

.vip-page--super .package-card--active .package-card__inner {
  border-radius: 10rpx;
  background-color: #050b19;
}

.package-name {
  font-size: 24rpx;
  line-height: 34rpx;
}

.package-price {
  display: flex;
  align-items: baseline;
  margin-top: 12rpx;
  color: #ffffff;
}

.package-card--active .package-price {
  color: #fed847;
}

.vip-page--super .package-card--active .package-price {
  color: #ffe8cd;
}

.package-price__symbol {
  font-size: 30rpx;
  line-height: 36rpx;
  font-weight: 700;
}

.package-price__value {
  font-size: 56rpx;
  line-height: 66rpx;
  font-weight: 700;
}

.package-origin {
  position: relative;
  margin-top: 2rpx;
  color: #999999;
  font-size: 24rpx;
  line-height: 34rpx;
}

.package-origin__line {
  position: absolute;
  left: -4rpx;
  right: -4rpx;
  top: 16rpx;
  height: 2rpx;
  background-color: #999999;
}

.activate-btn {
  width: 686rpx;
  height: 88rpx;
  border-radius: 44rpx;
  margin: 34rpx auto 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #000000;
  font-size: 30rpx;
  line-height: 42rpx;
  font-weight: 500;
}

.activate-btn::after {
  border: none;
}

.activate-btn--normal {
  background-color: #fed847;
}

.activate-btn--super {
  background: linear-gradient( 181deg, #FDFDFC 0%, #FDF8F2 0%, #FFC992 100%, #FFB96C 100%);
}

.agreement {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 24rpx;
  color: #999999;
  font-size: 20rpx;
  line-height: 28rpx;
}

.agreement__link {
  margin-left: -6rpx;
  text-decoration: underline;
}
</style>
