<template>
  <view class="message-page">
    <view class="nav-bar" :style="{ paddingTop: statusBarHeight + 'px' }">
      <view class="nav-content">
        <view>
          <text class="nav-title">系统消息</text>
          <text class="nav-subtitle">审核通知、评论互动和系统提醒都会在这里出现</text>
        </view>
        <view class="nav-right">
          <view v-if="unreadCount > 0" class="unread-chip">
            <text class="unread-chip-text">{{ unreadCount }} 未读</text>
          </view>
        </view>
      </view>
    </view>

    <view :style="{ height: statusBarHeight + 64 + 'px' }"></view>

    <view class="page-body">
      <view v-if="!isLoggedIn" class="state-card login-card">
        <text class="state-title">登录后查看你的系统消息</text>
        <text class="state-desc">审核结果、评论互动、点赞提醒都会同步到这里。</text>
        <button class="primary-btn" @tap="openLoginPopup('请先登录后查看消息')">立即登录</button>
      </view>

      <template v-else>
        <view class="filter-bar">
          <view class="filter-tabs">
            <view
              v-for="tab in filterTabs"
              :key="tab.value"
              class="filter-tab"
              :class="{ active: activeFilter === tab.value }"
              @tap="activeFilter = tab.value"
            >
              <text class="filter-tab-text">{{ tab.label }}</text>
            </view>
          </view>
          <view
            class="read-all-btn filter-read-all-btn"
            :class="{ disabled: readingAll || unreadCount === 0 }"
            @tap="handleMarkAllRead"
          >
            <text class="read-all-text">{{ readingAll ? "处理中" : "全部已读" }}</text>
          </view>
        </view>

        <view v-if="loading && !notificationList.length" class="state-card">
          <text class="state-title">消息加载中...</text>
          <text class="state-desc">正在同步你的最新通知</text>
        </view>

        <view v-else-if="loadError && !notificationList.length" class="state-card">
          <text class="state-title">消息加载失败</text>
          <text class="state-desc">{{ loadError }}</text>
          <button class="primary-btn" @tap="refreshList">重新加载</button>
        </view>

        <view v-else-if="groupedNotifications.length" class="section-list">
          <view v-for="section in groupedNotifications" :key="section.day" class="section-block">
            <view class="section-header">
              <text class="section-title">{{ formatDayLabel(section.day) }}</text>
            </view>
            <view
              v-for="item in section.items"
              :key="item.id"
              class="message-card"
              :class="{ unread: !item.isRead }"
              @tap="handleItemTap(item)"
            >
              <view class="message-avatar-wrap">
                <image class="message-avatar" :src="resolveAvatar(item)" mode="aspectFill" />
                <view v-if="!item.isRead" class="message-dot"></view>
              </view>

              <view class="message-main">
                <view class="message-head">
                  <view class="message-head-left">
                    <text class="message-title">{{ item.title || typeLabelMap[item.type] || "系统通知" }}</text>
                    <view
                      class="type-tag"
                      :style="{
                        color: resolveTypeStyle(item.type).color,
                        background: resolveTypeStyle(item.type).background
                      }"
                    >
                      <text class="type-tag-text">{{ typeLabelMap[item.type] || "提醒" }}</text>
                    </view>
                  </view>
                  <text class="message-time">{{ formatRelativeTime(item.createdAt) }}</text>
                </view>

                <text class="message-content">{{ item.content || "你有一条新的系统消息" }}</text>

                <view class="message-footer">
                  <text class="message-meta">{{ resolveActionText(item) }}</text>
                  <text class="message-link">{{ resolveJumpText(item) }}</text>
                </view>
              </view>
            </view>
          </view>

          <view class="list-status">
            <text>{{ loading ? "加载中..." : hasMore ? "上拉加载更多" : "没有更多消息了" }}</text>
          </view>
        </view>

        <view v-else class="state-card">
          <text class="state-title">{{ activeFilter === "unread" ? "暂时没有未读消息" : "还没有系统消息" }}</text>
          <text class="state-desc">{{ activeFilter === "unread" ? "已帮你处理完所有提醒" : "新的审核、评论和互动提醒会显示在这里" }}</text>
        </view>
      </template>
    </view>

    <LoginPopup ref="loginPopupRef" @logind="handleLoginSuccess" />
  </view>
</template>

<script setup>
import { computed, ref } from "vue";
import { onLoad, onPullDownRefresh, onReachBottom, onShow } from "@dcloudio/uni-app";
import { useUserStore } from "@/stores/user";
import { getStatusBarHeight } from "@/utils/system";
import { FILE_BASE_URL } from "@/utils/constants";
import { syncMessageTabBarBadge } from "@/utils/tabBar";
import {
  fetchNotificationList,
  fetchUnreadCount,
  markAsRead,
  markAllAsRead,
} from "@/api/notification";
import LoginPopup from "@/components/LoginPopup/LoginPopup.vue";

