<template>
  <view class="container">
    <view class="dream-bg dream-bg-one"></view>
    <view class="dream-bg dream-bg-two"></view>

    <view class="mail-header">
      <view>
        <text class="mail-title">信箱</text>
        <text class="mail-subtitle">查看发送记录和对方回复</text>
      </view>
    </view>

    <view class="mail-tabs">
      <view
        class="mail-tab"
        :class="{ active: currentTab === index }"
        v-for="(tab, index) in MAIL_TABS"
        :key="tab.name"
        @tap="changeTab({ index })"
      >
        <text>{{ tab.name }}</text>
      </view>
    </view>

    <view class="pull-refresh-indicator" v-if="isPullingDown && isH5">
      <view class="refresh-icon" :class="{ refreshing }">↓</view>
      <text>{{ refreshing ? "刷新中..." : "下拉可以刷新" }}</text>
    </view>

    <scroll-view
      ref="scrollViewRef"
      scroll-y
      class="mail-list"
      @scrolltolower="loadMore"
      refresher-enabled
      :refresher-triggered="refreshing"
      @refresherrefresh="onRefresh"
      @scroll="onScroll"
      @touchstart="onTouchStart"
      @touchmove="onTouchMove"
      @touchend="onTouchEnd"
    >
      <view class="tui-skeleton">
        <view v-if="mailList.length > 0" class="mail-list-inner">
          <mail-card v-for="mail in mailList" :key="mail.id" :mail="mail" @detail="viewDetail" />

          <view v-if="isH5 && showLoadMoreButton && hasMore" class="load-more-button" @click="loadMore">
            {{ loadMoreButtonText }}
          </view>
        </view>

        <mail-list-state
          :loading="loading && !refreshing"
          :empty="!loading && mailList.length === 0"
          :no-more="!hasMore && mailList.length > 0"
          :empty-image="MAIL_EMPTY_IMAGE"
        />
      </view>
    </scroll-view>
  </view>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, computed } from "vue";
import { onTabItemTap } from "@dcloudio/uni-app";

import MailCard from "@/components/mail/MailCard.vue";
import MailListState from "@/components/mail/MailListState.vue";
import {
  MAIL_DETAIL_PAGE,
  MAIL_EMPTY_IMAGE,
  MOCK_PHONE_PREFIXES,
  MAIL_TABS,
  MOCK_MAIL_CONTENTS,
  MailStatus,
  serializeMail,
  type Mail,
} from "@/config/mail";
import { USE_ABS_PATH } from "@/constants/glable";
import { useSwitchTab } from "@/stores/switchTab";

const isLogin = ref<boolean>(false);
const currentTab = ref<number>(0);
const mailList = ref<Mail[]>([]);
const page = ref<number>(1);
const pageSize = ref<number>(5);
const loading = ref<boolean>(false);
const hasMore = ref<boolean>(true);
const refreshing = ref<boolean>(false);
const scrollViewRef = ref<any>(null);
const scrollHeight = ref<number>(0);
const contentHeight = ref<number>(0);
const showLoadMoreButton = ref<boolean>(false);
const isTabSwitching = ref<boolean>(false);

const switchTab = useSwitchTab();
const originalPagePath = switchTab.lastPage;

const isH5 = ref<boolean>(false);
const isPullingDown = ref<boolean>(false);
const startY = ref<number>(0);
const scrollTop = ref<number>(0);
const pullDistance = ref<number>(0);
const PULL_THRESHOLD = 60;
const LOAD_MORE_THRESHOLD = 50;

const loadMoreButtonText = computed(() => {
  if (loading.value) return "加载中...";
  if (!hasMore.value) return "已经到底了";
  return "点击加载更多";
});

const checkPlatform = () => {
  isH5.value = typeof window !== "undefined" && typeof document !== "undefined";

  if (isH5.value) {
    setTimeout(updateScrollHeights, 500);
  }
};

