<template>
  <view class="asset-page asset-theme points-list-page">
    <asset-page-shell title="积分转换" />

    <view class="asset-scroll points-list-scroll">
      <view class="summary-card">
        <text class="summary-card__text">
          已选择订单：
          <text class="summary-card__accent asset-number-font">{{
            selectedCount
          }}</text>
          个；共
          <text class="summary-card__accent asset-number-font">{{
            displaySelectedTotal
          }}</text>
          积分
        </text>
        <text
          v-if="showTransferPointEstimate"
          class="summary-card__extra"
        >
          可用未释放积分预估值：
          <text class="summary-card__accent asset-number-font">{{
            displayTransferPointEstimate
          }}</text>
        </text>
      </view>

      <view class="selection-card">
        <text class="selection-card__title">按订单积分区间筛选</text>

        <view class="range-tabs">
          <view
            v-for="tab in rangeTabs"
            :key="tab.key"
            class="range-tabs__item"
            :class="{ 'range-tabs__item--active': activeRange === tab.key }"
            @click="switchRange(tab.key)"
          >
            {{ tab.label }}
          </view>
        </view>

        <view v-if="filteredItems.length" class="selection-list">
          <view
            v-for="item in filteredItems"
            :key="item.id"
            class="selection-item"
            :class="{ 'selection-item--disabled': item.disabled }"
            @click="toggleItem(item)"
          >
            <view
              class="selection-item__checkbox"
              :class="{
                'selection-item__checkbox--checked': isChecked(item),
                'selection-item__checkbox--disabled': item.disabled,
              }"
            >
              <text
                v-if="isChecked(item)"
                class="selection-item__checkbox-mark"
                >✓</text
              >
            </view>

            <view class="selection-item__main">
              <view class="selection-item__title-row">
                <text class="selection-item__title">{{ item.title }}</text>
                <view
                  v-if="item.statusText"
                  class="selection-item__status"
                  :class="{
                    'selection-item__status--warning': item.disabled,
                  }"
                >
                  {{ item.statusText }}
                </view>
              </view>

              <text class="selection-item__time asset-number-font">{{
                item.time
              }}</text>
            </view>

            <view class="selection-item__side" style="display: flex; align-items: center;">
              <text class="selection-item__label" style="margin-top: 6rpx">积分</text>
              <text class="selection-item__amount asset-number-font">{{
                item.amount
              }}</text>
            </view>
          </view>
        </view>

        <view v-else class="selection-empty">
          <text class="selection-empty__title">暂无可转换订单</text>
          <text class="selection-empty__desc">
            当前筛选条件下没有符合条件的积分订单。
          </text>
        </view>

        <view v-if="showLoadMoreState" class="list-load-more">
          <text class="list-load-more__text asset-number-font">{{ loadMoreText }}</text>
        </view>
      </view>
    </view>

    <view class="bottom-bar">
      <view class="bottom-bar__check-all" @click="toggleAll">
        <view
          class="bottom-bar__checkbox"
          :class="{ 'bottom-bar__checkbox--checked': allChecked }"
        >
          <text v-if="allChecked" class="bottom-bar__checkbox-mark">✓</text>
        </view>
        <text class="bottom-bar__check-all-text">全选</text>
      </view>

      <view
        class="bottom-bar__button"
        :class="{ 'bottom-bar__button--disabled': !canSubmit }"
        @click="openConfirm"
      >
        {{ submitting ? "提交中..." : "确认转换" }}
      </view>
    </view>

    <asset-confirm-popup
      class="points-confirm-popup"
      :visible="confirmVisible"
      title="兑换可用积分"
      :confirm-text="submitting ? '提交中...' : '确认'"
      cancel-text="取消"
      :show-close="false"
      :close-on-mask="false"
      @cancel="handleConfirmCancel"
      @confirm="submit"
    >
      <view class="points-confirm">
        <text class="points-confirm__line">
          确认使用
          <text class="points-confirm__number asset-number-font">{{
            displaySelectedTotal
          }}</text>
          积分 兑换
          <text class="points-confirm__number asset-number-font">{{
            displayTransferPointEstimate
          }}</text>
          可用积分吗？
        </text>
        <text class="points-confirm__note">
          注：积分成功兑换可用积分，不能再换回积分
        </text>
      </view>
    </asset-confirm-popup>
  </view>