const DEFAULT_AVATAR = "/static/images/icon/robot.png";
const APPROVED_AVATAR = "/static/images/icon/approved.png";
const REJECTED_AVATAR = "/static/images/icon/rejected.png";
const PENDING_AVATAR = "/static/images/icon/pending.png";

const userStore = useUserStore();
const loginPopupRef = ref(null);
const statusBarHeight = ref(getStatusBarHeight() || 20);
const loading = ref(false);
const readingAll = ref(false);
const page = ref(1);
const hasMore = ref(true);
const totalCount = ref(0);
const unreadCount = ref(0);
const loadError = ref("");
const activeFilter = ref("all");
const notificationList = ref([]);
const readingIds = ref([]);

const filterTabs = [
  { label: "全部", value: "all" },
  { label: "未读", value: "unread" },
];

const typeLabelMap = {
  topic_submit: "话题提交",
  topic_approved: "审核通过",
  topic_rejected: "审核未过",
  item_submit: "评分项提交",
  item_approved: "评分项通过",
  item_rejected: "评分项未过",
  comment: "评论互动",
  comment_like: "评论获赞",
  system: "系统通知",
};

const typeStyleMap = {
  topic_submit: { color: "#ff7d00", background: "rgba(255, 125, 0, 0.12)" },
  topic_approved: { color: "#12b76a", background: "rgba(18, 183, 106, 0.12)" },
  topic_rejected: { color: "#f04438", background: "rgba(240, 68, 56, 0.12)" },
  item_submit: { color: "#7a5af8", background: "rgba(122, 90, 248, 0.12)" },
  item_approved: { color: "#0ba5ec", background: "rgba(11, 165, 236, 0.12)" },
  item_rejected: { color: "#ef6820", background: "rgba(239, 104, 32, 0.12)" },
  comment: { color: "#ec4899", background: "rgba(236, 72, 153, 0.12)" },
  comment_like: { color: "#f63d68", background: "rgba(246, 61, 104, 0.12)" },
  system: { color: "#667085", background: "rgba(102, 112, 133, 0.12)" },
};

const isLoggedIn = computed(() => !!userStore.token || !!userStore.userInfo?.nickName);
let firstShow = true;

const todayCount = computed(() => {
  const today = formatDateKey(new Date());
  return notificationList.value.filter((item) => (item.day || formatDateKey(item.createdAt)) === today).length;
});

const filteredNotifications = computed(() => {
  if (activeFilter.value === "unread") {
    return notificationList.value.filter((item) => !item.isRead);
  }
  return notificationList.value;
});

const groupedNotifications = computed(() => {
  const map = {};
  filteredNotifications.value.forEach((item) => {
    const day = item.day || formatDateKey(item.createdAt);
    if (!map[day]) {
      map[day] = [];
    }
    map[day].push(item);
  });

  return Object.keys(map)
    .sort((a, b) => new Date(b).getTime() - new Date(a).getTime())
    .map((day) => ({
      day,
      items: map[day].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()),
    }));
});

const openLoginPopup = (message = "请先登录后再操作") => {
  loginPopupRef.value?.open();
  if (message) {
    uni.showToast({ title: message, icon: "none" });
  }
};

const formatDateKey = (value) => {
  const date = value instanceof Date ? value : new Date(value);
  if (Number.isNaN(date.getTime())) return "";
  const year = date.getFullYear();
  const month = `${date.getMonth() + 1}`.padStart(2, "0");
  const day = `${date.getDate()}`.padStart(2, "0");
  return `${year}-${month}-${day}`;
};

const formatRelativeTime = (value) => {
  if (!value) return "刚刚";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return "刚刚";

  const diff = Date.now() - date.getTime();
  const minute = 60 * 1000;
  const hour = 60 * minute;

  if (diff < minute) return "刚刚";
  if (diff < hour) return `${Math.max(1, Math.floor(diff / minute))}分钟前`;
  if (diff < 24 * hour) return `${Math.max(1, Math.floor(diff / hour))}小时前`;

  const month = date.getMonth() + 1;
  const day = date.getDate();
  const hours = `${date.getHours()}`.padStart(2, "0");
  const minutes = `${date.getMinutes()}`.padStart(2, "0");
  const currentYear = new Date().getFullYear();
  if (date.getFullYear() === currentYear) {
    return `${month}月${day}日 ${hours}:${minutes}`;
  }
  return `${date.getFullYear()}-${`${month}`.padStart(2, "0")}-${`${day}`.padStart(2, "0")}`;
};