const updateScrollHeights = () => {
  if (!isH5.value) return;

  const scrollViewElement = document.querySelector(".mail-list");
  const contentElement = document.querySelector(".mail-list-inner");

  if (scrollViewElement && contentElement) {
    scrollHeight.value = scrollViewElement.clientHeight;
    contentHeight.value = contentElement.scrollHeight;
  }
};

const checkShowLoadMoreButton = () => {
  if (!isH5.value || !hasMore.value || loading.value) return;

  const scrollViewElement = document.querySelector(".mail-list");
  const contentElement = document.querySelector(".mail-list-inner");

  if (!scrollViewElement || !contentElement) return;

  scrollHeight.value = scrollViewElement.clientHeight;
  contentHeight.value = contentElement.scrollHeight;

  const distanceToBottom = contentHeight.value - scrollHeight.value - scrollTop.value;
  const isNearBottom = distanceToBottom < LOAD_MORE_THRESHOLD;

  showLoadMoreButton.value = !isNearBottom && hasMore.value && mailList.value.length > 0 && !isTabSwitching.value;

  if (isNearBottom && hasMore.value && !loading.value && !isTabSwitching.value) {
    loadMore();
  }
};

const onTouchStart = (e: any) => {
  if (!isH5.value || scrollTop.value > 5) return;

  startY.value = e.touches[0].clientY || e.changedTouches[0].clientY;
};

const onTouchMove = (e: any) => {
  if (!isH5.value || scrollTop.value > 5 || refreshing.value) return;

  const currentY = e.touches[0].clientY || e.changedTouches[0].clientY;
  const distance = currentY - startY.value;

  if (distance > 10) {
    e.preventDefault();
    e.stopPropagation();
    pullDistance.value = Math.min(distance * 0.5, PULL_THRESHOLD * 1.5);
    isPullingDown.value = true;
  } else {
    pullDistance.value = 0;
    isPullingDown.value = false;
  }
};

const onTouchEnd = () => {
  if (!isH5.value || !isPullingDown.value) return;

  if (pullDistance.value > PULL_THRESHOLD) {
    refreshing.value = true;
    loadData(true);
  }

  pullDistance.value = 0;
  isPullingDown.value = false;
};

const onScroll = (e: any) => {
  if (e.detail) {
    scrollTop.value = e.detail.scrollTop || 0;
  }

  if (isH5.value && !loading.value && !refreshing.value) {
    setTimeout(checkShowLoadMoreButton, 100);
  }
};

const generateMockData = (count: number): Mail[] => {
  const statusOptions = [MailStatus.PENDING, MailStatus.SENT, MailStatus.FAILED];

  return Array.from({ length: count }, () => {
    const status = statusOptions[Math.floor(Math.random() * statusOptions.length)];
    const phonePrefix = MOCK_PHONE_PREFIXES[Math.floor(Math.random() * MOCK_PHONE_PREFIXES.length)];
    const phoneTail = String(Math.floor(Math.random() * 100000000)).padStart(8, "0");
    const randomDay = String(Math.floor(Math.random() * 30) + 1).padStart(2, "0");
    const randomTime = `${String(Math.floor(Math.random() * 24)).padStart(2, "0")}:${String(Math.floor(Math.random() * 60)).padStart(2, "0")}:${String(Math.floor(Math.random() * 60)).padStart(2, "0")}`;

    return {
      id: Math.floor(Math.random() * 1000000),
      orderNumber: `2503${String(Math.random()).slice(2, 16)}`,
      recipient: `${phonePrefix}${phoneTail}`,
      content: MOCK_MAIL_CONTENTS[Math.floor(Math.random() * MOCK_MAIL_CONTENTS.length)],
      sendTime: `2025-03-${randomDay} ${randomTime}`,
      submitTime: `2025-03-${randomDay} ${randomTime}`,
      status,
      price: Number((Math.random() * 10).toFixed(2)),
      isNew: true,
    };
  });
};

