<template>
  <div class="mobile-id-upload">
    <!-- 顶部导航 -->
    <div class="nav-bar">
      <div class="nav-back" @click="goBack">
        <el-icon><ArrowLeft /></el-icon>
      </div>
      <h1 class="nav-title">证件上传</h1>
      <div class="nav-placeholder"></div>
    </div>

    <!-- 步骤指示 -->
    <!--        <div class="step-bar">-->
    <!--            <div class="step-item" :class="{ active: step >= 1 }">-->
    <!--                <div class="step-num">1</div>-->
    <!--                <span>正面</span>-->
    <!--            </div>-->
    <!--            <div class="step-line" :class="{ active: step >= 2 }"></div>-->
    <!--            <div class="step-item" :class="{ active: step >= 2 }">-->
    <!--                <div class="step-num">2</div>-->
    <!--                <span>反面</span>-->
    <!--            </div>-->
    <!--            <div class="step-line" :class="{ active: step >= 3 }"></div>-->
    <!--            <div class="step-item" :class="{ active: step >= 3 }">-->
    <!--                <div class="step-num">3</div>-->
    <!--                <span>确认</span>-->
    <!--            </div>-->
    <!--        </div>-->
    <div class="content-box">
      <!-- 证件类型 -->
      <div class="type-selector">
        <div
          class="type-item"
          :class="{ active: form.idType === 'idcard' }"
          @click="switchType('idcard')"
        >
          <el-icon><Postcard /></el-icon>
          <span>身份证</span>
        </div>
        <div
          class="type-item"
          :class="{ active: form.idType === 'passport' }"
          @click="switchType('passport')"
        >
          <el-icon><Ticket /></el-icon>
          <span>护照</span>
        </div>
      </div>

      <!-- 拍摄提示 -->
      <div class="shoot-tips">
        <div class="tips-title">
          <el-icon><InfoFilled /></el-icon>
          拍摄要求
        </div>
        <div class="tips-grid">
          <div class="tip-item">
            <div class="tip-icon">📷</div>
            <span>光线充足</span>
          </div>
          <div class="tip-item">
            <div class="tip-icon">⬜</div>
            <span>背景纯色</span>
          </div>
          <div class="tip-item">
            <div class="tip-icon">✋</div>
            <span>手持平稳</span>
          </div>
          <div class="tip-item">
            <div class="tip-icon">🔍</div>
            <span>文字清晰</span>
          </div>
        </div>
      </div>

      <!-- 上传区域 -->
      <div class="upload-section">
        <!-- 正面 -->
        <div class="upload-card" :class="{ uploaded: form.frontImage }">
          <div class="card-label">
            <span class="label-tag">必传</span>
            {{ frontLabel }}
          </div>

          <div
            class="upload-area"
            @click="handleClickUpload('front')"
            @touchstart="touchStart"
            @touchend="touchEndFront"
          >
            <input
              ref="frontInputRef"
              type="file"
              accept="image/*"
              style="display: none"
              @change="(e: Event) => handleFileChange(e, 'front')"
            />

            <template v-if="form.frontImage">
              <div class="preview-wrap">
                <img
                  :src="form.frontPreview"
                  alt="正面"
                  @click.stop="previewImage(form.frontPreview)"
                />
                <div class="preview-mask" @click.stop>
                  <el-icon @click="previewImage(form.frontPreview)"><ZoomIn /></el-icon>
                  <el-icon @click="removeImage('front')"><Delete /></el-icon>
                </div>
              </div>
            </template>

            <template v-else>
              <div class="upload-inner" :class="{ pressing: frontPressing }">
                <div class="camera-icon">
                  <el-icon><Camera /></el-icon>
                  <div class="camera-ring"></div>
                </div>
                <p class="upload-title">点击拍照或选择相册</p>
                <p class="upload-desc">支持 JPG、PNG，最大 5MB</p>
              </div>
            </template>
          </div>
        </div>

        <!-- 反面 -->
        <div class="upload-card" :class="{ uploaded: form.backImage }">
          <div class="card-label">
            <span class="label-tag">必传</span>
            {{ backLabel }}
          </div>

          <div
            class="upload-area"
            @click="handleClickUpload('back')"
            @touchstart="touchStartBack"
            @touchend="touchEndBack"
          >
            <input
              ref="backInputRef"
              type="file"
              accept="image/*"
              style="display: none"
              @change="(e: Event) => handleFileChange(e, 'back')"
            />

            <template v-if="form.backImage">
              <div class="preview-wrap">
                <img
                  :src="form.backPreview"
                  alt="反面"
                  @click.stop="previewImage(form.backPreview)"
                />
                <div class="preview-mask" @click.stop>
                  <el-icon @click="previewImage(form.backPreview)"><ZoomIn /></el-icon>
                  <el-icon @click="removeImage('back')"><Delete /></el-icon>
                </div>
              </div>
            </template>

            <template v-else>
              <div class="upload-inner" :class="{ pressing: backPressing }">
                <div class="camera-icon">
                  <el-icon><Camera /></el-icon>
                  <div class="camera-ring"></div>
                </div>
                <p class="upload-title">点击拍照或选择相册</p>
                <p class="upload-desc">支持 JPG、PNG，最大 5MB</p>
              </div>
            </template>
          </div>
        </div>
      </div>
    </div>

    <!-- 底部提交 -->
    <div class="bottom-bar">
      <el-button
        class="submit-btn"
        type="primary"
        size="large"
        :loading="submitting"
        :disabled="!isReady"
        @click="handleSubmit"
      >
        {{ isReady ? '提交审核' : `请上传${!form.frontImage ? '正面' : '反面'}照片` }}
      </el-button>
    </div>

    <!-- 大图预览 -->
    <el-dialog
      v-model="previewVisible"
      :show-close="false"
      width="90%"
      class="preview-dialog"
      destroy-on-close
    >
      <img :src="previewUrl" class="preview-img" alt="preview" />
      <div class="preview-close" @click="previewVisible = false">
        <el-icon><Close /></el-icon>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  ArrowLeft,
  Postcard,
  Ticket,
  Camera,
  ZoomIn,
  Delete,
  InfoFilled,
  Close,
} from '@element-plus/icons-vue'
import { uploadCard } from '@/api/modules/livenessVerification'
import { useUserStore } from '@/stores/modules/user'