const formatDayLabel = (day) => {
  if (!day) return "更早";
  const today = formatDateKey(new Date());
  const yesterdayDate = new Date();
  yesterdayDate.setDate(yesterdayDate.getDate() - 1);
  const yesterday = formatDateKey(yesterdayDate);

  if (day === today) return "今天";
  if (day === yesterday) return "昨天";

  const date = new Date(day);
  if (Number.isNaN(date.getTime())) return day;
  return `${date.getMonth() + 1}月${date.getDate()}日`;
};

const resolveAvatar = (item) => {
  const avatar = item?.fromUser?.avatar;
  if (!avatar) {
    if(item.title.includes("已通过")) {
      return APPROVED_AVATAR;
    } else if(item.title.includes("未通过")) {
      return REJECTED_AVATAR;
    } else if(item.title.includes("已提交审核")) {
      return PENDING_AVATAR;
    } else {
      return DEFAULT_AVATAR;
    }
  }
  return String(avatar).startsWith("http") ? avatar : `${FILE_BASE_URL}${avatar}`;
};

const resolveTypeStyle = (type) => {
  return typeStyleMap[type] || typeStyleMap.system;
};

const resolveActionText = (item) => {
  if (!item.isRead) return "点击后将标记为已读";
  if (item.updatedAt && item.updatedAt !== item.createdAt) return "已处理";
  return "查看详情";
};

const resolveJumpText = (item) => {
  if(item.title.includes("已提交审核") || item.title.includes("未通过") || item.title.includes("评分项")) return "";

  if (item.topicId) return "查看话题";
  return "查看消息";
};

const normalizeListResponse = (res) => {
  const source = res?.data || res || {};
  const list = Array.isArray(source.list)
    ? source.list
    : Array.isArray(res?.list)
      ? res.list
      : [];
  const total = Number(source.totalCount ?? res?.totalCount ?? list.length);
  return { list, total };
};