const viewDetail = (mail: Mail) => {
  uni.navigateTo({
    url: `${MAIL_DETAIL_PAGE}?mail=${serializeMail(mail)}`,
  });
};

const getFilteredData = (mockData: Mail[]): Mail[] => {
  if (currentTab.value === 0) return mockData;
  if (currentTab.value === 1) return mockData.filter((item) => item.status === MailStatus.PENDING);
  if (currentTab.value === 2) return mockData.filter((item) => item.status === MailStatus.SENT);
  return mockData.filter((item) => item.status === MailStatus.FAILED);
};

const loadData = (reset = false) => {
  if (loading.value) return;

  if (reset) {
    page.value = 1;
    hasMore.value = true;
  }

  if (!hasMore.value) return;

  loading.value = true;
  showLoadMoreButton.value = false;

  setTimeout(() => {
    const filteredData = getFilteredData(generateMockData(pageSize.value));
    mailList.value = reset ? filteredData : [...mailList.value, ...filteredData];

    if (!reset && filteredData.length > 0) {
      setTimeout(() => {
        mailList.value.forEach((item) => {
          item.isNew = false;
        });
      }, 1500);
    }

    if (page.value >= 3) {
      hasMore.value = false;
    }

    page.value++;
    loading.value = false;
    refreshing.value = false;

    if (isH5.value) {
      setTimeout(() => {
        updateScrollHeights();
        checkShowLoadMoreButton();
      }, 300);
    }
  }, 1500);
};

const changeTab = (e: any) => {
  currentTab.value = e.index;
  isTabSwitching.value = true;
  loadData(true);

  setTimeout(() => {
    isTabSwitching.value = false;

    if (isH5.value) {
      updateScrollHeights();
      checkShowLoadMoreButton();
    }
  }, 1500);
};

const loadMore = () => {
  if (!loading.value && hasMore.value) {
    loadData();
  }
};

const onRefresh = () => {
  refreshing.value = true;
  isPullingDown.value = false;
  pullDistance.value = 0;
  loadData(true);
};

const checkScrollToBottom = () => {
  if (!isH5.value || loading.value || !hasMore.value) return;

  const scrollViewElement = document.querySelector(".mail-list");
  const contentElement = document.querySelector(".mail-list-inner");

  if (!scrollViewElement || !contentElement) return;

  const distanceToBottom = contentElement.scrollHeight - (scrollViewElement.scrollTop + scrollViewElement.clientHeight);

  if (distanceToBottom < LOAD_MORE_THRESHOLD && !isTabSwitching.value) {
    loadMore();
  }
};

let scrollTimer: any = null;

const onNativeScroll = () => {
  const scrollElement = document.querySelector(".mail-list");
  if (!scrollElement) return;

  scrollTop.value = scrollElement.scrollTop || 0;
  clearTimeout(scrollTimer);
  scrollTimer = setTimeout(() => {
    checkScrollToBottom();
    checkShowLoadMoreButton();
  }, 100);
};

const startScrollDetection = () => {
  if (!isH5.value) return;

  const scrollElement = document.querySelector(".mail-list");
  scrollElement?.addEventListener("scroll", onNativeScroll);
};

onTabItemTap((item) => {
  currentTab.value = 0;
  isLogin.value = true;

  if (!isLogin.value) {
    uni.showModal({
      title: "提示",
      content: "请先登录",
      success: (res) => {
        if (res.confirm) {
          uni.switchTab({
            url: "/pages/login/login",
          });
        } else if (res.cancel) {
          uni.switchTab({
            url: USE_ABS_PATH + originalPagePath,
          });
        }
      },
    });
  }

  console.log("完成Tab切换事件", item);
});

