<script setup lang="ts">
import type { FileItem } from './FileUploader.vue'
import CardContainer from '@af-mobile-client-vue3/components/data/CardContainer/CardContainer.vue'
import CardHeader from '@af-mobile-client-vue3/components/data/CardContainer/CardHeader.vue'
import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
import {
  showFailToast,
  showToast,
  Button as VanButton,
  Icon as VanIcon,
  ImagePreview as VanImagePreview,
} from 'vant'
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'

export interface FileTypeConfig {
  userType: string
  picMinNum: number
  icon?: string
  description?: string
}

interface Props {
  fileTypes: FileTypeConfig[]
  fileList?: FileItem[]
  title?: string
  maxSize?: number
}

const props = withDefaults(defineProps<Props>(), {
  fileList: () => [],
  title: '上传附件',
  maxSize: 10 * 1024 * 1024, // 10MB
})

const emit = defineEmits<{
  'update:fileList': [value: FileItem[]]
}>()

// 文件存储，按类型分组
const filesByType = reactive<Record<string, FileItem[]>>({})

// 浮动按钮状态管理
const activeTypeKey = ref<string>('')
const showFloatingButtons = ref(false)
// 定时器 ref 用于管理自动隐藏
const hideTimer = ref<number | null>(null)

// 图片预览状态管理
const showPreview = ref(false)
const previewImages = ref<string[]>([])
const previewIndex = ref(0)
const currentPreviewType = ref<string>('')
const currentPreviewFiles = ref<FileItem[]>([])

// 判断是否为开发环境
const isDev = import.meta.env.MODE === 'development'

// 模拟图片的base64数据 - 四色块图片（红绿蓝紫）
const mockImageBase64 = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8IS0tIOW3puS4iiAoUmVkKSAtLT4KICA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIGZpbGw9IiNGRjQ0NDQiLz4KICA8IS0tIOWPs+S4iiAoR3JlZW4pIC0tPgogIDxyZWN0IHg9IjUwIiB5PSIwIiB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIGZpbGw9IiM0NEZGNDQiLz4KICA8IS0tIOW3puS4iyAoQmx1ZSkgLS0+CiAgPHJlY3QgeD0iMCIgeT0iNTAiIHdpZHRoPSI1MCIgaGVpZ2h0PSI1MCIgZmlsbD0iIzQ0NDRGRiIvPgogIDwhLS0g57Sr5LiKIChQdXJwbGUpIC0tPgogIDxyZWN0IHg9IjUwIiB5PSI1MCIgd2lkdGg9IjUwIiBoZWlnaHQ9IjUwIiBmaWxsPSIjRkY0NEZGIi8+Cjwvc3ZnPgo='

// 所有文件的扁平列表
const allFiles = computed<FileItem[]>(() => {
  const files: FileItem[] = []
  Object.values(filesByType).forEach((typeFiles) => {
    files.push(...typeFiles)
  })
  return files
})

// 转换为标准FileItem格式并发送给父组件
function emitFileListUpdate(): void {
  emit('update:fileList', allFiles.value)
}

// 获取图标
function getIcon(config: FileTypeConfig): string {
  return config.icon || 'fluent-emoji:file-folder'
}

// 初始化文件存储
onMounted(() => {
  props.fileTypes.forEach((type) => {
    if (!filesByType[type.userType]) {
      filesByType[type.userType] = []
    }
  })
})

// 组件卸载时清理定时器
onUnmounted(() => {
  if (hideTimer.value) {
    clearTimeout(hideTimer.value)
    hideTimer.value = null
  }
})

// 触发文件上传
function triggerFileUpload(typeKey: string): void {
  console.log('点击上传事件 - 类型:', typeKey)

  // 判断是否为开发环境
  if (isDev) {
    console.log('开发环境，使用模拟上传并调用真实接口')
    uploadFileInDevMode(typeKey)
    return
  }

  // 非开发环境，使用原生功能
  mobileUtil.execute({
    funcName: 'takePicture',
    param: {},
    callbackFunc: (result: any) => {
      if (result.status === 'success') {
        uploadFileInProdMode(typeKey, result.data)
      }
    },
  })
}

