<template>
  <PageContainer title="站内通知中心">
    <template #header>
      <div class="header-row">
        <el-space>
          <el-tag type="info">总数 {{ total }}</el-tag>
          <el-tag type="danger">未读 {{ unreadCount }}</el-tag>
          <el-switch
            v-if="canRead"
            v-model="onlyUnread"
            inline-prompt
            active-text="仅看未读"
            inactive-text="全部"
          />
          <el-button
            v-if="canRead && canMarkRead"
            type="primary"
            plain
            class="notif-mark-all-read-btn"
            :disabled="unreadCount <= 0"
            @click="handleMarkAllRead"
          >
            全部标记已读
          </el-button>
          <el-button v-if="canRead" @click="load">刷新</el-button>
        </el-space>
      </div>
    </template>

    <el-alert
      v-if="!canRead"
      title="当前账号无查看站内通知权限"
      type="warning"
      show-icon
      :closable="false"
      class="mb-md"
    />

    <el-table v-else :data="rows" class="mt-md" empty-text="暂无站内通知">
      <el-table-column prop="title" label="标题" min-width="220" />
      <el-table-column prop="content" label="内容" min-width="360" show-overflow-tooltip />
      <el-table-column prop="status" label="状态" width="100" :formatter="statusFormatter" />
      <el-table-column prop="createdAt" label="创建时间" width="180" />
      <el-table-column prop="readAt" label="已读时间" width="180" />
      <el-table-column label="操作" width="190">
        <template #default="{ row }">
          <el-space wrap>
            <el-button size="small" @click="openDetail(row)">查看详情</el-button>
            <el-button
              v-if="canMarkRead && row.status !== 'READ'"
              type="primary"
              size="small"
              class="notif-mark-read-btn"
              @click="handleMarkRead(row.id)"
            >
              标记已读
            </el-button>
          </el-space>
        </template>
      </el-table-column>
    </el-table>

    <div v-if="canRead" class="flex-end mt-md">
      <el-pagination
        :current-page="pageNo"
        :page-size="pageSize"
        :page-sizes="[10, 20, 50, 100]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        @current-change="handlePageChange"
        @size-change="handlePageSizeChange"
      />
    </div>

    <InAppNotificationDetailDialog
      v-model="detailVisible"
      :notification="currentNotification"
      :can-mark-read="canMarkRead"
      @mark-read="handleMarkRead"
    />
  </PageContainer>
</template>

<script setup lang="ts">
import { computed, onMounted, ref, watch } from "vue";
import { ElMessage } from "element-plus";
import { fetchInAppNotifications, markAllInAppNotificationsRead, markInAppNotificationRead } from "../../api/modules";
import InAppNotificationDetailDialog from "../../components/InAppNotificationDetailDialog.vue";
import PageContainer from "../../components/PageContainer.vue";
import { PERMS } from "../../constants/permissions";
import { useAuthStore } from "../../stores/auth";
import { useNotificationStore } from "../../stores/notification";
import { toZhStatus } from "../../utils/status";

const authStore = useAuthStore();
const notificationStore = useNotificationStore();

const canRead = computed(() => authStore.scope === "TENANT" && authStore.hasPermission(PERMS.notification.inAppRead));
const canMarkRead = computed(
  () => authStore.scope === "TENANT" && authStore.hasPermission(PERMS.notification.inAppMarkRead),
);

const onlyUnread = ref(false);
const pageNo = ref(1);
const pageSize = ref(20);
const total = ref(0);
const unreadCount = ref(0);
const rows = ref<Record<string, any>[]>([]);
const detailVisible = ref(false);
const currentNotification = ref<Record<string, any> | null>(null);

const statusFormatter = (_row: unknown, _column: unknown, value: unknown) => toZhStatus(value);

const syncCurrentNotification = (targetId?: number) => {
  const id = Number(targetId || currentNotification.value?.id || 0);
  if (!Number.isFinite(id) || id <= 0) {
    return;
  }
  const nextRow = rows.value.find((item) => Number(item?.id || 0) === id) || null;
  if (nextRow) {
    currentNotification.value = nextRow;
  }
};