/* ==================== 类型定义 ==================== */

/** 证件类型 */
type IdType = 'idcard' | 'passport'

/** 照片面类型 */
type PhotoSide = 'front' | 'back'

/** 证件表单数据 */
interface IdForm {
  idType: IdType
  frontImage: File | null
  frontPreview: string
  backImage: File | null
  backPreview: string
}

/** 提交载荷 */
interface SubmitPayload {
  idType: IdType
  frontImage: File
  backImage: File
}

/** 上传错误类型 */
interface UploadError {
  side: PhotoSide
  message: string
}

/* ==================== 常量配置 ==================== */

const MAX_SIZE_MB = 5 // 最大文件大小（MB）

/* ==================== 响应式数据 ==================== */

const router = useRouter()

const form = reactive<IdForm>({
  idType: 'idcard',
  frontImage: null,
  frontPreview: '',
  backImage: null,
  backPreview: '',
})

const errors = reactive<Record<PhotoSide, string>>({
  front: '',
  back: '',
})

const frontInputRef = ref<HTMLInputElement | null>(null)
const backInputRef = ref<HTMLInputElement | null>(null)

const submitting = ref<boolean>(false)
const previewVisible = ref<boolean>(false)
const previewUrl = ref<string>('')

const frontPressing = ref<boolean>(false)
const backPressing = ref<boolean>(false)

let touchTimer: ReturnType<typeof setTimeout> | null = null
// 标记是否已通过触摸事件处理（防止 touchEnd 和 click 双重触发）
let touchedFront = false
let touchedBack = false

/* ==================== 计算属性 ==================== */

const step = computed<number>(() => {
  if (form.frontImage && form.backImage) return 3
  if (form.frontImage || form.backImage) return 2
  return 1
})

const frontLabel = computed<string>(() =>
  form.idType === 'idcard' ? '身份证人像面' : '护照个人信息页',
)

const backLabel = computed<string>(() =>
  form.idType === 'idcard' ? '身份证国徽面' : '护照封底/签证页',
)

const isReady = computed<boolean>(() => Boolean(form.frontImage && form.backImage))

const maxSizeBytes = computed<number>(() => MAX_SIZE_MB * 1024 * 1024)

/* ==================== 方法 ==================== */

/**
 * 切换证件类型
 * @param type - 目标证件类型
 */
const switchType = async (type: IdType): Promise<void> => {
  if (form.frontImage || form.backImage) {
    try {
      await ElMessageBox.confirm('切换证件类型将清空已上传照片，是否继续？', '提示', {
        confirmButtonText: '继续',
        cancelButtonText: '取消',
        type: 'warning',
      })
      resetAll()
      form.idType = type
    } catch {
      // 用户取消，不做任何操作
    }
  } else {
    form.idType = type
  }
}