</template>

<script>
import AssetConfirmPopup from "../../components/asset-confirm-popup.vue";
import AssetPageShell from "../../components/asset-page-shell.vue";
import {
  fetchPointsConvertSelection,
  submitAssetPointsConvert,
} from "../../api/assets";

export default {
  components: {
    AssetConfirmPopup,
    AssetPageShell,
  },
  data() {
    return {
      hasShown: false,
      activeRange: "below-20",
      submitting: false,
      confirmVisible: false,
      selectedIds: [],
      detail: {
        items: [],
      },
      page: 1,
      pageSize: 10,
      hasMore: false,
      loadingMore: false,
    };
  },
  computed: {
    rangeTabs() {
      return [
        {
          key: "below-20",
          label: "20以下",
          interval: "0,20",
        },
        {
          key: "20-100",
          label: "20-100",
          interval: "20,100",
        },
        {
          key: "100-200",
          label: "100-200",
          interval: "100,200",
        },
        {
          key: "200-500",
          label: "200-500",
          interval: "200,500",
        },
        {
          key: "500-plus",
          label: "500以上",
          interval: "500,10000000",
        },
      ];
    },
    currentInterval() {
      const currentTab = this.rangeTabs.find(
        (item) => item.key === this.activeRange,
      );

      return (currentTab && currentTab.interval) || "0,20";
    },
    items() {
      return Array.isArray(this.detail.items) ? this.detail.items : [];
    },
    filteredItems() {
      return this.items;
    },
    selectedItems() {
      return this.items.filter(
        (item) => !item.disabled && this.selectedIds.indexOf(item.id) > -1,
      );
    },
    selectedCount() {
      return this.selectedItems.length;
    },
    selectedTotal() {
      return this.selectedItems.reduce(
        (total, item) => total + Number(item.amountValue || 0),
        0,
      );
    },
    displaySelectedTotal() {
      return this.formatAmount(this.selectedTotal);
    },
    transferPointEstimate() {
      return this.selectedItems.reduce(
        (total, item) => total + Number(item.transferPointValue || 0),
        0,
      );
    },
    displayTransferPointEstimate() {
      return this.formatAmount(this.transferPointEstimate);
    },
    showTransferPointEstimate() {
      return this.transferPointEstimate > 0;
    },
    selectableFilteredItems() {
      return this.filteredItems.filter((item) => !item.disabled);
    },
    allChecked() {
      if (!this.selectableFilteredItems.length) {
        return false;
      }

      return this.selectableFilteredItems.every(
        (item) => this.selectedIds.indexOf(item.id) > -1,
      );
    },
    canSubmit() {
      return this.selectedItems.length > 0 && !this.submitting;
    },
    showLoadMoreState() {
      return this.items.length > 0;
    },
    loadMoreText() {
      if (this.loadingMore) {
        return "加载中...";
      }

      if (this.hasMore) {
        return "上拉加载更多";
      }

      return "没有更多了";
    },
  },
  onLoad() {
    this.resetPagingState();
    this.loadPage(true, 1);
  },
  onShow() {
    if (this.hasShown) {
      this.resetPagingState();
      this.loadPage(false, 1);
      return;
    }

    this.hasShown = true;
  },
  onReachBottom() {
    this.loadMore();
  },
  methods: {
    resetPagingState() {
      this.page = 1;
      this.hasMore = false;
      this.loadingMore = false;
    },
    updatePaging(result, requestedPage, receivedLength) {
      const pagination =
        result && result.pagination && typeof result.pagination === "object"
          ? result.pagination
          : null;
      this.page =
        Number(pagination && pagination.page) || Number(requestedPage) || this.page || 1;

      if (pagination && typeof pagination.hasMore === "boolean") {
        this.hasMore = pagination.hasMore;
        return;
      }

      this.hasMore = receivedLength >= this.pageSize;
    },
    mergeItems(currentItems, nextItems) {
      const mergedMap = {};
      const mergedList = [];
      const appendItem = (item) => {
        const key =
          String(item && item.id ? item.id : "").trim() ||
          [
            item && item.orderSn,
            item && item.time,
            item && item.title,
            item && item.amount,
          ]
            .map((value) => String(value || ""))
            .join("-");

        if (!key || mergedMap[key]) {
          return;
        }

        mergedMap[key] = true;
        mergedList.push(item);
      };

      (Array.isArray(currentItems) ? currentItems : []).forEach(appendItem);
      (Array.isArray(nextItems) ? nextItems : []).forEach(appendItem);
      return mergedList;
    },
    formatAmount(value) {
      const number = Number(value || 0);
      if (!Number.isFinite(number)) {
        return "0";
      }

      return Math.round(number)
        .toString()
        .replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    },
    switchRange(nextRangeKey) {
      const targetRangeKey = String(nextRangeKey || "");
      if (!targetRangeKey || targetRangeKey === this.activeRange) {
        return;
      }

      this.activeRange = targetRangeKey;
      this.selectedIds = [];
      this.resetPagingState();
      this.loadPage(true, 1);
    },
    isChecked(item) {
      return this.selectedIds.indexOf(item.id) > -1;
    },
    toggleItem(item) {
      if (!item) {
        return;
      }

      const transferPointNum = Number(
        item.transfer_point_num !== undefined
          ? item.transfer_point_num
          : item.transferPointValue || 0,
      );
      if (transferPointNum === 0) {
        uni.showToast({
          title: "当前订单无可用积分",
          icon: "none",
        });
        return;
      }

      if (item.disabled) {
        return;
      }

      if (this.isChecked(item)) {
        this.selectedIds = this.selectedIds.filter((id) => id !== item.id);
        return;
      }

      this.selectedIds = this.selectedIds.concat(item.id);
    },
    toggleAll() {
      const currentIds = this.selectableFilteredItems.map((item) => item.id);

      if (!currentIds.length) {
        return;
      }

      if (this.allChecked) {
        this.selectedIds = this.selectedIds.filter(
          (id) => currentIds.indexOf(id) === -1,
        );
        return;
      }

      this.selectedIds = Array.from(new Set(this.selectedIds.concat(currentIds)));
    },
    async loadPage(showLoading, targetPage) {
      const page = Number(targetPage || 1);
      const isLoadMore = page > 1;

      if (isLoadMore && this.loadingMore) {
        return;
      }

      if (isLoadMore) {
        this.loadingMore = true;
      }

      try {
        const requestOptions =
          !isLoadMore && showLoading
            ? {
                showLoading: true,
                loadingText: "加载中",
              }
            : null;
        const result = await fetchPointsConvertSelection(
          {
            page: page,
            pageSize: this.pageSize,
            interval: this.currentInterval,
          },
          requestOptions,
        );

        const incomingItems = Array.isArray(result.items) ? result.items : [];
        const previousCount = this.items.length;
        const mergedItems = isLoadMore
          ? this.mergeItems(this.items, incomingItems)
          : incomingItems;
        this.detail = Object.assign({}, this.detail, result, {
          items: mergedItems,
        });

        const validIds = this.items
          .filter((item) => !item.disabled)
          .map((item) => item.id);
        this.selectedIds = this.selectedIds.filter(
          (id) => validIds.indexOf(id) > -1,
        );

        this.updatePaging(result, page, incomingItems.length);

        if (isLoadMore && mergedItems.length <= previousCount) {
          this.hasMore = false;
        }
      } catch (error) {
        uni.showToast({
          title: error.message || (isLoadMore ? "加载更多失败" : "页面加载失败"),
          icon: "none",
        });
      } finally {
        if (isLoadMore) {
          this.loadingMore = false;
        }
      }
    },
    loadMore() {
      if (this.loadingMore || !this.hasMore) {
        return;
      }

      this.loadPage(false, this.page + 1);
    },
    openConfirm() {
      if (!this.canSubmit) {
        uni.showToast({
          title: "请选择可转换订单",
          icon: "none",
        });
        return;
      }

      this.confirmVisible = true;
    },
    handleConfirmCancel() {
      if (this.submitting) {
        return;
      }

      this.confirmVisible = false;
    },
    async submit() {
      if (this.submitting) {
        return;
      }

      if (!this.canSubmit) {
        uni.showToast({
          title: "请选择可转换订单",
          icon: "none",
        });
        return;
      }

      this.submitting = true;

      try {
        await submitAssetPointsConvert(
          {
            ids: this.selectedItems.map((item) => item.sourceId || item.id),
          },
          {
            showLoading: true,
            loadingText: "转换中",
          },
        );

        this.confirmVisible = false;
        uni.showToast({
          title: "转换成功",
          icon: "none",
        });
        this.selectedIds = [];
        this.resetPagingState();
        this.loadPage(false, 1);
      } catch (error) {
        uni.showToast({
          title: error.message || "转换失败",
          icon: "none",
        });
      } finally {
        this.submitting = false;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
@import "../../styles/tokens.scss";
@import "../../styles/common.scss";

.points-list-page {
  min-height: 100vh;
  background: #191e32;
}

.points-list-scroll {
  min-height: calc(100vh - env(safe-area-inset-top) - 104rpx);
  padding: 12rpx 14rpx calc(env(safe-area-inset-bottom) + 150rpx);
}

.summary-card,
.selection-card,
.bottom-bar {
  background: #242944;
}

.summary-card,
.selection-card,
.selection-empty {
  border-radius: 10rpx;
  box-shadow: 0 12rpx 24rpx rgba(8, 13, 30, 0.14);
}

.summary-card {
  position: relative;
  overflow: hidden;
  padding: 28rpx 26rpx;
}

.summary-card::after {
  content: "";
  position: absolute;
  top: -18rpx;
  left: -260rpx;
  width: 600rpx;
  height: 180rpx;
  background: rgba(123, 137, 190, 0.18);
  transform: rotate(130deg);
}

.summary-card__text {
  position: relative;
  z-index: 1;
  font-size: 28rpx;
  font-weight: 500;
  color: #ffffff;
}

.summary-card__accent {
  color: #ff8d62;
}

.summary-card__extra {
  position: relative;
  z-index: 1;
  display: block;
  margin-top: 12rpx;
  font-size: 26rpx;
  font-weight: 500;
  color: rgba(236, 242, 255, 0.92);
}

.selection-card {
  margin-top: 18rpx;
  padding: 28rpx 0 0;
  overflow: hidden;
}

.selection-card__title {
  display: block;
  padding: 0 20rpx;
  font-size: 28rpx;
  font-weight: 500;
  color: #ffffff;
}

.range-tabs {
  display: flex;
  align-items: center;
  margin-top: 26rpx;
  padding: 0 18rpx;
  border-bottom: 1px solid rgba(129, 141, 183, 0.18);
}

.range-tabs__item {
  position: relative;
  flex: 1;
  padding: 0 4rpx 18rpx;
  text-align: center;
  font-size: 24rpx;
  color: rgba(173, 182, 211, 0.92);
}

.range-tabs__item--active {
  color: #ff8d62;
  font-weight: 600;
}

.range-tabs__item--active::after {
  content: "";
  position: absolute;
  right: 18rpx;
  bottom: 0;
  left: 18rpx;
  height: 4rpx;
  border-radius: 999rpx;
  background: #ff8d62;
}

.selection-list {
  padding: 0 20rpx;
}

.selection-item {
  display: flex;
  align-items: flex-start;
  padding: 28rpx 0;
  border-top: 1px solid rgba(129, 141, 183, 0.18);
}

.selection-item:first-child {
  border-top: 0;
}

.selection-item--disabled {
  opacity: 0.6;
}

.selection-item__checkbox,
.bottom-bar__checkbox {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32rpx;
  height: 32rpx;
  border-radius: 6rpx;
  border: 2rpx solid rgba(255, 255, 255, 0.9);
  background: #ffffff;
  flex-shrink: 0;
}

.selection-item__checkbox {
  margin-top: 6rpx;
}

.selection-item__checkbox--checked,
.bottom-bar__checkbox--checked {
  border-color: #29d39c;
  background: #29d39c;
}

.selection-item__checkbox--disabled {
  border-color: rgba(205, 212, 235, 0.5);
  background: rgba(255, 255, 255, 0.92);
}

.selection-item__checkbox-mark,
.bottom-bar__checkbox-mark {
  font-size: 22rpx;
  line-height: 1;
  color: #ffffff;
}

.selection-item__main {
  flex: 1;
  min-width: 0;
  margin-left: 16rpx;
}

.selection-item__title-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

.selection-item__title {
  font-size: 28rpx;
  font-weight: 500;
  color: #ffffff;
}

.selection-item__status {
  margin-left: 14rpx;
  padding: 4rpx 14rpx;
  border-radius: 999rpx;
  background: rgba(255, 141, 98, 0.14);
  font-size: 22rpx;
  color: #ff8d62;
}

.selection-item__status--warning {
  background: rgba(255, 141, 98, 0.18);
}

.selection-item__time {
  display: block;
  margin-top: 14rpx;
  font-size: 22rpx;
  color: rgba(158, 170, 204, 0.9);
}

.selection-item__side {
  margin-left: 18rpx;
  padding-top: 2rpx;
  text-align: right;
}

.selection-item__label {
  display: block;
  font-size: 26rpx;
  color: rgba(240, 243, 255, 0.92);
}

.selection-item__amount {
  display: block;
  margin-top: 10rpx;
  font-size: 28rpx;
  font-weight: 700;
  color: #ff8d62;
}

.selection-empty {
  margin: 22rpx 20rpx 30rpx;
  padding: 70rpx 24rpx;
  text-align: center;
  background: rgba(38, 45, 73, 0.72);
}

.selection-empty__title {
  display: block;
  font-size: 28rpx;
  color: #ffffff;
}

.selection-empty__desc {
  display: block;
  margin-top: 14rpx;
  font-size: 22rpx;
  color: rgba(158, 170, 204, 0.86);
}

.list-load-more {
  display: flex;
  justify-content: center;
  padding: 12rpx 0 22rpx;
}

.list-load-more__text {
  font-size: 22rpx;
  color: rgba(173, 182, 211, 0.9);
}

.bottom-bar {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18rpx 20rpx calc(env(safe-area-inset-bottom) + 18rpx);
  border-top: 1px solid rgba(129, 141, 183, 0.16);
}

.bottom-bar__check-all {
  display: flex;
  align-items: center;
}

.bottom-bar__check-all-text {
  margin-left: 14rpx;
  font-size: 28rpx;
  color: #ffffff;
}

.bottom-bar__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 170rpx;
  height: 78rpx;
  padding: 0 34rpx;
  border-radius: 999rpx;
  background: linear-gradient(135deg, #1ec5ff 0%, #179fe8 100%);
  box-shadow: 0 14rpx 24rpx rgba(27, 179, 242, 0.22);
  font-size: 32rpx;
  font-weight: 600;
  color: #ffffff;
}

.bottom-bar__button--disabled {
  opacity: 0.5;
}

.points-confirm {
  padding: 6rpx 2rpx 4rpx;
}

.points-confirm__line {
  display: block;
  font-size: 30rpx;
  line-height: 1.9;
  text-align: center;
  color: #edf2ff;
}

.points-confirm__number {
  margin: 0 6rpx;
  color: #ff8d62;
  font-weight: 700;
}

.points-confirm__note {
  display: block;
  margin-top: 18rpx;
  font-size: 24rpx;
  line-height: 1.7;
  color: rgba(186, 194, 218, 0.9);
}
</style>