const mergeNotificationList = (list, reset = false) => {
  if (reset) {
    notificationList.value = list;
    return;
  }

  const map = new Map(notificationList.value.map((item) => [item.id, item]));
  list.forEach((item) => {
    map.set(item.id, item);
  });
  notificationList.value = Array.from(map.values()).sort(
    (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
  );
};

const loadUnread = async () => {
  if (!isLoggedIn.value) {
    unreadCount.value = 0;
    syncMessageTabBarBadge(0);
    return;
  }

  try {
    const res = await fetchUnreadCount();
    const count =
      Number(
        res?.data?.count ??
        res?.data?.unreadCount ??
        res?.count ??
        res?.unreadCount ??
        res?.data ??
        0
      ) || 0;
    unreadCount.value = count;
    syncMessageTabBarBadge(count);
  } catch (error) {
    unreadCount.value = unreadCount.value || 0;
    syncMessageTabBarBadge(unreadCount.value);
  }
};

const loadNotifications = async ({ reset = false } = {}) => {
  if (!isLoggedIn.value) {
    notificationList.value = [];
    totalCount.value = 0;
    hasMore.value = false;
    loadError.value = "";
    return;
  }

  if (loading.value) return;
  if (!reset && !hasMore.value) return;

  try {
    loading.value = true;
    loadError.value = "";
    const nextPage = reset ? 1 : page.value;
    const res = await fetchNotificationList({ page: nextPage });
    const { list, total } = normalizeListResponse(res);
    totalCount.value = total;
    mergeNotificationList(list, reset);
    hasMore.value = notificationList.value.length < total && list.length > 0;
    page.value = nextPage + 1;
  } catch (error) {
    console.error("获取消息列表失败:", error);
    loadError.value = "网络开了点小差，稍后再试";
    if (reset) {
      notificationList.value = [];
      totalCount.value = 0;
    }
  } finally {
    loading.value = false;
    uni.stopPullDownRefresh();
  }
};

const refreshList = async () => {
  page.value = 1;
  hasMore.value = true;
  await Promise.all([loadUnread(), loadNotifications({ reset: true })]);
};

const setItemReadState = (id, isRead = true) => {
  notificationList.value = notificationList.value.map((item) => {
    if (item.id !== id) return item;
    return {
      ...item,
      isRead,
    };
  });
};

const handleNavigate = (item) => {
  const isCommentInteraction = item?.type === 'comment' || item?.type === 'comment_like';
  const targetCommentId =
    item?.commentId ||
    (item?.targetType === 'comment' ? item?.targetId : '') ||
    item?.metadata?.commentId ||
    '';

  if (item.itemId) {
    uni.navigateTo({
      url: `/pages/rating/detail?topicId=${item.topicId || ""}&itemId=${item.itemId}${isCommentInteraction && targetCommentId ? `&commentId=${targetCommentId}` : ""}`,
    });
    return;
  }

  if (item.topicId) {
    uni.navigateTo({
      url: `/pages/rating/index?topicId=${item.topicId}`,
    });
    return;
  }
};

const markSingleAsRead = async (item) => {
  if (!item?.id || item.isRead || readingIds.value.includes(item.id)) return;

  readingIds.value = [...readingIds.value, item.id];
  try {
    await markAsRead(item.id);
    setItemReadState(item.id, true);
    unreadCount.value = Math.max(0, unreadCount.value - 1);
    syncMessageTabBarBadge(unreadCount.value);
  } catch (error) {
    console.error("标记消息已读失败:", error);
  } finally {
    readingIds.value = readingIds.value.filter((id) => id !== item.id);
  }
};

const handleItemTap = async (item) => {
  await markSingleAsRead(item);
  if(item.title.includes("未通过") || item.title.includes("已提交审核") || item.title.includes("评分项")) return
  handleNavigate(item);
};

const handleMarkAllRead = async () => {
  if (!isLoggedIn.value) {
    openLoginPopup("请先登录后再操作");
    return;
  }
  if (readingAll.value || unreadCount.value === 0) return;

  try {
    readingAll.value = true;
    await markAllAsRead();
    notificationList.value = notificationList.value.map((item) => ({
      ...item,
      isRead: true,
    }));
    unreadCount.value = 0;
    syncMessageTabBarBadge(0);
    uni.showToast({ title: "已全部标记为已读", icon: "none" });
  } catch (error) {
    console.error("全部标记已读失败:", error);
    uni.showToast({ title: "操作失败，请稍后再试", icon: "none" });
  } finally {
    readingAll.value = false;
  }
};

const handleLoginSuccess = async () => {
  await refreshList();
};

onLoad(() => {
  refreshList();
});

onShow(() => {
  if (firstShow) {
    firstShow = false;
    return;
  }
  refreshList();
});

onPullDownRefresh(() => {
  refreshList();
});

onReachBottom(() => {
  loadNotifications();
});
</script>

<style lang="scss" scoped>
.message-page {
  min-height: 100vh;
  background:
    radial-gradient(circle at top, rgba(255, 116, 71, 0.1) 0, rgba(255, 116, 71, 0) 36%),
    #f7f7f8;
  box-sizing: border-box;
}

.nav-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: rgba(247, 247, 248, 0.9);
  backdrop-filter: blur(18rpx);
}

.nav-content {
  min-height: 64px;
  padding: 0 28rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20rpx;
}

.nav-title {
  display: block;
  font-size: 38rpx;
  font-weight: 700;
  color: #18181b;
}

.nav-subtitle {
  display: block;
  margin-top: 8rpx;
  font-size: 22rpx;
  color: #8a8f99;
}

.nav-right {
  display: flex;
  align-items: center;
  gap: 14rpx;
  flex-shrink: 0;
}

.unread-chip {
  padding: 10rpx 18rpx;
  border-radius: 999rpx;
  background: rgba(255, 59, 48, 0.1);
}

.unread-chip-text {
  font-size: 22rpx;
  font-weight: 600;
  color: #ff4d4f;
}

.read-all-btn {
  padding: 12rpx 20rpx;
  border-radius: 999rpx;
  background: #111111;
}

.filter-read-all-btn {
  flex-shrink: 0;
  padding: 10rpx 22rpx;
}

.read-all-btn.disabled {
  opacity: 0.45;
}

.read-all-text {
  font-size: 22rpx;
  font-weight: 600;
  color: #ffffff;
}

.page-body {
  padding: 20rpx 24rpx 140rpx;
}

.hero-card {
  padding: 30rpx 28rpx;
  border-radius: 32rpx;
  background: linear-gradient(135deg, #ffffff 0%, #fff5f2 100%);
  box-shadow: 0 14rpx 34rpx rgba(15, 23, 42, 0.05);
}

.hero-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24rpx;
}

.hero-title {
  display: block;
  font-size: 34rpx;
  font-weight: 700;
  color: #171717;
}

.hero-desc {
  display: block;
  margin-top: 10rpx;
  font-size: 24rpx;
  line-height: 1.6;
  color: #7a7f88;
}

.hero-icon {
  width: 96rpx;
  height: 96rpx;
  flex-shrink: 0;
}