// 开发环境上传文件
function uploadFileInDevMode(typeKey: string): void {
  // 基本信息
  const filename = `${typeKey}_test.png`
  const fileSize = 0.0003 // MB
  const operator = '测试管理员'

  // 创建临时文件对象（SVG转换为文件）
  const uid = Date.now() + Math.random().toString(36).substr(2, 5)
  const byteString = atob(mockImageBase64.split(',')[1])
  const ab = new ArrayBuffer(byteString.length)
  const ia = new Uint8Array(ab)
  for (let i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i)
  }
  const blob = new Blob([ab], { type: 'image/png' })
  const file = new File([blob], filename, { type: 'image/png' })

  // 创建文件项
  const fileItem: FileItem = {
    uid,
    name: filename,
    size: file.size,
    type: 'image/svg+xml',
    userType: typeKey,
    status: 'uploading',
    url: mockImageBase64,
  }

  // 添加到对应类型的文件列表
  if (!filesByType[typeKey]) {
    filesByType[typeKey] = []
  }
  filesByType[typeKey].push(fileItem)

  // 创建FormData
  const formData = new FormData()
  formData.append('avatar', file) // 文件二进制数据
  formData.append('resUploadMode', 'server')
  formData.append('formType', 'file')
  formData.append('useType', typeKey)
  formData.append('resUploadStock', '1')
  formData.append('filename', filename)
  formData.append('filesize', fileSize.toString())
  formData.append('f_operator', operator)

  // 调用接口上传
  fetch('/api/af-revenue/resource/upload', {
    method: 'POST',
    body: formData,
  })
    .then(response => response.json())
    .then((result) => {
      console.log('上传成功:', result)
      // 找到对应文件项 并替换
      const fileItem = filesByType[typeKey].find(f => f.uid === uid)
      if (fileItem) {
        fileItem.status = 'success'
        fileItem.result = result.data.data
      }
      emitFileListUpdate()
    })
    .catch((error) => {
      console.error('上传失败:', error)
      fileItem.status = 'error'
      showFailToast(`上传文件失败: ${error.message || error.msg || '请稍后重试'}`)
      emitFileListUpdate()
    })
}

// 生产环境上传文件
function uploadFileInProdMode(typeKey: string, file: any): void {
  // 创建文件项
  const fileItem: FileItem = {
    uid: Date.now() + Math.random().toString(36).substr(2, 5),
    name: file.name,
    size: file.size,
    type: 'image/jpeg',
    userType: typeKey,
    status: 'uploading',
    url: `data:image/png;base64,${file.content}`,
    filePath: file?.filePath,
  }

  // 添加到对应类型的文件列表
  if (!filesByType[typeKey]) {
    filesByType[typeKey] = []
  }
  filesByType[typeKey].push(fileItem)

  mobileUtil.execute({
    funcName: 'uploadResource',
    param: {
      resUploadMode: 'server',
      pathKey: 'Default',
      formType: 'image',
      useType: typeKey,
      resUploadStock: '1',
      filename: file?.name,
      filesize: file?.size,
      f_operator: 'server',
      imgPath: file?.filePath,
      urlPath: '/api/af-revenue/resource/upload',
    },
    callbackFunc: (result: any) => {
      if (result.status === 'success') {
        fileItem.status = 'success'
        fileItem.result = result.data
        emitFileListUpdate()
      }
      else {
        fileItem.status = 'error'
        showFailToast(`上传图片失败,${result.message}`)
        emitFileListUpdate()
      }
    },
  })
}

// 删除文件
function removeFile(typeKey: string, fileId: string | number): void {
  const typeFiles = filesByType[typeKey]
  if (!typeFiles)
    return

  const index = typeFiles.findIndex(f => f.uid === fileId)
  if (index > -1) {
    const removedFile = typeFiles.splice(index, 1)[0]
    if (removedFile.url) {
      URL.revokeObjectURL(removedFile.url)
    }

    emitFileListUpdate()
  }
}

