<script setup lang="ts">
import { reactive, ref, watch } from 'vue';
import dayjs from 'dayjs';
import { fetchGetProductActivityTimelinePage } from '@/service/api';
import BusinessDateRangePicker from '@/components/custom/business-date-range-picker.vue';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
import {
  DEFAULT_PRODUCT_ACTIVITY_PAGE_SIZE,
  PRODUCT_ACTIVITY_TIME_SHORTCUTS,
  PRODUCT_ACTIVITY_TYPE_OPTIONS,
  type ProductActivityFilterType,
  buildProductActivityDisplayItems,
  buildProductActivityRange
} from '../product-activity';

defineOptions({ name: 'ProductActivityTimelineDialog' });

interface Props {
  productId: string;
}

const props = defineProps<Props>();

const visible = defineModel<boolean>('visible', {
  default: false
});

const loading = ref(false);
const loadError = ref(false);
const items = ref<ReturnType<typeof buildProductActivityDisplayItems>>([]);
const pagination = reactive({
  pageNo: 1,
  pageSize: DEFAULT_PRODUCT_ACTIVITY_PAGE_SIZE,
  total: 0
});
const filters = reactive<{
  activityType: ProductActivityFilterType;
  timeRange: [string, string];
}>({
  activityType: 'all',
  timeRange: buildProductActivityRange(30)
});

const timeRangeShortcuts = PRODUCT_ACTIVITY_TIME_SHORTCUTS.map(shortcut => ({
  label: shortcut.label,
  value: () => {
    const end = dayjs();
    const start = dayjs()
      .subtract(Math.max(shortcut.days - 1, 0), 'day')
      .startOf('day');

    return [start.format('YYYY-MM-DD'), end.format('YYYY-MM-DD')] as [string, string];
  }
}));

function buildDraftDateRange(timeRange: [string, string]) {
  const [startTime, endTime] = timeRange;

  return [dayjs(startTime).format('YYYY-MM-DD'), dayjs(endTime).format('YYYY-MM-DD')] as [string, string];
}

