<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useSettingsStore } from '../stores/settings'
import { getOS, clamp } from '../utils'

interface Props {
  id: string
  title?: string
  defaultWidth?: number
  defaultHeight?: number
  minWidth?: number
  minHeight?: number
}

const props = withDefaults(defineProps<Props>(), {
  title: '',
  defaultWidth: 800,
  defaultHeight: 600,
  minWidth: 400,
  minHeight: 300
})

const settingsStore = useSettingsStore()

type ResizeDirection = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw'

const isDragging = ref(false)
const isResizing = ref(false)
const resizeDirection = ref<ResizeDirection | null>(null)
const dragStartPos = ref({ x: 0, y: 0 })
const elementStartPos = ref({ x: 0, y: 0 })
const elementStartSize = ref({ width: 0, height: 0 })

const os = computed(() => getOS())
const isOpen = computed(() => settingsStore.isWindowOpen(props.id))
const windowState = computed(() => settingsStore.getWindowState(props.id))

const position = computed(() => windowState.value?.position ?? { x: 100, y: 100 })
const size = computed(() => windowState.value?.size ?? { width: props.defaultWidth, height: props.defaultHeight })
const zIndex = computed(() => windowState.value?.zIndex ?? 100)

const blurAmount = computed(() => settingsStore.theme.blurAmount ?? 20)
const backgroundColor = computed(() => settingsStore.theme.backgroundColor ?? 'rgba(30, 30, 30, 0.7)')

function close() {
  settingsStore.closeWindow(props.id)
}

function bringToFront() {
  settingsStore.bringWindowToFront(props.id)
}

function handleDragStart(e: MouseEvent) {
  if ((e.target as HTMLElement).closest('.window-close-btn')) return
  if ((e.target as HTMLElement).closest('.resize-handle')) return
  e.preventDefault()
  bringToFront()
  isDragging.value = true
  dragStartPos.value = { x: e.clientX, y: e.clientY }
  elementStartPos.value = { ...position.value }
  document.addEventListener('mousemove', handleDragMove)
  document.addEventListener('mouseup', handleDragEnd)
}

function handleDragMove(e: MouseEvent) {
  if (!isDragging.value) return

  const deltaX = e.clientX - dragStartPos.value.x
  const deltaY = e.clientY - dragStartPos.value.y

  const maxX = window.innerWidth - size.value.width - 20
  const maxY = window.innerHeight - size.value.height - 100

  const newX = clamp(elementStartPos.value.x + deltaX, 20, maxX)
  const newY = clamp(elementStartPos.value.y + deltaY, 20, maxY)

  settingsStore.updateWindowPosition(props.id, { x: newX, y: newY })
}

function handleDragEnd() {
  isDragging.value = false
  document.removeEventListener('mousemove', handleDragMove)
  document.removeEventListener('mouseup', handleDragEnd)
}

function handleResizeStart(e: MouseEvent, direction: ResizeDirection) {
  e.preventDefault()
  e.stopPropagation()
  bringToFront()
  isResizing.value = true
  resizeDirection.value = direction
  dragStartPos.value = { x: e.clientX, y: e.clientY }
  elementStartPos.value = { ...position.value }
  elementStartSize.value = { ...size.value }
  document.addEventListener('mousemove', handleResizeMove)
  document.addEventListener('mouseup', handleResizeEnd)
}

function handleResizeMove(e: MouseEvent) {
  if (!isResizing.value || !resizeDirection.value) return

  const deltaX = e.clientX - dragStartPos.value.x
  const deltaY = e.clientY - dragStartPos.value.y
  const dir = resizeDirection.value

  let newWidth = elementStartSize.value.width
  let newHeight = elementStartSize.value.height
  let newX = elementStartPos.value.x
  let newY = elementStartPos.value.y

  if (dir.includes('e')) {
    newWidth = clamp(elementStartSize.value.width + deltaX, props.minWidth, window.innerWidth - position.value.x - 20)
  }
  if (dir.includes('w')) {
    const maxDeltaX = elementStartSize.value.width - props.minWidth
    const actualDeltaX = clamp(deltaX, -maxDeltaX, elementStartPos.value.x - 20)
    newWidth = elementStartSize.value.width - actualDeltaX
    newX = elementStartPos.value.x + actualDeltaX
  }
  if (dir.includes('s')) {
    newHeight = clamp(elementStartSize.value.height + deltaY, props.minHeight, window.innerHeight - position.value.y - 100)
  }
  if (dir.includes('n')) {
    const maxDeltaY = elementStartSize.value.height - props.minHeight
    const actualDeltaY = clamp(deltaY, -maxDeltaY, elementStartPos.value.y - 20)
    newHeight = elementStartSize.value.height - actualDeltaY
    newY = elementStartPos.value.y + actualDeltaY
  }

  settingsStore.updateWindowPosition(props.id, { x: newX, y: newY })
  settingsStore.updateWindowSize(props.id, { width: newWidth, height: newHeight })
}