const load = async () => {
  if (!canRead.value) {
    rows.value = [];
    total.value = 0;
    unreadCount.value = 0;
    return;
  }
  let resp = await fetchInAppNotifications({
    ts: Date.now(),
    pageNo: pageNo.value,
    pageSize: pageSize.value,
    onlyUnread: onlyUnread.value,
  });
  rows.value = Array.isArray(resp?.data?.list) ? resp.data.list : [];
  total.value = Number(resp?.data?.total || 0);
  pageNo.value = Number(resp?.data?.pageNo || pageNo.value || 1);
  pageSize.value = Number(resp?.data?.pageSize || pageSize.value || 20);
  const maxPage = total.value > 0 ? Math.max(1, Math.ceil(total.value / pageSize.value)) : 1;
  if (pageNo.value > maxPage) {
    pageNo.value = maxPage;
    resp = await fetchInAppNotifications({
      ts: Date.now(),
      pageNo: pageNo.value,
      pageSize: pageSize.value,
      onlyUnread: onlyUnread.value,
    });
    rows.value = Array.isArray(resp?.data?.list) ? resp.data.list : [];
    total.value = Number(resp?.data?.total || 0);
    pageNo.value = Number(resp?.data?.pageNo || pageNo.value || 1);
    pageSize.value = Number(resp?.data?.pageSize || pageSize.value || 20);
  }
  unreadCount.value = Number(notificationStore.unreadCount || 0);
};

const handleMarkRead = async (id: number) => {
  await markInAppNotificationRead(id);
  await notificationStore.loadUnreadCount();
  unreadCount.value = Number(notificationStore.unreadCount || 0);
  await load();
  syncCurrentNotification(id);
  ElMessage.success("已标记为已读");
};

const handleMarkAllRead = async () => {
  const resp = await markAllInAppNotificationsRead();
  const affected = Number(resp?.data?.affected || 0);
  await notificationStore.loadUnreadCount();
  unreadCount.value = Number(notificationStore.unreadCount || 0);
  if (onlyUnread.value && affected > 0) {
    pageNo.value = 1;
  }
  await load();
  syncCurrentNotification();
  ElMessage.success(affected > 0 ? `已标记 ${affected} 条通知为已读` : "没有未读通知");
};

const openDetail = (row: Record<string, any>) => {
  currentNotification.value = row;
  detailVisible.value = true;
};

const handlePageChange = async (nextPage: number) => {
  pageNo.value = Number(nextPage || 1);
  await load();
};

const handlePageSizeChange = async (nextPageSize: number) => {
  pageSize.value = Number(nextPageSize || 20);
  pageNo.value = 1;
  await load();
};

watch(rows, () => {
  if (!detailVisible.value || !currentNotification.value) {
    return;
  }
  syncCurrentNotification();
});

watch(onlyUnread, async () => {
  if (!canRead.value) {
    return;
  }
  pageNo.value = 1;
  await load();
});

onMounted(async () => {
  await notificationStore.loadUnreadCount();
  unreadCount.value = Number(notificationStore.unreadCount || 0);
  await load();
});
</script>

<style scoped>
.header-row {
  margin-top: 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

:deep(.notif-mark-all-read-btn.el-button--primary.is-plain) {
  background: rgba(var(--wo-theme-rgb), 0.14) !important;
  border: 1px solid rgba(var(--wo-theme-rgb), 0.3) !important;
  color: var(--wo-brand-primary-dark-2) !important;
  font-weight: 600;
}

:deep(.notif-mark-all-read-btn.el-button--primary.is-plain:hover:not(.is-disabled)) {
  background: rgba(var(--wo-theme-rgb), 0.22) !important;
  border-color: var(--wo-brand-primary-dark-2) !important;
  color: var(--wo-brand-primary-dark-2) !important;
  box-shadow: 0 2px 10px rgba(var(--wo-theme-rgb), 0.18);
}

:deep(.notif-mark-read-btn.el-button--primary) {
  background: var(--wo-brand-primary-dark-2) !important;
  border: 1px solid var(--wo-brand-primary-dark-2) !important;
  color: #fff !important;
  font-weight: 600;
  box-shadow: 0 2px 8px rgba(var(--wo-theme-rgb), 0.2);
}

:deep(.notif-mark-read-btn.el-button--primary:hover:not(.is-disabled)) {
  background: var(--wo-brand-gradient) !important;
  border-color: transparent !important;
  color: #fff !important;
}

:deep(.notif-mark-all-read-btn.is-disabled),
:deep(.notif-mark-read-btn.is-disabled) {
  box-shadow: none !important;
}
</style>
