<script setup lang="ts">
import { ref, computed, watch, onUnmounted } from 'vue'
import { useViewerStore } from '@/stores/viewer'
import { getClippingService, resetClippingService, type Axis } from '@/services/clippingService'
import { getRenderService } from '@/services/renderService'
import { getPartsTreeService } from '@/services/partsTreeService'

const viewerStore = useViewerStore()
const isInitialized = ref(false)

// Initialize when scene/renderer changes
watch(
  [() => viewerStore.scene, () => viewerStore.renderer],
  ([scene, renderer]) => {
    if (scene && renderer) {
      const service = getClippingService()
      service.initialize(scene, renderer)
      isInitialized.value = service.isInitialized()
    }
  },
  { immediate: true }
)

// Apply clipping when axis enabled state changes
watch(
  () => viewerStore.crossSection,
  (cs) => {
    if (!isInitialized.value) return

    const service = getClippingService()
    const axes: Axis[] = ['x', 'y', 'z']

    axes.forEach((axis) => {
      service.setAxisEnabled(axis, cs[axis].enabled)
      if (cs[axis].enabled) {
        service.setPlanePosition(axis, cs[axis].position)
      }
    })

    // Update edge line clipping planes
    getRenderService().updateEdgeClipping()

    // Update selection overlay clipping planes
    getPartsTreeService().updateSelectionClipping()

    viewerStore.forceRender()
  },
  { deep: true }
)

// Watch plane visibility changes
watch(
  () => viewerStore.crossSection.planeVisible,
  (visible) => {
    if (!isInitialized.value) return
    const service = getClippingService()
    service.setPlaneVisible(visible)
    viewerStore.forceRender()
  }
)

onUnmounted(() => {
  resetClippingService()
})

function toggleAxis(axis: Axis) {
  const current = viewerStore.crossSection[axis].enabled
  viewerStore.setCrossSectionAxis(axis, !current)
}

function handlePositionChange(axis: Axis, event: Event) {
  const target = event.target as HTMLInputElement
  viewerStore.setCrossSectionPosition(axis, Number(target.value))
}

function togglePlaneVisibility() {
  viewerStore.setCrossSectionPlaneVisible(!viewerStore.crossSection.planeVisible)
}

function toggleSection() {
  const service = getClippingService()
  service.flipAllPlaneNormals()
  viewerStore.setCrossSectionFlipped(!viewerStore.crossSection.sectionFlipped)
  // Update selection overlay clipping when planes flip
  getPartsTreeService().updateSelectionClipping()
  viewerStore.forceRender()
}

// Check if any plane is active
const hasActivePlane = computed(() => {
  return (
    viewerStore.crossSection.x.enabled ||
    viewerStore.crossSection.y.enabled ||
    viewerStore.crossSection.z.enabled
  )
})

const axisColors: Record<Axis, string> = {
  x: '#ef4444',
  y: '#22c55e',
  z: '#3b82f6',
}
</script>

<template>
  <div class="feature-section">
    <h4>剖面</h4>

    <div class="controls-row">
      <!-- Axis toggle buttons -->
      <div class="axis-toggles">
        <button
          v-for="axis in ['x', 'y', 'z'] as Axis[]"
          :key="axis"
          class="axis-btn"
          :class="[axis, { active: viewerStore.crossSection[axis].enabled }]"
          :disabled="!isInitialized"
          @click="toggleAxis(axis)"
        >
          {{ axis.toUpperCase() }}
        </button>
      </div>

      <!-- Action buttons -->
      <div class="action-toggles">
        <button
          class="action-btn"
          :class="{ active: viewerStore.crossSection.planeVisible }"
          :disabled="!isInitialized || !hasActivePlane"
          @click="togglePlaneVisibility"
          title="显示/隐藏切割平面"
        >
          <svg viewBox="0 0 20 20" fill="currentColor" class="icon">
            <template v-if="viewerStore.crossSection.planeVisible">
              <path d="M10 12a2 2 0 100-4 2 2 0 000 4z"/>
              <path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"/>
            </template>
            <template v-else>
              <path fill-rule="evenodd" d="M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z" clip-rule="evenodd"/>
              <path d="M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z"/>
            </template>
          </svg>
        </button>
        <button
          class="action-btn flip-btn"
          :class="{ active: viewerStore.crossSection.sectionFlipped }"
          :disabled="!isInitialized || !hasActivePlane"
          @click="toggleSection"
          title="切换显示区域"
        >
          <svg viewBox="0 0 20 20" fill="currentColor" class="icon">
            <path fill-rule="evenodd" d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z" clip-rule="evenodd"/>
          </svg>
        </button>
      </div>
    </div>

    <!-- Position sliders -->
    <div
      v-for="axis in ['x', 'y', 'z'] as Axis[]"
      :key="`slider-${axis}`"
      v-show="viewerStore.crossSection[axis].enabled"
      class="axis-slider"
    >
      <span class="axis-label" :style="{ color: axisColors[axis] }">
        {{ axis.toUpperCase() }}
      </span>
      <div class="slider-container">
        <input
          type="range"
          class="slider"
          min="0"
          max="100"
          :value="viewerStore.crossSection[axis].position"
          @input="(e) => handlePositionChange(axis, e)"
        />
        <span class="slider-value">{{ viewerStore.crossSection[axis].position }}%</span>
      </div>
    </div>

    <p v-if="hasActivePlane && viewerStore.crossSection.sectionFlipped" class="hint">
      已切换到对角区域
    </p>
  </div>
</template>

<style scoped>
.controls-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.axis-toggles {
  display: flex;
  gap: 4px;
}

.action-toggles {
  display: flex;
  gap: 4px;
}

.axis-slider {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}

.axis-label {
  font-weight: 600;
  font-size: 12px;
  min-width: 20px;
}

.action-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  background: var(--bg-secondary);
  color: var(--text-primary);
  cursor: pointer;
  transition: all 0.15s ease;
}

.action-btn:hover:not(:disabled) {
  background: var(--bg-tertiary);
  border-color: var(--primary-color);
}

.action-btn.active {
  background: var(--primary-color);
  border-color: var(--primary-color);
  color: white;
}

.action-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.action-btn .icon {
  width: 16px;
  height: 16px;
}

.flip-btn.active {
  background: #f59e0b;
  border-color: #f59e0b;
}

.hint {
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-secondary);
}

.slider-container {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
}

.slider {
  flex: 1;
  -webkit-appearance: none;
  height: 4px;
  border-radius: 2px;
  background: var(--bg-tertiary);
}

.slider::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: var(--bg-tertiary);
}

.slider::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: var(--bg-tertiary);
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--primary-color);
  cursor: pointer;
  margin-top: -5px;
}

.slider::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--primary-color);
  cursor: pointer;
  border: none;
}

.slider-value {
  min-width: 40px;
  text-align: right;
  font-size: 12px;
  color: var(--text-secondary);
}
</style>