function handleResizeEnd() {
  isResizing.value = false
  resizeDirection.value = null
  document.removeEventListener('mousemove', handleResizeMove)
  document.removeEventListener('mouseup', handleResizeEnd)
}

onUnmounted(() => {
  document.removeEventListener('mousemove', handleDragMove)
  document.removeEventListener('mouseup', handleDragEnd)
  document.removeEventListener('mousemove', handleResizeMove)
  document.removeEventListener('mouseup', handleResizeEnd)
})
</script>

<template>
  <Teleport to="body">
    <Transition name="window-fade">
      <div
        v-if="isOpen"
        class="window"
        :class="{ 'window-dragging': isDragging }"
        :style="{
          left: position.x + 'px',
          top: position.y + 'px',
          width: size.width + 'px',
          height: size.height + 'px',
          zIndex: zIndex,
          background: backgroundColor,
          backdropFilter: 'blur(' + blurAmount + 'px)',
          WebkitBackdropFilter: 'blur(' + blurAmount + 'px)'
        }"
        @mousedown="bringToFront"
      >
        <div class="window-header" @mousedown="handleDragStart">
          <div class="window-controls" :class="{ 'controls-left': os === 'mac', 'controls-right': os !== 'mac' }">
            <button class="window-close-btn" @click="close" title="关闭">
              <svg v-if="os === 'mac'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
                <path d="M3 3l6 6M9 3l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
              </svg>
              <svg v-else xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
                <path d="M2 2l8 8M10 2l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
              </svg>
            </button>
          </div>
          <span class="window-title">{{ title }}</span>
          <div class="window-controls-placeholder"></div>
        </div>
        <div class="window-content">
          <slot></slot>
        </div>
        
        <div class="resize-handle resize-n" @mousedown="(e) => handleResizeStart(e, 'n')"></div>
        <div class="resize-handle resize-s" @mousedown="(e) => handleResizeStart(e, 's')"></div>
        <div class="resize-handle resize-e" @mousedown="(e) => handleResizeStart(e, 'e')"></div>
        <div class="resize-handle resize-w" @mousedown="(e) => handleResizeStart(e, 'w')"></div>
        <div class="resize-handle resize-ne" @mousedown="(e) => handleResizeStart(e, 'ne')"></div>
        <div class="resize-handle resize-nw" @mousedown="(e) => handleResizeStart(e, 'nw')"></div>
        <div class="resize-handle resize-se" @mousedown="(e) => handleResizeStart(e, 'se')"></div>
        <div class="resize-handle resize-sw" @mousedown="(e) => handleResizeStart(e, 'sw')"></div>
      </div>
    </Transition>
  </Teleport>
</template>

<style scoped>
.window {
  position: fixed;
  border-radius: 12px;
  background: v-bind('backgroundColor');
  backdrop-filter: blur(v-bind('blurAmount + "px"'));
  -webkit-backdrop-filter: blur(v-bind('blurAmount + "px"'));
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.window-dragging {
  cursor: grabbing;
}

.window-header {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  cursor: grab;
  user-select: none;
  min-height: 20px;
}

.window-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.window-controls-left {
  order: -1;
  margin-right: 12px;
}

.window-controls-right {
  order: 1;
  margin-left: 12px;
}

.window-close-btn {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #ff5f57;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: all 0.2s ease;
}

.window-close-btn:hover {
  background: #ff3b30;
}

.window-close-btn svg {
  width: 8px;
  height: 8px;
  color: rgba(0, 0, 0, 0.5);
  opacity: 0;
  transition: opacity 0.2s ease;
}

.window-close-btn:hover svg {
  opacity: 1;
}

.window-title {
  flex: 1;
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  color: white;
}

.window-controls-placeholder {
  width: 12px;
}

.window-content {
  flex: 1;
  overflow: auto;
  padding: 0;
}

.resize-handle {
  position: absolute;
  z-index: 10;
}

.resize-n, .resize-s {
  left: 10px;
  right: 10px;
  height: 6px;
  cursor: ns-resize;
}

.resize-n {
  top: -3px;
}

.resize-s {
  bottom: -3px;
}

.resize-e, .resize-w {
  top: 10px;
  bottom: 10px;
  width: 6px;
  cursor: ew-resize;
}

.resize-e {
  right: -3px;
}

.resize-w {
  left: -3px;
}

.resize-ne, .resize-nw, .resize-se, .resize-sw {
  width: 12px;
  height: 12px;
}

.resize-ne {
  top: -3px;
  right: -3px;
  cursor: nesw-resize;
}

.resize-nw {
  top: -3px;
  left: -3px;
  cursor: nwse-resize;
}

.resize-se {
  bottom: -3px;
  right: -3px;
  cursor: nwse-resize;
}

.resize-sw {
  bottom: -3px;
  left: -3px;
  cursor: nesw-resize;
}

.window-fade-enter-active,
.window-fade-leave-active {
  transition: all 0.3s ease;
}

.window-fade-enter-from,
.window-fade-leave-to {
  opacity: 0;
  transform: scale(0.95);
}
</style>