onMounted(() => {
  checkPlatform();

  if (typeof document !== "undefined") {
    document.addEventListener("touchstart", onTouchStart, { passive: false });
    document.addEventListener("touchmove", onTouchMove, { passive: false });
    document.addEventListener("touchend", onTouchEnd, { passive: false });
    setTimeout(startScrollDetection, 1000);
  }

  loadData();
});

onUnmounted(() => {
  if (typeof document !== "undefined") {
    document.removeEventListener("touchstart", onTouchStart);
    document.removeEventListener("touchmove", onTouchMove);
    document.removeEventListener("touchend", onTouchEnd);
  }

  const scrollElement = document.querySelector(".mail-list");
  scrollElement?.removeEventListener("scroll", onNativeScroll);
  clearTimeout(scrollTimer);
});
</script>

<style scoped lang="scss">
.container {
  display: flex;
  flex-direction: column;
  background:
    linear-gradient(180deg, rgba(255, 244, 250, 0.98) 0%, rgba(239, 248, 255, 0.96) 48%, #f7f8fb 100%),
    linear-gradient(135deg, rgba(255, 204, 225, 0.22), rgba(199, 233, 255, 0.24));
  position: relative;
  height: 100vh;
  overflow: hidden;
}

.dream-bg {
  position: fixed;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
}

.dream-bg-one {
  width: 360rpx;
  height: 360rpx;
  right: -150rpx;
  top: 120rpx;
  background: rgba(255, 193, 215, 0.22);
}

.dream-bg-two {
  width: 320rpx;
  height: 320rpx;
  left: -130rpx;
  top: 620rpx;
  background: rgba(171, 218, 255, 0.2);
}

.mail-header {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  padding: 30rpx 28rpx 18rpx;
}

.mail-title,
.mail-subtitle {
  display: block;
}

.mail-title {
  color: #20273a;
  font-size: 44rpx;
  font-weight: 700;
  line-height: 1.2;
}

.mail-subtitle {
  margin-top: 10rpx;
  color: #687286;
  font-size: 25rpx;
  line-height: 1.45;
}

.mail-tabs {
  position: relative;
  z-index: 1;
  display: flex;
  margin: 0 24rpx 18rpx;
  padding: 8rpx;
  border-radius: 999rpx;
  background: rgba(255, 255, 255, 0.62);
  border: 1rpx solid rgba(255, 255, 255, 0.86);
  box-shadow: 0 10rpx 26rpx rgba(83, 96, 130, 0.05);
}

.mail-tab {
  flex: 1;
  height: 62rpx;
  line-height: 62rpx;
  text-align: center;
  border-radius: 999rpx;
  color: #7b8493;
  font-size: 24rpx;
  font-weight: 600;
}

.mail-tab.active {
  color: #fff;
  background: linear-gradient(135deg, #ff78a2 0%, #83c6ff 100%);
  box-shadow: 0 10rpx 20rpx rgba(255, 120, 162, 0.18);
}

.mail-list {
  position: relative;
  z-index: 1;
  flex: 1;
  height: 0;
  padding: 0;
}

.mail-list-inner {
  padding: 0 24rpx 28rpx;
}

.tui-skeleton {
  width: 100%;
}

.tui-skeleton-rect,
.tui-skeleton-circular,
.tui-skeleton-fillet {
  position: relative;
}

.pull-refresh-indicator {
  position: fixed;
  top: 44px;
  left: 0;
  right: 0;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(255, 255, 255, 0.82);
  z-index: 99;
  font-size: 14px;
  color: #666;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.refresh-icon {
  margin-right: 8px;
  font-size: 16px;
  transition: transform 0.3s;

  &.refreshing {
    animation: rotating 1s linear infinite;
  }
}

@keyframes rotating {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.load-more-button {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 44px;
  margin: 18rpx 0 28rpx;
  background-color: rgba(255, 255, 255, 0.72);
  color: #7b8493;
  font-size: 14px;
  border-radius: 999rpx;
  cursor: pointer;

  &:active {
    background-color: #eaeaea;
  }
}
</style>