// 显示浮动按钮
function showFloatingMenu(typeKey: string): void {
  // 清除之前的定时器
  if (hideTimer.value) {
    clearTimeout(hideTimer.value)
    hideTimer.value = null
  }

  activeTypeKey.value = typeKey
  showFloatingButtons.value = true

  hideTimer.value = window.setTimeout(() => {
    hideFloatingMenu()
  }, 1200)
}

// 隐藏浮动按钮
function hideFloatingMenu(): void {
  // 清除定时器
  if (hideTimer.value) {
    clearTimeout(hideTimer.value)
    hideTimer.value = null
  }

  showFloatingButtons.value = false
  activeTypeKey.value = ''
}

// 查看已上传的文件
function viewFiles(typeKey: string): void {
  const typeFiles = filesByType[typeKey]
  if (!typeFiles?.length) {
    showToast('暂无已上传的文件')
    return
  }

  // 过滤出图片文件
  const imageFiles = typeFiles.filter(f => f.url && f.type.startsWith('image/'))
  if (!imageFiles.length) {
    showToast('暂无图片文件')
    return
  }

  // 设置预览状态
  currentPreviewType.value = typeKey
  currentPreviewFiles.value = imageFiles
  previewImages.value = imageFiles.map(f => f.url!).filter(Boolean)
  previewIndex.value = 0
  showPreview.value = true

  hideFloatingMenu()
}

// 上传文件（原有逻辑）
function uploadFiles(typeKey: string): void {
  triggerFileUpload(typeKey)
  hideFloatingMenu()
}

// 预览组件事件处理
function onPreviewChange(index: number): void {
  previewIndex.value = index
}

// 删除当前预览的图片
function deleteCurrentPreviewImage(): void {
  const currentFile = currentPreviewFiles.value[previewIndex.value]
  if (!currentFile)
    return

  // 从文件列表中删除
  removeFile(currentPreviewType.value, currentFile.uid)

  // 更新预览状态
  currentPreviewFiles.value.splice(previewIndex.value, 1)
  previewImages.value.splice(previewIndex.value, 1)

  // 如果没有图片了，关闭预览
  if (previewImages.value.length === 0) {
    showPreview.value = false
    return
  }

  // 调整索引
  if (previewIndex.value >= previewImages.value.length) {
    previewIndex.value = previewImages.value.length - 1
  }
}

// 获取类型的已上传文件数量
function getUploadedCount(typeKey: string): number {
  return filesByType[typeKey]?.length || 0
}

// 检查是否必填且未满足最小要求
function isRequired(config: FileTypeConfig): boolean {
  return config.picMinNum > 0
}

function isRequirementMet(config: FileTypeConfig): boolean {
  const uploadedCount = getUploadedCount(config.userType)
  return uploadedCount >= config.picMinNum
}

// 验证所有必填项是否满足
function validateAll(): boolean {
  for (const config of props.fileTypes) {
    if (isRequired(config) && !isRequirementMet(config)) {
      showToast(`${config.userType}至少需要上传${config.picMinNum}张照片`)
      return false
    }
  }
  return true
}

const minLength = computed(() => {
  return props.fileTypes.reduce((acc, config) => acc + config.picMinNum, 0)
})

// 暴露验证方法给父组件
defineExpose({
  validateAll,
  getAllFiles: () => allFiles.value,
  triggerFileUpload,
})
</script>