/** 重置所有数据 */
const resetAll = (): void => {
  if (form.frontPreview) URL.revokeObjectURL(form.frontPreview)
  if (form.backPreview) URL.revokeObjectURL(form.backPreview)
  form.frontImage = null
  form.frontPreview = ''
  form.backImage = null
  form.backPreview = ''
  errors.front = ''
  errors.back = ''
  if (frontInputRef.value) frontInputRef.value.value = ''
  if (backInputRef.value) backInputRef.value.value = ''
}

/**
 * 触发文件选择
 * @param side - 正面或反面
 */
const triggerUpload = (side: PhotoSide): void => {
  const input = side === 'front' ? frontInputRef.value : backInputRef.value
  input?.click()
}

/**
 * 点击上传（带触摸防抖）
 * 移动端：touchEnd 已处理 → touched=true → click 跳过
 * 桌面端：无 touch 事件 → touched=false → click 正常执行
 */
const handleClickUpload = (side: PhotoSide): void => {
  const isTouched = side === 'front' ? touchedFront : touchedBack
  if (isTouched) {
    // 已经被 touchEnd 处理过了，跳过
    return
  }
  // 桌面端或未经过触摸的情况，正常触发
  triggerUpload(side)
}

/* ---------- 触摸反馈 ---------- */

const touchStart = (): void => {
  frontPressing.value = true
  touchedFront = true // 标记正面已触摸
  if (touchTimer) clearTimeout(touchTimer)
}

/** 正面：触摸结束 → 触发上传 */
const touchEndFront = (): void => {
  frontPressing.value = true
  triggerUpload('front')

  touchTimer = setTimeout(() => {
    frontPressing.value = false
    touchedFront = false // 延迟重置，允许下一次操作
  }, 300) // 300ms > 浏览器 click 延迟
}

const touchStartBack = (): void => {
  backPressing.value = true
  touchedBack = true // 标记反面已触摸
  if (touchTimer) clearTimeout(touchTimer)
}

/** 反面：触摸结束 → 触发上传 */
const touchEndBack = (): void => {
  backPressing.value = true
  triggerUpload('back')

  touchTimer = setTimeout(() => {
    backPressing.value = false
    touchedBack = false // 延迟重置，允许下一次操作
  }, 300) // 300ms > 浏览器 click 延迟
}

/* ---------- 图片处理 ---------- */

/**
 * 验证文件
 * @param file - 待验证文件
 * @param side - 上传面
 * @returns 是否通过验证
 */
const validateFile = (file: File, side: PhotoSide): boolean => {
  errors[side] = ''

  if (!file.type.startsWith('image/')) {
    errors[side] = '仅支持图片文件'
    ElMessage.error('请选择图片文件')
    return false
  }

  if (file.size > maxSizeBytes.value) {
    errors[side] = `文件大小不能超过 ${MAX_SIZE_MB}MB`
    ElMessage.error(`文件过大，最大支持 ${MAX_SIZE_MB}MB`)
    return false
  }

  return true
}

/**
 * 处理文件选择变化
 * @param event - 输入事件
 * @param side - 上传面
 */
const handleFileChange = async (event: Event, side: PhotoSide): Promise<void> => {
  const target = event.target as HTMLInputElement
  const file = target.files?.[0]
  if (!file) return

  if (!validateFile(file, side)) {
    target.value = ''
    return
  }

  try {
    // 创建预览 URL
    const previewUrl = URL.createObjectURL(file)

    if (side === 'front') {
      // 释放旧的预览 URL
      if (form.frontPreview) URL.revokeObjectURL(form.frontPreview)
      form.frontImage = file
      form.frontPreview = previewUrl
    } else {
      if (form.backPreview) URL.revokeObjectURL(form.backPreview)
      form.backImage = file
      form.backPreview = previewUrl
    }
  } catch (err) {
    const errorMsg = err instanceof Error ? err.message : '图片处理失败'
    ElMessage.error(errorMsg)
  } finally {
    target.value = ''
  }
}

/**
 * 删除已上传图片
 * @param side - 要删除的面
 */
const removeImage = async (side: PhotoSide): Promise<void> => {
  try {
    await ElMessageBox.confirm('确定删除这张照片？', '删除确认', {
      confirmButtonText: '删除',
      cancelButtonText: '保留',
      type: 'warning',
    })

    if (side === 'front') {
      if (form.frontPreview) URL.revokeObjectURL(form.frontPreview)
      form.frontImage = null
      form.frontPreview = ''
    } else {
      if (form.backPreview) URL.revokeObjectURL(form.backPreview)
      form.backImage = null
      form.backPreview = ''
    }

    const input = side === 'front' ? frontInputRef.value : backInputRef.value
    if (input) input.value = ''
    ElMessage.success('已删除')
  } catch {
    // 取消删除
  }
}

