<template>
  <div class="error-boundary">
    <slot v-if="!hasError"></slot>
    <transition name="fade">
      <div v-if="hasError" class="error-page">
        <div class="error-content">
          <el-icon class="error-icon"><WarningFilled /></el-icon>
          <h3>页面加载失败</h3>
          <p>{{ errorMessage || '当前页面发生了错误，请尝试刷新或返回首页' }}</p>
          <div class="error-actions">
            <el-button type="primary" @click="handleRetry">重试</el-button>
            <el-button @click="handleGoHome">返回首页</el-button>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onErrorCaptured, onUnmounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { WarningFilled } from '@element-plus/icons-vue'
import { useTabsStore } from '@/stores/modules/tabs'

const router = useRouter()
const route = useRoute()
const tabsStore = useTabsStore()

const hasError = ref(false)
const errorMessage = ref('')
let unwatchRoute: (() => void) | null = null

// 判断是否为 API 请求错误或表单验证错误（这些错误不应该触发错误边界）
const isApiError = (err: any): boolean => {
console.log('err:', err);
  // axios 错误通常有 config 属性
  if ((err as any).config) return true
  // 网络错误
  if (err.message === 'Network Error') return true
  // 超时错误
  if (err.message?.includes('timeout') || err.message?.includes('Timeout')) return true
  // 请求被取消
  if (err.message?.includes('cancel') || err.name === 'CanceledError') return true
  // 包含请求相关信息的错误
  if (err.message?.includes('request') || err.message?.includes('Request')  || err.data  || err.msg) return true
  
  // ========== 表单验证相关错误 ==========
  // Element Plus 表单验证错误格式：{ fieldName: [errorMessage], ... }
  // 检查是否为普通对象（非 Error 实例）且值为数组（错误信息数组）
  if (err && typeof err === 'object' && !err.message && !err.stack) {
    const keys = Object.keys(err)
    if (keys.length > 0 && keys.every(key => Array.isArray(err[key]))) {
      // 这是一个表单验证错误对象 {varietyName: [错误信息], ...}
      return true
    }
  }
  // Element Plus 表单验证错误特征
  const errorMessage = err.message || err.msg || ''
  // 表单验证错误常见关键词
  const formValidationKeywords = ['validate', 'validation', '校验', '验证', '必填', 'required', 'pattern', '格式']
  if (formValidationKeywords.some(keyword => errorMessage.toLowerCase().includes(keyword.toLowerCase()))) return true
  // 表单验证错误对象特征（包含 field、trigger 等属性）
  if (err.field || err.fieldName || err.prop || err.validator) return true
  // 表单验证错误数组
  if (Array.isArray(err.errors) && err.errors.length > 0) return true
  // 自定义表单验证错误类名
  if (err.name === 'ValidationError' || err.name === 'FormValidateError') return true
  
  return true
}

// 全局错误捕获
onErrorCaptured((err: Error, instance: any, info: string) => {
  console.error('❌ ErrorBoundary 捕获到错误:', err)
  console.error('错误来源组件:', instance?.$options?.name || '未知组件')
  console.error('错误信息:', info)
  
  // 如果是 API 请求错误，不触发错误边界，让 API 模块自己处理
  if (isApiError(err)) {
    console.log('API 请求错误，由 API 模块处理')
    return false
  }
  
  // 只有真正的渲染错误才触发错误边界
  hasError.value = true
  errorMessage.value = err.message || '未知错误'
  
  // 返回 false 阻止错误继续向上传播
  return false
})

// 监听路由变化，自动清除错误状态
unwatchRoute = watch(
  () => route.path,
  () => {
    // 路由变化时，清除错误状态
    if (hasError.value) {
      hasError.value = false
      errorMessage.value = ''
    }
  }
)

// 组件卸载时清理
onUnmounted(() => {
  if (unwatchRoute) {
    unwatchRoute()
    unwatchRoute = null
  }
})

// 重试当前页面
const handleRetry = () => {
  hasError.value = false
  errorMessage.value = ''
  // 刷新当前路由的 key，触发重新渲染
  tabsStore.refreshTab(route.path)
  router.replace(route.fullPath)
}

// 返回首页
const handleGoHome = () => {
  hasError.value = false
  errorMessage.value = ''
  router.push('/dashboard')
}
</script>

<style scoped lang="scss">
.error-boundary {
  width: 100%;
  height: 100%;
  position: relative;
}

.error-page {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--el-bg-color-page, #f5f7fa);
  z-index: 100;
  
  .error-content {
    text-align: center;
    padding: 40px;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    max-width: 400px;
    
    .error-icon {
      font-size: 64px;
      color: #e6a23c;
      margin-bottom: 20px;
    }
    
    h3 {
      font-size: 24px;
      color: #303133;
      margin-bottom: 12px;
    }
    
    p {
      font-size: 14px;
      color: #909399;
      margin-bottom: 24px;
      line-height: 1.6;
    }
    
    .error-actions {
      display: flex;
      gap: 12px;
      justify-content: center;
    }
  }
}

// 过渡动画
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>