<template>
  <view class="contribution-list" v-if="visible">
    <!-- 渐变模糊背景层 -->
    <view class="list-bg"></view>
    <scroll-view
      class="list-content"
      scroll-y
      :scroll-into-view="latestRecordId"
      :scroll-with-animation="true"
      :show-scrollbar="false"
      :enhanced="true"
      :bounces="false"
    >
      <view
        v-for="(record, index) in records"
        :key="record.id"
        :id="`contribution-record-${record.id}`"
        class="contribution-item"
        :class="{ 'new-item': index === records.length - 1, 'fading-out': record.fading }"
      >
        <!-- 左侧：用户信息（头像 + 昵称 + 赠送动作） -->
        <view class="user-info">
          <image
            class="user-avatar"
            :src="record.avatar_url"
            mode="aspectFill"
          />
          <view class="user-text">
            <text class="user-nickname">{{ record.nickname }}</text>
            <text class="gift-text" v-if="record.item_name"
              >送{{ record.item_name }}</text
            >
          </view>
        </view>

        <!-- 右侧：道具图标（外层模块带 11° 旋转 + 红色阴影） -->
        <view class="item-icon-wrap">
          <image class="item-icon" :src="record.item_icon" mode="aspectFill" />
          <view class="quantity-info">
            <text class="item-x">X</text>
            <text
              class="item-count"
              :class="getCountSizeClass(record.quantity)"
              >{{ record.quantity }}</text
            >
          </view>
        </view>
      </view>
    </scroll-view>
  </view>
</template>

<script setup>
import { ref, computed, watch, onMounted, onUnmounted } from "vue";
import { useContributionRealtime } from "../composables/useContributionRealtime.js";

const props = defineProps({
  activityId: {
    type: String,
    required: true,
  },
});

const isPageActive = ref(true);

// 使用实时 composable（WS 优先，断线降级为轮询）
const { records, visible, loading, error, isUsingWS } = useContributionRealtime(
  computed(() => props.activityId),
  isPageActive,
);

onMounted(() => {
  isPageActive.value = true;
});

// 实时 composable 内部已在 onMounted/onUnmounted 中处理 start/stop/reset，
// 此处无需重复调用 stop()。
onUnmounted(() => {
  // 仅将页面标记为非激活；实际资源释放由 useContributionRealtime 内部完成。
  isPageActive.value = false;
});

// 暴露给父组件使用
defineExpose({
  // useContributionRealtime 内部管理生命周期，无需对外暴露 reset。
});

/**
 * 根据数量值映射数字字号档位
 * - >= 999    → count-largest（最大）
 * - 520 ~ 998 → count-mid（次大）
 * - <  520    → count-small（最小）
 */
const getCountSizeClass = (value) => {
  const n = Number(value) || 0;
  if (n >= 999) return "count-largest";
  if (n >= 520) return "count-mid";
  return "count-small";
};

// scroll-into-view 直接滚到指定 id 的元素,比 scroll-top 更可靠(不用猜位置)。
// 通过"先清空、再设值"的方式,确保每次都能触发 scroll-view 滚动
// (因为 scroll-into-view 值未变化时不会重新滚动)。
//
// 关键设计:不能依赖 records[0] 或 records[N-1] 来定位"最新记录"——
// WS 路径是 append(最新在尾),polling 路径是 prepend(最新在头),方向相反。
// 由于 id 单调递增(后端保证 + useContributionRealtime 也用 highestIdRef 判断),
// 所以直接找 id 最大的那条记录,无论它在头还是在尾,都能正确滚过去。
const latestRecordId = ref("");
let scrollTimerId = null;

function getMaxIdRecord() {
  const list = records.value;
  if (list.length === 0) return null;
  let max = list[0];
  for (let i = 1; i < list.length; i++) {
    if (list[i].id > max.id) max = list[i];
  }
  return max;
}

function scrollToLatest() {
  // 防抖:快速连续触发时只滚最后一次
  if (scrollTimerId) clearTimeout(scrollTimerId);
  scrollTimerId = setTimeout(() => {
    const target = getMaxIdRecord();
    if (!target) return;
    const targetId = `contribution-record-${target.id}`;
    // 关键:清空再赋值,确保 scroll-into-view 一定触发
    latestRecordId.value = "";
    // 用 setTimeout 把赋值推到下一个宏任务,避开 Vue 的批处理
    setTimeout(() => {
      latestRecordId.value = targetId;
    }, 0);
    scrollTimerId = null;
  }, 50);
}

// 监听"id 最大的那条记录的 id"——这是真正能感知"新记录到达"的信号。
// 注意:不能只 watch length —— 当列表已满 MAX_RECORDS=5 时,
// WS 是 [...records, record].slice(-5),polling 也是 [...newRecords, ...records].slice(0, 5),
// 两种情况下 length 都不变,只会替换现有元素,length watch 不触发。
watch(
  () => {
    const target = getMaxIdRecord();
    return target ? target.id : null;
  },
  () => scrollToLatest(),
);

// 监听 visible 变化:scroll-view 通过 v-if="visible" 渲染,visible 由 false→true
// 时 scroll-view 才挂载,需要在挂载完成后立即滚动一次
watch(
  () => visible.value,
  (val) => {
    if (val) {
      scrollToLatest();
    }
  },
);

