<script setup lang="ts">
import { ref, watch } from 'vue';
import { fetchGetProductActivityTimelinePage } from '@/service/api';
import {
  DEFAULT_PRODUCT_ACTIVITY_PAGE_SIZE,
  buildProductActivityDisplayItems,
  buildProductActivityRange,
  formatProductActivityTime
} from '../product-activity';
import ProductActivityTimelineDialog from './product-activity-timeline-dialog.vue';

defineOptions({ name: 'ProductActivityTimelinePanel' });

interface Props {
  productId: string;
}

interface Emits {
  (e: 'latest-time-change', value: string): void;
}

const props = defineProps<Props>();
const emit = defineEmits<Emits>();

const dialogVisible = ref(false);
const loading = ref(false);
const loadError = ref(false);
const items = ref<ReturnType<typeof buildProductActivityDisplayItems>>([]);

async function loadRecentActivities() {
  if (!props.productId) {
    items.value = [];
    loadError.value = false;
    emit('latest-time-change', '');
    return;
  }

  loading.value = true;
  loadError.value = false;

  try {
    const [startTime, endTime] = buildProductActivityRange(30);
    const result = await fetchGetProductActivityTimelinePage(props.productId, {
      pageNo: 1,
      pageSize: DEFAULT_PRODUCT_ACTIVITY_PAGE_SIZE,
      startTime,
      endTime
    });

    if (result.error || !result.data) {
      loadError.value = true;
      items.value = [];
      emit('latest-time-change', '');
      return;
    }

    items.value = buildProductActivityDisplayItems(result.data.list);
    emit('latest-time-change', formatProductActivityTime(result.data.list[0]?.occurredAt) || '');
  } finally {
    loading.value = false;
  }
}

function openDialog() {
  if (!props.productId) {
    return;
  }

  dialogVisible.value = true;
}

watch(
  () => props.productId,
  async () => {
    await loadRecentActivities();
  },
  { immediate: true }
);
</script>

<template>
  <ElCard class="product-activity-panel card-wrapper">
    <template #header>
      <div class="product-activity-panel__header">
        <div>
          <h3 class="product-activity-panel__title">产品动态时间线</h3>
        </div>

        <ElButton text type="primary" :disabled="!productId" @click="openDialog">更多</ElButton>
      </div>
    </template>

    <div v-loading="loading" class="product-activity-panel__body">
      <div v-if="loadError" class="product-activity-panel__state">
        <ElEmpty description="产品动态加载失败" :image-size="88" />
        <ElButton type="primary" plain @click="loadRecentActivities">重新加载</ElButton>
      </div>

      <div v-else-if="items.length" class="product-activity-panel__timeline">
        <article v-for="item in items" :key="item.id" class="product-activity-panel__item">
          <div class="product-activity-panel__rail">
            <span class="product-activity-panel__dot" :class="`product-activity-panel__dot--${item.tone}`" />
            <span class="product-activity-panel__line" />
          </div>

          <div class="product-activity-panel__content">
            <div class="product-activity-panel__meta">
              <div class="product-activity-panel__meta-main">
                <ElTag effect="plain" size="small">{{ item.tagLabel }}</ElTag>
              </div>
              <span class="product-activity-panel__time">{{ item.timeText }}</span>
            </div>

            <p class="product-activity-panel__sentence">
              <span class="product-activity-panel__sentence-main">{{ item.compactText }}</span>
              <span v-if="item.statusTransition">，状态：{{ item.statusTransition }}</span>
              <span v-if="item.reasonText">，原因：{{ item.reasonText }}</span>
            </p>
          </div>
        </article>
      </div>

      <ElEmpty v-else description="当前最近30天暂无可展示的产品动态" :image-size="88" />
    </div>
  </ElCard>

  <ProductActivityTimelineDialog v-model:visible="dialogVisible" :product-id="productId" />
</template>

<style scoped>
.product-activity-panel {
  overflow: hidden;
}

.product-activity-panel__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.product-activity-panel__title {
  margin: 0;
  color: rgb(15 23 42 / 98%);
  font-size: 16px;
  font-weight: 700;
}

.product-activity-panel__desc {
  margin: 4px 0 0;
  color: rgb(100 116 139 / 92%);
  font-size: 13px;
  line-height: 1.7;
}

.product-activity-panel__body {
  min-height: 520px;
}

.product-activity-panel__state {
  display: flex;
  min-height: 420px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.product-activity-panel__timeline {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.product-activity-panel__item {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  gap: 12px;
}

.product-activity-panel__rail {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.product-activity-panel__dot {
  width: 12px;
  height: 12px;
  margin-top: 6px;
  border-radius: 999px;
  box-shadow: 0 0 0 4px rgb(255 255 255 / 96%);
}

.product-activity-panel__dot--sky {
  background-color: rgb(14 165 233 / 88%);
}

.product-activity-panel__dot--emerald {
  background-color: rgb(5 150 105 / 88%);
}

.product-activity-panel__dot--amber {
  background-color: rgb(217 119 6 / 88%);
}

.product-activity-panel__dot--rose {
  background-color: rgb(225 29 72 / 88%);
}

.product-activity-panel__dot--slate {
  background-color: rgb(100 116 139 / 88%);
}

.product-activity-panel__line {
  flex: 1;
  width: 2px;
  min-height: 24px;
  margin-top: 4px;
  background: linear-gradient(180deg, rgb(203 213 225 / 96%), rgb(226 232 240 / 28%));
}

.product-activity-panel__item:last-child .product-activity-panel__line {
  opacity: 0;
}

.product-activity-panel__content {
  padding: 10px 12px;
  border: 1px solid rgb(226 232 240 / 92%);
  border-radius: 16px;
  background-color: rgb(255 255 255 / 98%);
}

.product-activity-panel__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.product-activity-panel__meta-main {
  display: flex;
  min-width: 0;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.product-activity-panel__time {
  color: rgb(100 116 139 / 90%);
  font-size: 12px;
}

.product-activity-panel__sentence {
  margin: 6px 0 0;
  color: rgb(71 85 105 / 94%);
  font-size: 14px;
  line-height: 1.6;
}

.product-activity-panel__sentence-main {
  color: rgb(15 23 42 / 98%);
}

@media (width <= 768px) {
  .product-activity-panel__body {
    min-height: auto;
  }

  .product-activity-panel__header {
    flex-direction: column;
    align-items: stretch;
  }
}
</style>