/**
 * 预览图片
 * @param url - 图片地址
 */
const previewImage = (url: string): void => {
  previewUrl.value = url
  previewVisible.value = true
}

/** 提交表单 */
const handleSubmit = async (): Promise<void> => {
  if (!isReady.value) return

  submitting.value = true
  try {
    const formData = new FormData()
    formData.append('type', form.idType === 'idcard' ? '1' : '2')
    formData.append('card_1', form.frontImage!)
    formData.append('card_2', form.backImage!)

    await uploadCard(formData)

    router.push('/livenessVerification')
  } catch (err) {
    const errorMsg = err instanceof Error ? err.message : '提交失败'
    ElMessage.error(errorMsg)
  } finally {
    submitting.value = false
  }
}

/** 返回上一页 */
const goBack = (): void => {
  const userStore = useUserStore() 
  // real_check === 1 表示未认证状态，real_check !== 1 表示已认证
  const isRealNameVerified = userStore.userInfo?.real_check !== 1
  console.log('real_check value:', userStore.userInfo?.real_check, 'isRealNameVerified:', isRealNameVerified)

  if (form.frontImage || form.backImage) {
    ElMessageBox.confirm('退出将丢失已上传的照片，是否继续？', '提示', {
      confirmButtonText: '退出',
      cancelButtonText: '留在页面',
      type: 'warning',
    })
      .then(() => {
        // 清理预览 URL
        if (form.frontPreview) URL.revokeObjectURL(form.frontPreview)
        if (form.backPreview) URL.revokeObjectURL(form.backPreview)

        if (isRealNameVerified) {
          console.log('已认证用户可以返回上一页')
          // 已认证用户可以返回上一页
          router.back()
        } else {
          // 未认证用户跳转到登录页
          console.log('未实名验证只能去登录页')
          router.push('/user/login')
        }
      })
      .catch(() => { })
  } else {
    if (isRealNameVerified) {
      console.log('已认证用户可以返回上一页')
      // 已认证用户可以返回上一页
      router.back()
    } else {
      // 未认证用户跳转到登录页
      console.log('未实名验证只能去登录页')
      router.push('/user/login')
    }
  }
}
</script>

<style scoped lang="scss">
.mobile-id-upload {
  width: 100vw;
  min-height: 100vh;
  background: #f5f6fa;
  padding-bottom: 100px;
  -webkit-tap-highlight-color: transparent;
  display: flex;
  flex-direction: column;
  align-items: center;
}

// ========== 导航栏 ==========
.nav-bar {
  width: 100%;
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 44px;
  padding: 0 16px;
  background: #fff;
  border-bottom: 1px solid #f0f0f0;

  .nav-back {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    color: #333;
    border-radius: 50%;

    &:active {
      background: #f5f5f5;
    }
  }

  .nav-title {
    font-size: 17px;
    font-weight: 600;
    color: #1a1a1a;
  }

  .nav-placeholder {
    width: 32px;
  }
}

.content-box {
  width: 100%;
  height: 100%;
  margin: 0 auto;
  overflow-y: auto;
}

// ========== 步骤条 ==========
.step-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px 24px;
  background: #fff;
  margin-bottom: 12px;

  .step-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;

    .step-num {
      width: 28px;
      height: 28px;
      border-radius: 50%;
      background: #e4e7ed;
      color: #909399;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 13px;
      font-weight: 600;
      transition: all 0.3s;
    }

    span {
      font-size: 12px;
      color: #909399;
    }

    &.active {
      .step-num {
        background: var(--el-color-primary);
        color: #fff;
      }

      span {
        color: var(--el-color-primary);
        font-weight: 500;
      }
    }
  }

  .step-line {
    width: 40px;
    height: 2px;
    background: #e4e7ed;
    margin: 0 12px;
    margin-bottom: 20px;
    transition: all 0.3s;

    &.active {
      background: var(--el-color-primary);
    }
  }
}

