<template>
  <section class="analysis-panel">
    <header class="panel-header">
      <LmFilterTabs v-model="dimensionModel" :options="dimensionTabs" mode="compact" />

      <div class="right-filters">
        <LmFilterTabs v-model="timeModel" :options="timeFilters" mode="compact" />
        <span class="update-tip">今日数据，每天0点更新</span>
      </div>
    </header>

    <div
      class="panel-main"
      @touchstart.passive="onTouchStart"
      @touchend.passive="onTouchEnd"
      @mousedown="onMouseDown"
      @mouseup="onMouseUp"
      @mouseleave="onMouseLeave"
    >
      <Transition :name="slideTransition" mode="out-in">
        <SubjectAnalysisContent :key="activeDimension" :dimension="activeDimension" />
      </Transition>
      <div class="pagination-dots">
        <button
          v-for="item in dimensionTabs"
          :key="item.key"
          type="button"
          class="dot"
          :class="{ active: item.key === activeDimension }"
          :aria-label="`切换到${item.label}`"
          @click="setDimension(item.key)"
        ></button>
      </div>
    </div>
  </section>
</template>

<script setup lang="ts">
import { computed, ref } from "vue";
import LmFilterTabs, { type FilterTabOption } from "@/components/lm/LmFilterTabs.vue";
import SubjectAnalysisContent, { type AnalysisDimension } from "./SubjectAnalysisContent.vue";

type TimeKey = "today" | "week" | "month" | "total";

const props = defineProps<{
  activeDimension: AnalysisDimension;
  activeTime: TimeKey;
  dimensionTabs: FilterTabOption[];
  timeFilters: FilterTabOption[];
}>();

const emit = defineEmits<{
  (e: "update:activeDimension", value: AnalysisDimension): void;
  (e: "update:activeTime", value: TimeKey): void;
}>();

const dimensionModel = computed({
  get: () => props.activeDimension,
  set: (value: string) => setDimension(value),
});

const timeModel = computed({
  get: () => props.activeTime,
  set: (value: string) => emit("update:activeTime", value as TimeKey),
});

const slideDirection = ref<"left" | "right">("left");
const slideTransition = computed(() => `slide-${slideDirection.value}`);

let touchStartX = 0;
let touchStartY = 0;
let mouseStartX = 0;
let mouseStartY = 0;
let isMouseDown = false;

function setDimension(value: string) {
  const next = value as AnalysisDimension;
  const currentIndex = currentDimensionIndex.value;
  const nextIndex = props.dimensionTabs.findIndex((item) => item.key === next);

  if (nextIndex >= 0 && currentIndex >= 0) {
    slideDirection.value = nextIndex > currentIndex ? "left" : "right";
  }

  emit("update:activeDimension", next);
}

function switchByOffset(offset: number) {
  const nextIndex = currentDimensionIndex.value + offset;
  const next = props.dimensionTabs[nextIndex];
  if (!next) return;
  slideDirection.value = offset > 0 ? "left" : "right";
  emit("update:activeDimension", next.key as AnalysisDimension);
}

function handleSwipe(endX: number, endY: number, startX: number, startY: number) {
  const diffX = startX - endX;
  const diffY = startY - endY;
  if (Math.abs(diffX) < 60 || Math.abs(diffX) <= Math.abs(diffY)) return;
  switchByOffset(diffX > 0 ? 1 : -1);
}

function onTouchStart(event: TouchEvent) {
  touchStartX = event.touches[0].clientX;
  touchStartY = event.touches[0].clientY;
}

function onTouchEnd(event: TouchEvent) {
  const touch = event.changedTouches[0];
  handleSwipe(touch.clientX, touch.clientY, touchStartX, touchStartY);
}

function onMouseDown(event: MouseEvent) {
  isMouseDown = true;
  mouseStartX = event.clientX;
  mouseStartY = event.clientY;
}

function onMouseUp(event: MouseEvent) {
  if (!isMouseDown) return;
  isMouseDown = false;
  handleSwipe(event.clientX, event.clientY, mouseStartX, mouseStartY);
}

function onMouseLeave() {
  isMouseDown = false;
}

const currentDimensionIndex = computed(() =>
  props.dimensionTabs.findIndex((item) => item.key === props.activeDimension),
);
</script>

<style scoped lang="scss">
.analysis-panel {
  width: 100%;
  max-width: 1792px;
  height: 100%;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 2px solid rgba(255, 255, 255, 0.72);
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.3);
}

.panel-header {
  min-height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 24px 32px;
  flex-shrink: 0;
}

.right-filters {
  display: flex;
  align-items: center;
  gap: 238px;
  flex-shrink: 0;
}

.update-tip {
  color: #7c8595;
  font-size: 18px;
  white-space: nowrap;
}

.panel-main {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 18px;
  background: linear-gradient(180deg, rgba(250, 254, 255, 0.82), rgba(255, 255, 255, 0.95));
  cursor: grab;
  user-select: none;

  &:active {
    cursor: grabbing;
  }
}

.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
  transition:
    transform 0.28s ease,
    opacity 0.28s ease;
}

.slide-left-enter-from,
.slide-right-leave-to {
  opacity: 0;
  transform: translateX(36px);
}

.slide-left-leave-to,
.slide-right-enter-from {
  opacity: 0;
  transform: translateX(-36px);
}

.pagination-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12px;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
  pointer-events: none;
}

.dot {
  width: 13px;
  height: 5px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: #dbe3ef;
  pointer-events: auto;
  cursor: pointer;
  transition: all 0.2s;

  &.active {
    width: 34px;
    background: #9ec2ff;
  }
}
</style>