.hero-stats {
  margin-top: 28rpx;
  padding-top: 24rpx;
  border-top: 1rpx solid rgba(17, 17, 17, 0.06);
  display: flex;
  align-items: center;
}

.hero-stat {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.hero-stat-num {
  font-size: 34rpx;
  font-weight: 700;
  color: #111111;
}

.hero-stat-num.accent {
  color: #ff5a36;
}

.hero-stat-label {
  font-size: 22rpx;
  color: #8a8f99;
}

.hero-divider {
  width: 1rpx;
  height: 56rpx;
  background: rgba(17, 17, 17, 0.08);
}

.filter-bar {
  margin-top: 24rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20rpx;
}

.filter-tabs {
  padding: 8rpx;
  border-radius: 999rpx;
  background: #ffffff;
  display: inline-flex;
  align-items: center;
  gap: 8rpx;
  box-shadow: 0 10rpx 24rpx rgba(15, 23, 42, 0.04);
}

.filter-tab {
  min-width: 112rpx;
  height: 60rpx;
  padding: 0 24rpx;
  border-radius: 999rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.filter-tab.active {
  background: #111111;
}

.filter-tab-text {
  font-size: 24rpx;
  font-weight: 600;
  color: #8a8f99;
}

.filter-tab.active .filter-tab-text {
  color: #ffffff;
}

.filter-hint {
  font-size: 22rpx;
  color: #9aa0aa;
}

.section-list {
  margin-top: 20rpx;
}

.section-block + .section-block {
  margin-top: 24rpx;
}

.section-header {
  padding: 6rpx 8rpx 14rpx;
}

.section-title {
  font-size: 24rpx;
  font-weight: 600;
  color: #8a8f99;
}

.message-card {
  position: relative;
  display: flex;
  gap: 20rpx;
  padding: 24rpx;
  border-radius: 28rpx;
  background: #ffffff;
  box-shadow: 0 12rpx 28rpx rgba(15, 23, 42, 0.05);
}

.message-card + .message-card {
  margin-top: 16rpx;
}

.message-card.unread {
  background: linear-gradient(180deg, #ffffff 0%, #fff9f7 100%);
}

.message-avatar-wrap {
  position: relative;
  width: 84rpx;
  height: 84rpx;
  flex-shrink: 0;
}

.message-avatar {
  width: 84rpx;
  height: 84rpx;
  border-radius: 50%;
  background: #f4f5f7;
}

.message-dot {
  position: absolute;
  top: 0;
  right: 2rpx;
  width: 18rpx;
  height: 18rpx;
  border-radius: 50%;
  background: #ff4d4f;
  border: 4rpx solid #ffffff;
  box-sizing: border-box;
}

.message-main {
  flex: 1;
  min-width: 0;
}

.message-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20rpx;
}

.message-head-left {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10rpx;
}

.message-title {
  font-size: 28rpx;
  font-weight: 700;
  color: #18181b;
}

.type-tag {
  padding: 6rpx 14rpx;
  border-radius: 999rpx;
}

.type-tag-text {
  font-size: 20rpx;
  font-weight: 600;
}

.message-time {
  flex-shrink: 0;
  font-size: 22rpx;
  color: #a0a4ae;
}

.message-content {
  display: block;
  margin-top: 12rpx;
  font-size: 26rpx;
  line-height: 1.7;
  color: #555b66;
}

.message-footer {
  margin-top: 16rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20rpx;
}

.message-meta {
  font-size: 22rpx;
  color: #a0a4ae;
}

.message-link {
  font-size: 22rpx;
  font-weight: 600;
  color: #ff5a36;
}

.state-card {
  margin-top: 24rpx;
  padding: 44rpx 32rpx;
  border-radius: 32rpx;
  background: #ffffff;
  text-align: center;
  box-shadow: 0 12rpx 28rpx rgba(15, 23, 42, 0.05);
}

.login-card {
  margin-top: 28rpx;
}

.state-title {
  display: block;
  font-size: 30rpx;
  font-weight: 700;
  color: #18181b;
}

.state-desc {
  display: block;
  margin-top: 14rpx;
  font-size: 24rpx;
  line-height: 1.7;
  color: #8a8f99;
}

.primary-btn {
  margin-top: 24rpx;
  height: 84rpx;
  line-height: 84rpx;
  border-radius: 999rpx;
  background: linear-gradient(135deg, #ff7a45 0%, #ff4d4f 100%);
  color: #ffffff;
  font-size: 28rpx;
  font-weight: 600;
}

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

.list-status {
  padding: 28rpx 0 12rpx;
  text-align: center;
  font-size: 22rpx;
  color: #a0a4ae;
}
</style>