// 组件挂载后,如果已有历史记录,也立即滚动到 id 最大的那条
onMounted(() => {
  if (records.value.length > 0) {
    scrollToLatest();
  }
});

</script>

<style scoped>
.contribution-list {
  width: 100%;
  padding: 0 24rpx;
  margin-top: 32rpx;
  position: relative;
}

/* 渐变模糊背景层：Figma 中的 4 色径向 + 50px 模糊 */
.list-bg {
  position: absolute;
  top: 0;
  left: 24rpx;
  right: 24rpx;
  height: 512rpx;
  border-radius: 48rpx;
  background: linear-gradient(
    131.84deg,
    rgba(154, 146, 255, 0.47) 9.69%,
    rgba(255, 202, 229, 0.47) 43.91%,
    rgba(255, 250, 253, 0.465) 76.13%,
    rgba(63, 63, 76, 0.47) 91.61%
  );
  filter: blur(50rpx);
  z-index: 0;
  pointer-events: none;
}

.list-content {
  height: 512rpx;
  border-radius: 24rpx;
  padding: 24rpx 16rpx;
  position: relative;
  z-index: 1;
}

/* 单条贡献 item：胶囊形状 + 红色阴影 + 宽度跟随昵称 */
.contribution-item {
  /* 宽度由 :style 注入的 --item-width 控制（跨端最稳）；CSS 仅兜底 min/max */
  width: max-content;
  min-width: 200rpx;
  max-width: 420rpx;
  height: 88rpx;
  display: flex;
  align-items: center;

  margin-bottom: 24rpx;
  animation: fadeIn 0.3s ease-out;
  position: relative;
}

.contribution-item:last-child {
  margin-bottom: 0;
}

.new-item {
  animation: slideIn 0.3s ease-out;
}

.fading-out {
  animation: fadeOut 0.5s forwards;
}

/* 左侧：用户信息容器（头像 + 文字） */
.user-info {
  display: flex;
  align-items: center;
  /* 不再 flex:1 撑满，宽度跟随内容 */
  flex: 0 0 auto;
  min-width: 0;
  border-radius: 999rpx;
  padding: 8rpx 16rpx;
  padding-right: 64rpx;
  box-shadow: 0 4rpx 8rpx rgba(102, 7, 7, 0.25);
  background-image: url("@/static/rank/activity-support-icon/beijingkuang.png");
  background-size: 100% 130%;
  background-position: center;
}

/* 头像：圆形 + 红色阴影 */
.user-avatar {
  width: 78rpx;
  height: 78rpx;
  border-radius: 50%;
  margin-right: 16rpx;
  box-shadow: 2rpx 2rpx 8rpx rgba(181, 7, 7, 0.54);
  flex-shrink: 0;
}

/* 文字容器（昵称 + 赠送动作） */
.user-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* 不再 flex:1，让昵称真实宽度决定容器宽度 */
  flex: 0 0 auto;
  white-space: nowrap;
}

/* 昵称：黄色 + 红色文字阴影 */
.user-nickname {
  font-size: 24rpx;
  font-weight: bold;
  color: #fff9a1;
  text-shadow: -2rpx 2rpx 8rpx rgba(206, 9, 9, 0.45);
  white-space: nowrap;
  line-height: 1.2;
  font-family: "Abhaya Libre ExtraBold", sans-serif;
}

/* 赠送动作文本 */
.gift-text {
  font-size: 20rpx;
  color: #ffffff;
  text-shadow: -2rpx 2rpx 8rpx rgba(206, 9, 9, 0.45);
  white-space: nowrap;
  line-height: 1.2;
  margin-top: 2rpx;
  font-family: "Abhaya Libre ExtraBold", sans-serif;
}

/* 道具图标外层：带 11° 旋转 + 红色阴影 + 绝对定位伸出版心 */
.item-icon-wrap {
  display: flex;
  /* position: absolute;
  right: -64rpx; */
  border-radius: 8rpx;
  margin-left: -40rpx;
}

/* 道具图标本体：填满外层模块 */
.item-icon {
  width: 96rpx;
  height: 96rpx;
  display: block;
  transform: rotate(10deg);
  transform-origin: center center;
}

/* 数量区域：X 白色 + 数字黄色 */
.quantity-info {
  display: flex;
  align-items: flex-end;
  text-shadow: -0.0625rem 0.0625rem 0.25rem rgba(206, 9, 9, 0.45);
  margin-left: 16rpx;
}

.item-x {
  font-size: 32rpx;
  color: #ffffff;
  font-style: italic;
  margin-right: 6rpx;
}

.item-count {
  font-size: 56rpx;
  color: #f7e600;
  font-weight: bold;
  line-height: 1;
  font-style: italic;
}

/* 数量档位样式：999+ 顶格、520~998 中档、其他常规 */
.count-largest {
  font-size: 76rpx;
}
.count-mid {
  font-size: 52rpx;
}
.count-small {
  font-size: 48rpx;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(-10rpx);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateX(-20rpx);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
</style>