function buildApiTimeRange(dateRange: [string, string]): [string, string] {
  const [startDate, endDate] = dateRange;

  return [
    dayjs(startDate).startOf('day').format('YYYY-MM-DD HH:mm:ss'),
    dayjs(endDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')
  ];
}

function buildQueryParams(): Api.Product.ProductActivityTimelinePageParams {
  const [startTime, endTime] = filters.timeRange;

  return {
    pageNo: pagination.pageNo,
    pageSize: pagination.pageSize,
    activityType: filters.activityType === 'all' ? null : filters.activityType,
    startTime,
    endTime
  };
}

function resetFilters() {
  filters.activityType = 'all';
  filters.timeRange = buildProductActivityRange(30);
  pagination.pageNo = 1;
  pagination.pageSize = DEFAULT_PRODUCT_ACTIVITY_PAGE_SIZE;
}

async function loadActivities() {
  if (!visible.value || !props.productId) {
    items.value = [];
    pagination.total = 0;
    loadError.value = false;
    return;
  }

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

  try {
    const result = await fetchGetProductActivityTimelinePage(props.productId, buildQueryParams());

    if (result.error || !result.data) {
      items.value = [];
      pagination.total = 0;
      loadError.value = true;
      return;
    }

    items.value = buildProductActivityDisplayItems(result.data.list);
    pagination.total = result.data.total;
  } finally {
    loading.value = false;
  }
}

function reloadActivities() {
  loadActivities().catch(() => {
    loadError.value = true;
  });
}

function handleQuery() {
  pagination.pageNo = 1;
  reloadActivities();
}

function handleReset() {
  resetFilters();
  reloadActivities();
}

function handlePageChange(pageNo: number) {
  pagination.pageNo = pageNo;
  reloadActivities();
}

function handleDateRangeChange(dateRange: [string, string]) {
  filters.timeRange = buildApiTimeRange(dateRange);
  pagination.pageNo = 1;
  reloadActivities();
}

watch(
  () => filters.activityType,
  () => {
    if (!visible.value) {
      return;
    }

    pagination.pageNo = 1;
    reloadActivities();
  }
);

watch([() => visible.value, () => props.productId], ([currentVisible, productId]) => {
  if (!currentVisible) {
    return;
  }

  if (!productId) {
    items.value = [];
    pagination.total = 0;
    loadError.value = false;
    return;
  }

  reloadActivities();
});
</script>

<template>
  <BusinessFormDialog
    v-model="visible"
    class="product-activity-dialog"
    title="产品动态时间线"
    width="1100px"
    :scrollbar="false"
  >
    <div class="product-activity-dialog__layout">
      <aside class="product-activity-dialog__filters">
        <section class="product-activity-dialog__section">
          <div class="product-activity-dialog__section-header">
            <h4>分类</h4>
          </div>

          <ElRadioGroup v-model="filters.activityType" class="product-activity-dialog__radio-group">
            <ElRadioButton
              v-for="option in PRODUCT_ACTIVITY_TYPE_OPTIONS"
              :key="option.value"
              :label="option.value"
              :value="option.value"
            >
              {{ option.label }}
            </ElRadioButton>
          </ElRadioGroup>
        </section>

        <section class="product-activity-dialog__section">
          <div class="product-activity-dialog__section-header">
            <h4>时间范围</h4>
          </div>

          <BusinessDateRangePicker
            :model-value="buildDraftDateRange(filters.timeRange)"
            :shortcuts="timeRangeShortcuts"
            placeholder="请选择时间范围"
            @update:model-value="handleDateRangeChange"
          />
        </section>

        <div class="product-activity-dialog__actions">
          <ElButton @click="handleReset">重置</ElButton>
          <ElButton type="primary" @click="handleQuery">查询</ElButton>
        </div>
      </aside>

      <section class="product-activity-dialog__result">
        <div class="product-activity-dialog__result-header">
          <h4>查询结果</h4>
          <span v-if="pagination.total" class="product-activity-dialog__result-total">
            共 {{ pagination.total }} 条
          </span>
        </div>

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

          <ElScrollbar v-else-if="items.length" class="product-activity-dialog__scrollbar">
            <div class="product-activity-dialog__timeline">
              <article v-for="item in items" :key="item.id" class="product-activity-dialog__item">
                <div class="product-activity-dialog__rail">
                  <span class="product-activity-dialog__dot" :class="`product-activity-dialog__dot--${item.tone}`" />
                  <span class="product-activity-dialog__line" />
                </div>

                <div class="product-activity-dialog__content">
                  <div class="product-activity-dialog__meta">
                    <div class="product-activity-dialog__meta-main">
                      <ElTag effect="plain" size="small">{{ item.tagLabel }}</ElTag>
                    </div>
                    <span class="product-activity-dialog__time">{{ item.timeText }}</span>
                  </div>

                  <p class="product-activity-dialog__sentence">
                    <span class="product-activity-dialog__sentence-main">
                      <template v-for="(part, index) in item.compactTextParts" :key="`${item.id}-${index}`">
                        <strong v-if="part.strong" class="product-activity-dialog__subject">{{ part.text }}</strong>
                        <span v-else>{{ part.text }}</span>
                      </template>
                    </span>
                    <span v-if="item.statusTransition">，状态：{{ item.statusTransition }}</span>
                    <span v-if="item.reasonText">，原因：{{ item.reasonText }}</span>
                  </p>
                </div>
              </article>
            </div>
          </ElScrollbar>

          <ElEmpty v-else description="当前筛选条件下暂无产品动态" :image-size="88" />
        </div>
      </section>
    </div>

    <template #footer="{ close }">
      <div class="product-activity-dialog__footer-inner">
        <div class="product-activity-dialog__footer-pagination">
          <ElPagination
            v-if="pagination.total"
            layout="total,prev,pager,next"
            :current-page="pagination.pageNo"
            :page-size="pagination.pageSize"
            :total="pagination.total"
            @current-change="handlePageChange"
          />
        </div>

        <ElButton @click="close">关闭</ElButton>
      </div>
    </template>
  </BusinessFormDialog>
</template>

<style scoped>
.product-activity-dialog {
  :deep(.el-dialog) {
    max-width: calc(100vw - 32px);
  }
}

.product-activity-dialog__layout {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  gap: 16px;
  height: 640px;
}

.product-activity-dialog__filters,
.product-activity-dialog__result {
  min-width: 0;
  border: 1px solid var(--el-border-color-light);
  border-radius: 18px;
  background-color: var(--el-fill-color-lighter);
}

.product-activity-dialog__filters {
  display: flex;
  flex-direction: column;
  gap: 16px;
  height: 100%;
  padding: 16px;
  overflow-y: auto;
}

.product-activity-dialog__section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.product-activity-dialog__section-header {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.product-activity-dialog__section-header h4,
.product-activity-dialog__result-header h4 {
  margin: 0;
  color: var(--el-text-color-primary);
  font-size: 14px;
  font-weight: 700;
}

.product-activity-dialog__section-header span,
.product-activity-dialog__result-total {
  margin: 0;
  color: var(--el-text-color-secondary);
  font-size: 12px;
  line-height: 1.6;
}

.product-activity-dialog__radio-group {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.product-activity-dialog__radio-group :deep(.el-radio-button__inner) {
  width: 100%;
}

.product-activity-dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: auto;
}

.product-activity-dialog__time-range-input {
  width: 100%;
}

.product-activity-dialog__result {
  display: flex;
  flex-direction: column;
  gap: 16px;
  height: 100%;
  padding: 16px;
  overflow: hidden;
  background: linear-gradient(180deg, var(--el-bg-color), var(--el-fill-color-lighter));
}

.product-activity-dialog__result-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.product-activity-dialog__result-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.product-activity-dialog__state {
  display: flex;
  height: 100%;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.product-activity-dialog__scrollbar {
  height: 100%;
}

.product-activity-dialog__scrollbar :deep(.el-scrollbar__wrap) {
  overflow-x: hidden;
}

.product-activity-dialog__timeline {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 100%;
}

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

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

.product-activity-dialog__dot {
  width: 12px;
  height: 12px;
  margin-top: 6px;
  border-radius: 999px;
  box-shadow: 0 0 0 4px var(--el-bg-color);
}

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

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

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

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

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

.product-activity-dialog__line {
  flex: 1;
  width: 2px;
  min-height: 24px;
  margin-top: 4px;
  background: linear-gradient(180deg, var(--el-border-color), transparent);
}

.product-activity-dialog__item:last-child .product-activity-dialog__line {
  opacity: 0;
}

.product-activity-dialog__content {
  padding: 10px 12px;
  border: 1px solid var(--el-border-color-light);
  border-radius: 16px;
  background-color: var(--el-bg-color);
}

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

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

.product-activity-dialog__time {
  color: var(--el-text-color-secondary);
  font-size: 12px;
}

.product-activity-dialog__sentence {
  margin: 6px 0 0;
  color: var(--el-text-color-regular);
  font-size: 14px;
  line-height: 1.6;
}

.product-activity-dialog__sentence-main {
  color: var(--el-text-color-primary);
}

.product-activity-dialog__subject {
  color: var(--el-text-color-primary);
  font-weight: 700;
}

.product-activity-dialog__footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
}

.product-activity-dialog__footer-pagination {
  min-width: 0;
}

@media (width <= 960px) {
  .product-activity-dialog__layout {
    grid-template-columns: 1fr;
    height: 640px;
  }

  .product-activity-dialog__result-header {
    flex-direction: column;
    align-items: stretch;
  }

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