// ========== 证件类型选择 ==========
.type-selector {
  display: flex;
  gap: 12px;
  padding: 0 16px;
  margin-top: 16px;
  margin-bottom: 16px;

  .type-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 16px 0;
    background: #fff;
    border-radius: 12px;
    border: 2px solid transparent;
    transition: all 0.2s;

    .el-icon {
      font-size: 28px;
      color: #909399;
    }

    span {
      font-size: 14px;
      color: #606266;
    }

    &.active {
      border-color: var(--el-color-primary);
      background: var(--el-color-primary-light-9);

      .el-icon,
      span {
        color: var(--el-color-primary);
      }
    }

    &:active {
      transform: scale(0.98);
    }
  }
}

// ========== 上传卡片 ==========
.upload-section {
  padding: 0 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.upload-card {
  background: #fff;
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);

  &.uploaded {
    .upload-area {
      border-color: var(--el-color-success);
      background: var(--el-color-success-light-9);
    }
  }
}

.card-label {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-size: 15px;
  font-weight: 600;
  color: #1a1a1a;

  .label-tag {
    font-size: 11px;
    padding: 2px 6px;
    background: var(--el-color-danger-light-9);
    color: var(--el-color-danger);
    border-radius: 4px;
    font-weight: 500;
  }
}

// ========== 上传区域 ==========
.upload-area {
  width: 100%;
  aspect-ratio: 1.6;
  border-radius: 12px;
  border: 2px dashed #dcdfe6;
  background: #fafbfc;
  overflow: hidden;
  position: relative;
  transition: all 0.2s;

  &:active {
    border-color: var(--el-color-primary);
    background: var(--el-color-primary-light-9);
  }
}

.upload-inner {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: transform 0.1s;

  &.pressing {
    transform: scale(0.96);
  }

  .camera-icon {
    position: relative;
    width: 64px;
    height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;

    .el-icon {
      font-size: 36px;
      color: var(--el-color-primary);
      z-index: 2;
    }

    .camera-ring {
      position: absolute;
      inset: 0;
      border-radius: 50%;
      border: 2px solid var(--el-color-primary-light-5);
      animation: pulse 2s infinite;
    }
  }

  .upload-title {
    font-size: 15px;
    color: #303133;
    font-weight: 500;
    margin: 0;
  }

  .upload-desc {
    font-size: 12px;
    color: #909399;
    margin: 0;
  }
}

@keyframes pulse {

  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }

  50% {
    transform: scale(1.1);
    opacity: 0.6;
  }
}

// ========== 预览 ==========
.preview-wrap {
  width: 100%;
  height: 100%;
  position: relative;

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  .preview-mask {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    opacity: 0;
    transition: opacity 0.2s;

    .el-icon {
      font-size: 28px;
      color: #fff;
      padding: 12px;
      border-radius: 50%;
      background: rgba(255, 255, 255, 0.2);
    }
  }

  &:active .preview-mask {
    opacity: 1;
  }
}

// ========== 拍摄提示 ==========
.shoot-tips {
  margin: 16px;
  padding: 16px;
  background: #fff;
  border-radius: 16px;

  .tips-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 600;
    color: #303133;
    margin-bottom: 12px;

    .el-icon {
      color: var(--el-color-primary);
    }
  }

  .tips-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;

    .tip-item {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 6px;

      .tip-icon {
        font-size: 24px;
      }

      span {
        font-size: 12px;
        color: #606266;
      }
    }
  }
}

// ========== 底部提交 ==========
.bottom-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 12px 16px 24px;
  background: #fff;
  border-top: 1px solid #f0f0f0;
  z-index: 100;

  .submit-btn {
    width: 100%;
    height: 48px;
    font-size: 16px;
    font-weight: 600;
    border-radius: 24px;

    &:disabled {
      background: #c0c4cc;
      border-color: #c0c4cc;
    }
  }
}

// ========== 预览弹窗 ==========
.preview-dialog {
  :deep(.el-dialog) {
    border-radius: 12px;
    overflow: hidden;
    margin-top: 15vh !important;
  }

  :deep(.el-dialog__body) {
    padding: 0;
  }

  .preview-img {
    width: 100%;
    display: block;
  }

  .preview-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 20px;
  }
}

// ========== 加载遮罩 ==========
.loading-mask {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  color: #fff;
  z-index: 9999;

  .loading-icon {
    font-size: 32px;
    animation: rotate 1s linear infinite;
  }
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

// ========== 适配安全区 ==========
@supports (padding-bottom: env(safe-area-inset-bottom)) {
  .bottom-bar {
    padding-bottom: calc(24px + env(safe-area-inset-bottom));
  }

  .mobile-id-upload {
    padding-bottom: calc(100px + env(safe-area-inset-bottom));
  }
}
</style>