<template>
  <CardContainer class="grid-file-uploader">
    <CardHeader :title="title">
      <template #extra>
        <div class="grid-file-uploader__progress">
          上传进度: {{ allFiles.filter(f => f.status === 'success').length }}/{{ minLength }} 已完成
        </div>
      </template>
    </CardHeader>

    <div class="grid-file-uploader__description">
      点击对应类别上传相关照片和文件
    </div>

    <div class="grid-file-uploader__grid">
      <div
        v-for="config in fileTypes"
        :key="config.userType"
        class="grid-file-uploader__item"
        :class="{
          'grid-file-uploader__item--required': isRequired(config),
          'grid-file-uploader__item--completed': isRequirementMet(config),
          'grid-file-uploader__item--pending': isRequired(config) && !isRequirementMet(config),
        }"
      >
        <!-- 必填标识 -->
        <div
          v-if="isRequired(config) && !isRequirementMet(config)"
          class="grid-file-uploader__item-required"
        >
          必
        </div>
        <VanIcon
          v-else-if="isRequirementMet(config)"
          name="success"
          class="grid-file-uploader__item-success"
        />

        <!-- 文件上传区域 -->
        <div class="grid-file-uploader__item-content" @click="showFloatingMenu(config.userType)">
          <!-- 图标 -->
          <div class="grid-file-uploader__item-icon">
            <VanIcon
              :icon="getIcon(config)"
              class="grid-file-uploader__icon"
            />
          </div>

          <!-- 标题 -->
          <div class="grid-file-uploader__item-title">
            {{ config.userType }}
          </div>

          <!-- 描述文本 -->
          <div class="grid-file-uploader__item-desc">
            {{ config.description || `${config.userType}照片` }}
          </div>

          <!-- 文件数量显示 -->
          <div class="grid-file-uploader__item-count">
            {{ getUploadedCount(config.userType) }}
            <span v-if="config.picMinNum > 0" class="grid-file-uploader__item-count-min">
              /{{ config.picMinNum }}
            </span>
          </div>
        </div>

        <!-- 浮动按钮 -->
        <div
          v-if="showFloatingButtons && activeTypeKey === config.userType"
          class="grid-file-uploader__floating-buttons"
          @click.stop
        >
          <VanButton
            v-if="getUploadedCount(config.userType) > 0"
            type="primary"
            size="small"
            icon="eye-o"
            class="grid-file-uploader__floating-btn"
            @click="viewFiles(config.userType)"
          >
            查看
          </VanButton>
          <VanButton
            type="success"
            size="small"
            :icon="isDev ? 'photograph' : 'camera-o'"
            class="grid-file-uploader__floating-btn"
            @click="uploadFiles(config.userType)"
          >
            {{ isDev ? '上传' : '拍照' }}
          </VanButton>
        </div>
      </div>
    </div>

    <!-- 图片预览组件 -->
    <VanImagePreview
      v-model:show="showPreview"
      :images="previewImages"
      :start-position="previewIndex"
      teleport="body"
      @change="onPreviewChange"
    >
      <template #index>
        <div class="preview-footer" style="text-align: center;">
          <span class="preview-index">第{{ previewIndex + 1 }}页</span>
          <br>
          <VanButton
            type="danger"
            size="small"
            icon="delete-o"
            class="preview-delete-btn"
            @click="deleteCurrentPreviewImage"
          >
            删除
          </VanButton>
        </div>
      </template>
    </VanImagePreview>
  </CardContainer>
</template>

<style lang="less" scoped>
.grid-file-uploader {
  &__description {
    font-size: 14px;
    color: #666;
    margin: 0 0 16px 0;
    padding: 0 16px;
  }

  &__progress {
    font-size: 12px;
    color: #999;
    margin: 0;
  }

  &__grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
    padding: 0 16px 16px 16px;

    @media screen and (max-width: 768px) {
      grid-template-columns: repeat(2, 1fr);
      gap: 12px;
      padding: 0 12px 12px 12px;
    }

    @media screen and (max-width: 480px) {
      grid-template-columns: repeat(2, 1fr);
      gap: 10px;
      padding: 0 10px 10px 10px;
    }
  }

  &__item {
    position: relative;
    border: 2px dashed #d9d9d9;
    border-radius: 8px;
    background: #fafafa;
    transition: all 0.3s ease;
    min-height: 120px;
    height: 120px;

    &:hover {
      border-color: #40a9ff;
      background: #f0f7ff;
    }

    &--required {
      border-color: #ff7875;
      background: #fff2f0;
    }

    &--completed {
      border-color: #52c41a;
      background: #f6ffed;
    }

    &--pending {
      border-color: #faad14;
      background: #fffbe6;
    }

    @media screen and (max-width: 768px) {
      min-height: 110px;
      height: 110px;
    }

    @media screen and (max-width: 480px) {
      min-height: 100px;
      height: 100px;
    }
  }

  &__item-required {
    position: absolute;
    top: -8px;
    right: -8px;
    background: #ff9500;
    color: #fff;
    font-size: 12px;
    font-weight: bold;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2;
    line-height: 1;
    box-shadow: 0 2px 4px rgba(255, 149, 0, 0.3);

    @media screen and (max-width: 480px) {
      font-size: 11px;
      width: 20px;
      height: 20px;
      top: -6px;
      right: -6px;
    }
  }

  &__item-success {
    position: absolute;
    top: 4px;
    right: 4px;
    color: #52c41a;
    font-size: 16px;
    z-index: 2;
  }

  &__item-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 16px 12px;
    height: 100%;
    cursor: pointer;
    position: relative;

    @media screen and (max-width: 768px) {
      padding: 14px 10px;
    }

    @media screen and (max-width: 480px) {
      padding: 12px 8px;
    }
  }

  &__item-input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
  }

  &__item-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 8px;

    @media screen and (max-width: 768px) {
      margin-bottom: 6px;
    }

    @media screen and (max-width: 480px) {
      margin-bottom: 5px;
    }
  }

  &__icon {
    width: 36px;
    height: 36px;
    display: block;

    @media screen and (max-width: 768px) {
      width: 32px;
      height: 32px;
    }

    @media screen and (max-width: 480px) {
      width: 28px;
      height: 28px;
    }
  }

  &__item-title {
    font-size: 14px;
    font-weight: 500;
    color: #333;
    margin-bottom: 4px;
    text-align: center;
    line-height: 1.2;

    @media screen and (max-width: 768px) {
      font-size: 13px;
      margin-bottom: 3px;
    }

    @media screen and (max-width: 480px) {
      font-size: 12px;
      margin-bottom: 3px;
    }
  }

  &__item-desc {
    font-size: 12px;
    color: #666;
    text-align: center;
    margin-bottom: 8px;
    line-height: 1.2;

    @media screen and (max-width: 768px) {
      font-size: 11px;
      margin-bottom: 6px;
    }

    @media screen and (max-width: 480px) {
      font-size: 10px;
      margin-bottom: 5px;
    }
  }

  &__item-count {
    font-size: 14px;
    font-weight: 600;
    color: #1890ff;

    &-min {
      color: #999;
      font-weight: normal;
    }
  }

  &__item-files {
    position: absolute;
    bottom: 8px;
    left: 8px;
    right: 8px;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    max-height: 40px;
    overflow: hidden;
  }

  &__file-preview {
    position: relative;
    width: 32px;
    height: 32px;
    border-radius: 4px;
    overflow: hidden;
    border: 1px solid #d9d9d9;
  }

  &__file-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  &__file-icon {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    background: #f5f5f5;
  }

  &__file-remove {
    position: absolute;
    top: -4px;
    right: -4px;
    background: #ff4d4f;
    color: #fff;
    border-radius: 50%;
    font-size: 12px;
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 3;

    &:hover {
      background: #ff7875;
    }
  }

  &__file-loading {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
  }

  // 浮动按钮样式
  &__floating-buttons {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    gap: 12px;
    background: rgba(255, 255, 255, 0.95);
    padding: 16px;
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
    backdrop-filter: blur(10px);
    z-index: 10;
    animation: fadeInScale 0.3s ease-out;

    @media screen and (max-width: 480px) {
      gap: 8px;
      padding: 12px;
      border-radius: 10px;
    }
  }

  &__floating-btn {
    min-width: 60px;
    height: 36px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 500;
    transition: all 0.2s ease;

    &:hover {
      transform: translateY(-1px);
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    }

    @media screen and (max-width: 480px) {
      min-width: 50px;
      height: 32px;
      font-size: 12px;
    }
  }

  // 动画效果
  @keyframes fadeInScale {
    from {
      opacity: 0;
      transform: translate(-50%, -50%) scale(0.8);
    }
    to {
      opacity: 1;
      transform: translate(-50%, -50%) scale(1);
    }
  }
}
</style>
