<script setup lang="ts">
import { nextTick, onMounted, reactive, ref } from 'vue'
import type { UploadProps, UploadUserFile } from 'element-plus'
import {
  ElButton,
  ElCard,
  ElDialog,
  ElForm,
  ElFormItem,
  ElInput,
  ElInputNumber,
  ElMessage,
  ElMessageBox,
  ElOption,
  ElPagination,
  ElSelect,
  ElSpace,
  ElTable,
  ElTableColumn,
  ElTag,
  ElUpload,
} from 'element-plus'
import {
  AlertCircle,
  Download,
  Eye,
  FileText,
  Plus,
  Receipt,
  RefreshCw,
  RotateCcw,
  Search,
  Upload,
} from 'lucide-vue-next'
import { renderAsync } from 'docx-preview'
import VuePdfEmbed from 'vue-pdf-embed'
import { clientGet, clientPost } from '@/utils/request.ts'

// 接口定义
export interface AContractInfo {
  id: string
  simplifiedHouseId: string
  contractNumber: string
  contractDate: string
  contractTime: string
  contractExpirationDate: string
  contractDeposit: number
  contractStatus: string
  originalContractUrl: string
  signContractUrl: string
  createTime: string
  updateTime: string
}

interface AContractInfoListResponse extends BaseResponse {
  data: PageType<AContractInfo>
}

interface CanBeReceiptDataReponse extends BaseResponse {
  data: {
    zj: number //租金
    yj: number //押金
    jkdw: string //交款单位
  }
}

interface ReceiptDto {
  paymentUnit: string // 交款单位
  paymentMethod: string // 付款方式
  rmb: number // 人民币金额
  yj: number // 押金
  zj: number // 租金
  wyf: number // 物业费
  sf: number // 水费
  paymentReason: string // 付款事由
}

interface CanBeReturnReceiptDataReponse extends BaseResponse {
  data: {
    zh: string //租户
    yj: number //押金
  }
}

interface ReturnReceiptDto {
  dw: string // 单位
  rmb: number // 人民币金额
  yj: number // 押金
  zj: number // 租金
  wyf: number // 物业费
  zh: string // 租户
}

// 文件类型枚举
enum FileType {
  DOCX = 'docx',
  PDF = 'pdf',
  JPG = 'jpg',
  PNG = 'png',
}

// 响应式数据
const loading = ref(false)
const tableData = ref<AContractInfo[]>([])
const total = ref(0)
const currentPage = ref(1)
const pageSize = ref(10)
const MINIO_URL = import.meta.env.VITE_MINIO_BASE_URL

// 搜索表单
const searchForm = reactive({
  contractNumber: '',
})

// 预览相关
const previewVisible = ref(false)
const previewLoading = ref(false)
const previewTitle = ref('')
const previewContainer = ref<HTMLElement>()
const previewFileType = ref<FileType>(FileType.DOCX)
const previewFileUrl = ref('')
const previewRelativeUrl = ref('') // 新增：存储相对路径用于下载

// PDF预览相关
const pdfSource = ref('')
const pdfCurrentPage = ref(1)
const pdfTotalPages = ref(0)
const pdfScale = ref(1.0)

// 上传相关
const uploadVisible = ref(false)
const uploadLoading = ref(false)
const currentContractId = ref('')
const currentContractNumber = ref('')
const fileList = ref<UploadUserFile[]>([])

// 收据相关
const receiptVisible = ref(false)
const receiptLoading = ref(false)
const receiptGenerating = ref(false)
const currentReceiptContractId = ref('')
const currentReceiptContractNumber = ref('')

// 收据表单数据
const receiptForm = reactive<ReceiptDto>({
  paymentUnit: '',
  paymentMethod: '转账',
  rmb: 0,
  yj: 0,
  zj: 0,
  wyf: 0,
  sf: 0,
  paymentReason: '房屋租赁费用',
})

// 退据相关
const returnReceiptVisible = ref(false)
const returnReceiptLoading = ref(false)
const returnReceiptGenerating = ref(false)
const currentReturnReceiptContractId = ref('')
const currentReturnReceiptContractNumber = ref('')

// 退据表单数据
const returnReceiptForm = reactive<ReturnReceiptDto>({
  dw: '',
  rmb: 0,
  yj: 0,
  zj: 0,
  wyf: 0,
  zh: '',
})

// 付款方式选项
const paymentMethods = [
  { label: '转账', value: '转账' },
  { label: '扫码', value: '扫码' },
  { label: '其他', value: '其他' },
]

// 付款事由选项
const paymentReasons = [
  { label: '房屋租赁费用', value: '房屋租赁费用' },
  { label: '押金', value: '押金' },
  { label: '物业费', value: '物业费' },
  { label: '水电费', value: '水电费' },
  { label: '其他费用', value: '其他费用' },
]

// 获取文件类型
const getFileType = (url: string): FileType => {
  const extension = url.split('.').pop()?.toLowerCase()
  switch (extension) {
    case 'pdf':
      return FileType.PDF
    case 'jpg':
    case 'jpeg':
      return FileType.JPG
    case 'png':
      return FileType.PNG
    case 'docx':
    default:
      return FileType.DOCX
  }
}

// 获取合同状态标签类型
const getStatusType = (status: string) => {
  const statusMap: Record<string, string> = {
    有效: 'success',
    已退租: 'warning',
  }
  return statusMap[status] || 'info'
}

// 获取列表数据
const getList = async () => {
  loading.value = true
  try {
    const response = await clientGet<
      {
        pageNum: number
        pageSize: number
        contractNumber: string
      },
      AContractInfoListResponse
    >('/acontractInfo/findByPage', {
      params: {
        pageNum: currentPage.value,
        pageSize: pageSize.value,
        contractNumber: searchForm.contractNumber,
      },
    })
    if (response.code === 200 && response.data) {
      tableData.value = response.data.records
      total.value = response.data.total
      currentPage.value = response.data.current || 1
    } else {
      ElMessage.error(response.msg || '获取数据失败')
    }
  } catch (error) {
    ElMessage.error('网络请求失败')
    console.error('获取合同列表失败:', error)
  } finally {
    loading.value = false
  }
}

// 搜索
const handleSearch = () => {
  currentPage.value = 1
  getList()
}

// 重置搜索
const handleReset = () => {
  searchForm.contractNumber = ''
  currentPage.value = 1
  getList()
}

// 分页变化
const handleCurrentChange = (page: number) => {
  currentPage.value = page
  getList()
}

const handleSizeChange = (size: number) => {
  pageSize.value = size
  currentPage.value = 1
  getList()
}

// 预览文档
const previewDocument = async (url: string, title: string) => {
  const fullUrl = MINIO_URL + url
  if (!url) {
    ElMessage.warning('文档地址为空，无法预览')
    return
  }

  previewTitle.value = title
  previewFileUrl.value = fullUrl
  previewRelativeUrl.value = url // 存储相对路径用于下载
  previewFileType.value = getFileType(url)
  previewVisible.value = true
  previewLoading.value = true

  // 重置PDF相关状态
  if (previewFileType.value === FileType.PDF) {
    pdfCurrentPage.value = 1
    pdfTotalPages.value = 0
    pdfScale.value = 1.0
    pdfSource.value = fullUrl
  }

  await nextTick()

  try {
    if (previewFileType.value === FileType.DOCX) {
      await previewDocx(fullUrl)
    } else if (previewFileType.value === FileType.JPG || previewFileType.value === FileType.PNG) {
      await previewImage(fullUrl)
    }
    // PDF预览由vue-pdf-embed组件自动处理
  } catch (error) {
    ElMessage.error('文档预览失败: ' + (error as Error).message)
    console.error('文档预览失败:', error)
  } finally {
    previewLoading.value = false
  }
}

// 预览DOCX文档
const previewDocx = async (url: string) => {
  const response = await fetch(url)
  if (!response.ok) {
    throw new Error('文档加载失败')
  }
  const arrayBuffer = await response.arrayBuffer()
  if (previewContainer.value) {
    previewContainer.value.innerHTML = ''
    await renderAsync(arrayBuffer, previewContainer.value, undefined, {
      className: 'docx-preview',
      inWrapper: true,
      ignoreWidth: false,
      ignoreHeight: false,
      ignoreFonts: false,
      breakPages: true,
      ignoreLastRenderedPageBreak: true,
      experimental: false,
      trimXmlDeclaration: true,
      useBase64URL: false,
      renderChanges: false,
      renderComments: false,
      renderEndnotes: true,
      renderFootnotes: true,
      renderFooters: true,
      renderHeaders: true,
    })
  }
}

// 预览图片
const previewImage = async (url: string) => {
  if (previewContainer.value) {
    previewContainer.value.innerHTML = `
      <div class="flex justify-center items-center h-full">
        <img
          src="${url}"
          alt="预览图片"
          class="max-w-full max-h-full object-contain"
          style="max-height: 600px;"
        />
      </div>
    `
  }
}

// PDF相关方法
const onPdfLoaded = (pdf: any) => {
  pdfTotalPages.value = pdf.numPages
  previewLoading.value = false
}

const onPdfError = (error: any) => {
  console.error('PDF加载失败:', error)
  ElMessage.error('PDF文档加载失败')
  previewLoading.value = false
}

const pdfPrevPage = () => {
  if (pdfCurrentPage.value > 1) {
    pdfCurrentPage.value--
  }
}

const pdfNextPage = () => {
  if (pdfCurrentPage.value < pdfTotalPages.value) {
    pdfCurrentPage.value++
  }
}

const pdfZoomIn = () => {
  if (pdfScale.value < 3) {
    pdfScale.value += 0.2
  }
}

const pdfZoomOut = () => {
  if (pdfScale.value > 0.4) {
    pdfScale.value -= 0.2
  }
}

const pdfResetZoom = () => {
  pdfScale.value = 1.0
}

// 下载文档
const downloadDocument = (url: string, filename: string) => {
  const fullUrl = MINIO_URL + url
  if (!url) {
    ElMessage.warning('文档地址为空，无法下载')
    return
  }

  const link = document.createElement('a')
  link.href = fullUrl
  link.download = filename
  link.target = '_blank'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

// 从预览对话框下载文档
const downloadFromPreview = () => {
  if (!previewRelativeUrl.value) {
    ElMessage.warning('文档地址为空，无法下载')
    return
  }
  // 从标题中提取文件名，如果没有则使用默认名称
  const filename = previewTitle.value || '文档'
  downloadDocument(previewRelativeUrl.value, filename)
}

// 打开上传对话框
const openUploadDialog = (contractId: string, contractNumber: string) => {
  currentContractId.value = contractId
  currentContractNumber.value = contractNumber
  fileList.value = []
  uploadVisible.value = true
}

// 文件上传前的检查
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
  const allowedTypes = [
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // docx
    'application/pdf', // pdf
    'image/jpeg', // jpg
    'image/png', // png
  ]
  const allowedExtensions = ['.docx', '.pdf', '.jpg', '.jpeg', '.png']
  const isValidType =
    allowedTypes.includes(file.type) ||
    allowedExtensions.some((ext) => file.name.toLowerCase().endsWith(ext))

  if (!isValidType) {
    ElMessage.error('只能上传 .docx、.pdf、.jpg、.png 格式的文件！')
    return false
  }

  const isLt10M = file.size / 1024 / 1024 < 10
  if (!isLt10M) {
    ElMessage.error('文件大小不能超过 10MB！')
    return false
  }

  return true
}

// 文件选择变化
const handleFileChange: UploadProps['onChange'] = (file, fileList) => {
  console.log(file, fileList)
  //移除第一个元素

  if (fileList.length > 1) {
    fileList.splice(0, 1)
    ElMessage.warning('每次只能上传一个文件，已自动替换为最新选择的文件')
    // 确保只保留最新的文件
    // fileList.value = [fileList[fileList.length - 1]]
  } else {
    // fileList = [...fileList]
  }
}

// 移除文件
const handleRemove: UploadProps['onRemove'] = () => {
  fileList.value = []
}

// 上传签约合同
const uploadSignContract = async () => {
  if (fileList.value.length === 0) {
    ElMessage.warning('请选择要上传的文件')
    return
  }

  const file = fileList.value[0].raw
  if (!file) {
    ElMessage.warning('文件无效，请重新选择')
    return
  }

  try {
    await ElMessageBox.confirm(
      `确定要上传合同 ${currentContractNumber.value} 的签约文档吗？`,
      '确认上传',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      },
    )

    uploadLoading.value = true

    const formData = new FormData()
    formData.append('contractId', currentContractId.value)
    formData.append('file', file)

    const response = await clientPost<FormData, BaseResponse>(
      '/acontractInfo/uploadSignContract',
      formData,
      {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      },
    )

    if (response.code === 200) {
      ElMessage.success('签约合同上传成功！')
      uploadVisible.value = false
      fileList.value = []
      await getList()
    } else {
      ElMessage.error(response.msg || '上传失败')
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error('上传失败：' + (error.message || '网络错误'))
      console.error('上传签约合同失败:', error)
    }
  } finally {
    uploadLoading.value = false
  }
}

// 关闭上传对话框
const closeUploadDialog = () => {
  uploadVisible.value = false
  fileList.value = []
  currentContractId.value = ''
  currentContractNumber.value = ''
}

// 获取能获取的收据数据
const getCanBeReceiptData = async (contractId: string) => {
  const res = await clientGet<
    {
      contractId: string
    },
    CanBeReceiptDataReponse
  >('/acontractInfo/canBeDetReceiptData', {
    params: {
      contractId,
    },
  })
  console.log(res) // res的类型就是CanBeReceiptDataReponse
  return res
}

// 获取收据
const gainReceipt = async (contractId: string, dto: ReceiptDto) => {
  const res = await clientPost<ReceiptDto, BaseResponse & { data: string }>(
    '/acontractInfo/getReceipt',
    dto,
    {
      params: {
        contractId: contractId,
      },
    },
  )
  console.log(res) // res.data就是收据的url地址 前面还是要添加MINIO_URL
  return res
}

// 打开收据对话框
const openReceiptDialog = async (contractId: string, contractNumber: string) => {
  currentReceiptContractId.value = contractId
  currentReceiptContractNumber.value = contractNumber
  receiptVisible.value = true
  receiptLoading.value = true

  // 重置表单
  Object.assign(receiptForm, {
    paymentUnit: '',
    paymentMethod: '转账',
    rmb: 0,
    yj: 0,
    zj: 0,
    wyf: 0,
    sf: 0,
    paymentReason: '房屋租赁费用',
  })

  try {
    // 获取可用的收据数据
    const response = await getCanBeReceiptData(contractId)
    if (response.code === 200 && response.data) {
      // 填充表单数据
      receiptForm.paymentUnit = response.data.jkdw || ''
      receiptForm.yj = response.data.yj || 0
      receiptForm.zj = response.data.zj || 0
      // 计算总金额
      calculateTotalAmount()
    } else {
      ElMessage.error(response.msg || '获取收据数据失败')
    }
  } catch (error) {
    ElMessage.error('获取收据数据失败')
    console.error('获取收据数据失败:', error)
  } finally {
    receiptLoading.value = false
  }
}

// 计算总金额
const calculateTotalAmount = () => {
  receiptForm.rmb = receiptForm.yj + receiptForm.zj + receiptForm.wyf + receiptForm.sf
}

// 监听金额变化，自动计算总额
const handleAmountChange = () => {
  calculateTotalAmount()
}

// 生成收据
const generateReceipt = async () => {
  // 表单验证
  if (!receiptForm.paymentUnit.trim()) {
    ElMessage.warning('请填写交款单位')
    return
  }
  if (receiptForm.rmb <= 0) {
    ElMessage.warning('总金额必须大于0')
    return
  }

  try {
    await ElMessageBox.confirm(
      `确定要为合同 ${currentReceiptContractNumber.value} 生成收据吗？`,
      '确认生成收据',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      },
    )

    receiptGenerating.value = true
    const response = await gainReceipt(currentReceiptContractId.value, receiptForm)

    if (response.code === 999) {
      // 收据已存在，让用户选择是否预览
      ElMessage.success('收据已存在！')
      receiptVisible.value = false

      try {
        await ElMessageBox.confirm(
          `合同 ${currentReceiptContractNumber.value} 的收据已存在，是否要预览该收据？`,
          '收据已存在',
          {
            confirmButtonText: '预览收据',
            cancelButtonText: '不预览',
            type: 'info',
          },
        )
        // 用户选择预览
        await previewDocument(response.data, `${currentReceiptContractNumber.value} - 收据`)
      } catch (error) {
        // 用户选择不预览，不做任何操作
        console.log('用户选择不预览收据', error)
      }
    } else if (response.code === 200 && response.data) {
      ElMessage.success('收据生成成功！')
      // 自动预览生成的收据
      const receiptUrl = response.data
      await previewDocument(receiptUrl, `${currentReceiptContractNumber.value} - 收据`)
      // 关闭收据对话框
      receiptVisible.value = false
    } else {
      ElMessage.error(response.msg || '收据生成失败')
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error('收据生成失败：' + (error.message || '网络错误'))
      console.error('收据生成失败:', error)
    }
  } finally {
    receiptGenerating.value = false
  }
}

// 关闭收据对话框
const closeReceiptDialog = () => {
  receiptVisible.value = false
  currentReceiptContractId.value = ''
  currentReceiptContractNumber.value = ''
  // 重置表单
  Object.assign(receiptForm, {
    paymentUnit: '',
    paymentMethod: '转账',
    rmb: 0,
    yj: 0,
    zj: 0,
    wyf: 0,
    sf: 0,
    paymentReason: '房屋租赁费用',
  })
}

// 获取能获取的退据数据
const getCanBeReturnReceiptData = async (contractId: string) => {
  const res = await clientGet<
    {
      contractId: string
    },
    CanBeReturnReceiptDataReponse
  >('/acontractInfo/canBeDetReturnReceiptData', {
    params: {
      contractId,
    },
  })
  console.log(res) // res的类型就是CanBeReturnReceiptDataReponse
  return res
}

// 获取退据
const gainReturnReceipt = async (contractId: string, dto: ReturnReceiptDto) => {
  const res = await clientPost<ReturnReceiptDto, BaseResponse & { data: string }>(
    '/acontractInfo/getReturnReceipt',
    dto,
    {
      params: {
        contractId: contractId,
      },
    },
  )
  console.log(res) // res.data就是退据的url地址 前面还是要添加MINIO_URL
  return res
}

// 打开退据对话框
const openReturnReceiptDialog = async (contractId: string, contractNumber: string) => {
  currentReturnReceiptContractId.value = contractId
  currentReturnReceiptContractNumber.value = contractNumber
  returnReceiptVisible.value = true
  returnReceiptLoading.value = true

  // 重置表单
  Object.assign(returnReceiptForm, {
    dw: '',
    rmb: 0,
    yj: 0,
    zj: 0,
    wyf: 0,
    zh: '',
  })

  try {
    // 获取可用的退据数据
    const response = await getCanBeReturnReceiptData(contractId)
    if (response.code === 200 && response.data) {
      // 填充表单数据
      returnReceiptForm.zh = response.data.zh || ''
      returnReceiptForm.yj = response.data.yj || 0
      // 计算总金额
      calculateReturnTotalAmount()
    } else {
      ElMessage.error(response.msg || '获取退据数据失败')
    }
  } catch (error) {
    ElMessage.error('获取退据数据失败')
    console.error('获取退据数据失败:', error)
  } finally {
    returnReceiptLoading.value = false
  }
}

// 计算退据总金额
const calculateReturnTotalAmount = () => {
  returnReceiptForm.rmb = returnReceiptForm.yj + returnReceiptForm.zj + returnReceiptForm.wyf
}

// 监听退据金额变化，自动计算总额
const handleReturnAmountChange = () => {
  calculateReturnTotalAmount()
}

// 生成退据
const generateReturnReceipt = async () => {
  // 表单验证
  if (!returnReceiptForm.dw.trim()) {
    ElMessage.warning('请填写单位名称')
    return
  }
  if (!returnReceiptForm.zh.trim()) {
    ElMessage.warning('请填写租户名称')
    return
  }
  if (returnReceiptForm.rmb <= 0) {
    ElMessage.warning('总金额必须大于0')
    return
  }

  try {
    await ElMessageBox.confirm(
      `确定要为合同 ${currentReturnReceiptContractNumber.value} 生成退据吗？`,
      '确认生成退据',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      },
    )

    returnReceiptGenerating.value = true
    const response = await gainReturnReceipt(
      currentReturnReceiptContractId.value,
      returnReceiptForm,
    )

    if (response.code === 999) {
      // 退据已存在，让用户选择是否预览
      ElMessage.success('退据已存在！')
      returnReceiptVisible.value = false

      try {
        await ElMessageBox.confirm(
          `合同 ${currentReturnReceiptContractNumber.value} 的退据已存在，是否要预览该退据？`,
          '退据已存在',
          {
            confirmButtonText: '预览退据',
            cancelButtonText: '不预览',
            type: 'info',
          },
        )
        // 用户选择预览
        await previewDocument(response.data, `${currentReturnReceiptContractNumber.value} - 退据`)
      } catch (error) {
        // 用户选择不预览，不做任何操作
        console.log('用户选择不预览退据', error)
      }
    } else if (response.code === 200 && response.data) {
      ElMessage.success('退据生成成功！')
      // 自动预览生成的退据
      const returnReceiptUrl = response.data
      await previewDocument(returnReceiptUrl, `${currentReturnReceiptContractNumber.value} - 退据`)
      // 关闭退据对话框
      returnReceiptVisible.value = false
    } else {
      ElMessage.error(response.msg || '退据生成失败')
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error('退据生成失败：' + (error.message || '网络错误'))
      console.error('退据生成失败:', error)
    }
  } finally {
    returnReceiptGenerating.value = false
  }
}

// 关闭退据对话框
const closeReturnReceiptDialog = () => {
  returnReceiptVisible.value = false
  currentReturnReceiptContractId.value = ''
  currentReturnReceiptContractNumber.value = ''
  // 重置表单
  Object.assign(returnReceiptForm, {
    dw: '',
    rmb: 0,
    yj: 0,
    zj: 0,
    wyf: 0,
    zh: '',
  })
}

// 初始化
onMounted(() => {
  getList()
})
</script>

<template>
  <div class="p-6 bg-gray-50 min-h-screen font-sans">
    <!-- 页面标题 -->
    <div class="mb-6">
      <h1 class="text-2xl font-bold text-gray-800 mb-2">租房合同管理</h1>
      <p class="text-gray-600">管理和查看所有租房合同信息</p>
    </div>

    <!-- 搜索区域 -->
    <ElCard class="mb-6" shadow="never">
      <ElForm :model="searchForm" inline class="bg-gray-50 p-5 rounded-lg">
        <ElFormItem label="合同编号">
          <ElInput
            v-model="searchForm.contractNumber"
            placeholder="请输入合同编号"
            clearable
            class="w-50"
            @keyup.enter="handleSearch"
          />
        </ElFormItem>
        <ElFormItem>
          <ElSpace>
            <ElButton type="primary" :icon="Search" @click="handleSearch">搜索</ElButton>
            <ElButton :icon="RefreshCw" @click="handleReset">重置</ElButton>
          </ElSpace>
        </ElFormItem>
      </ElForm>
    </ElCard>

    <!-- 表格区域 -->
    <ElCard shadow="never" class="rounded-lg overflow-hidden">
      <ElTable
        :data="tableData"
        :loading="loading"
        stripe
        border
        style="width: 100%"
        empty-text="暂无数据"
        class="rounded-lg overflow-hidden"
      >
        <ElTableColumn prop="contractNumber" label="合同编号" width="160" />
        <ElTableColumn prop="contractDate" label="签约日期" width="140" />
        <ElTableColumn prop="contractTime" label="合同期限" width="120" />
        <ElTableColumn prop="contractExpirationDate" label="到期日期" width="140" />
        <ElTableColumn prop="contractDeposit" label="押金(元)" width="140">
          <template #default="{ row }">
            <span class="text-orange-600 font-medium">
              ¥{{ row.contractDeposit.toLocaleString() }}
            </span>
          </template>
        </ElTableColumn>
        <ElTableColumn prop="contractStatus" label="合同状态" width="120">
          <template #default="{ row }">
            <ElTag :type="getStatusType(row.contractStatus)" size="small">
              {{ row.contractStatus }}
            </ElTag>
          </template>
        </ElTableColumn>
        <ElTableColumn label="合同文档" min-width="380">
          <template #default="{ row }">
            <div class="flex flex-col gap-4">
              <div v-if="row.originalContractUrl" class="flex items-center gap-2">
                <FileText class="w-4 h-4 text-blue-500" />
                <span class="text-sm text-gray-600">原合同:</span>
                <ElButton
                  type="primary"
                  size="small"
                  text
                  :icon="Eye"
                  @click="
                    previewDocument(row.originalContractUrl, `${row.contractNumber} - 原合同`)
                  "
                >
                  预览
                </ElButton>
                <ElButton
                  type="success"
                  size="small"
                  text
                  :icon="Download"
                  @click="downloadDocument(row.originalContractUrl, `${row.contractNumber}_原合同`)"
                >
                  下载
                </ElButton>
              </div>
              <div v-else class="text-sm text-gray-400">原合同: 暂无</div>

              <div v-if="row.signContractUrl" class="flex items-center gap-2">
                <FileText class="w-4 h-4 text-green-500" />
                <span class="text-sm text-gray-600">签订合同:</span>
                <ElButton
                  type="primary"
                  size="small"
                  text
                  :icon="Eye"
                  @click="previewDocument(row.signContractUrl, `${row.contractNumber} - 签订合同`)"
                >
                  预览
                </ElButton>
                <ElButton
                  type="success"
                  size="small"
                  text
                  :icon="Download"
                  @click="downloadDocument(row.signContractUrl, `${row.contractNumber}_签订合同`)"
                >
                  下载
                </ElButton>
                <ElButton
                  type="warning"
                  size="small"
                  text
                  :icon="Upload"
                  @click="openUploadDialog(row.id, row.contractNumber)"
                >
                  重新上传
                </ElButton>
              </div>
              <div v-else class="flex items-center gap-2">
                <span class="text-sm text-gray-400">签订合同: 暂无</span>
                <ElButton
                  type="warning"
                  size="small"
                  text
                  :icon="Upload"
                  @click="openUploadDialog(row.id, row.contractNumber)"
                >
                  上传
                </ElButton>
              </div>
            </div>
          </template>
        </ElTableColumn>
        <ElTableColumn label="操作" width="160" fixed="right">
          <template #default="{ row }">
            <div class="flex flex-col gap-1">
              <div>
                <ElButton
                  type="primary"
                  size="small"
                  text
                  :icon="Receipt"
                  @click="openReceiptDialog(row.id, row.contractNumber)"
                >
                  获取收据
                </ElButton>
              </div>
              <div>
                <ElButton
                  type="warning"
                  size="small"
                  text
                  :icon="RotateCcw"
                  @click="openReturnReceiptDialog(row.id, row.contractNumber)"
                >
                  获取退据
                </ElButton>
              </div>
            </div>
          </template>
        </ElTableColumn>
        <ElTableColumn prop="createTime" label="创建时间" width="180" />
        <ElTableColumn prop="updateTime" label="更新时间" width="180" />
      </ElTable>

      <!-- 分页 -->
      <div class="flex justify-center mt-6">
        <ElPagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[10, 20, 50, 100]"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </ElCard>

    <!-- 文档预览对话框 -->
    <ElDialog
      v-model="previewVisible"
      :title="previewTitle"
      width="70%"
      top="5vh"
      destroy-on-close
      class="preview-dialog"
    >
      <!-- 预览对话框标题栏添加下载按钮 -->
      <template #header="{ titleId, titleClass }">
        <div class="flex items-center justify-between w-full">
          <span :id="titleId" :class="titleClass">{{ previewTitle }}</span>
          <ElButton
            type="primary"
            :icon="Download"
            @click="downloadFromPreview"
            :disabled="!previewRelativeUrl"
          >
            下载文档
          </ElButton>
        </div>
      </template>

      <div
        v-loading="previewLoading"
        element-loading-text="正在加载文档..."
        class="border border-gray-200 rounded bg-white overflow-hidden"
        style="height: 75vh"
      >
        <!-- PDF预览 -->
        <div v-if="previewFileType === FileType.PDF" class="h-full flex flex-col">
          <!-- PDF工具栏 -->
          <div class="flex items-center justify-between p-3 bg-gray-50 border-b border-gray-200">
            <div class="flex items-center gap-2">
              <ElButton size="small" @click="pdfPrevPage" :disabled="pdfCurrentPage <= 1">
                上一页
              </ElButton>
              <span class="text-sm text-gray-600">
                {{ pdfCurrentPage }} / {{ pdfTotalPages }}
              </span>
              <ElButton
                size="small"
                @click="pdfNextPage"
                :disabled="pdfCurrentPage >= pdfTotalPages"
              >
                下一页
              </ElButton>
            </div>
            <div class="flex items-center gap-2">
              <ElButton size="small" @click="pdfZoomOut" :disabled="pdfScale <= 0.4">
                缩小
              </ElButton>
              <span class="text-sm text-gray-600 min-w-12 text-center">
                {{ Math.round(pdfScale * 100) }}%
              </span>
              <ElButton size="small" @click="pdfZoomIn" :disabled="pdfScale >= 3"> 放大 </ElButton>
              <ElButton size="small" @click="pdfResetZoom"> 重置 </ElButton>
            </div>
          </div>
          <!-- PDF内容 -->
          <div class="flex-1 overflow-auto p-4 bg-gray-100 flex justify-center">
            <VuePdfEmbed
              :source="pdfSource"
              :page="pdfCurrentPage"
              :scale="pdfScale"
              class="shadow-lg w-50%"
              @loaded="onPdfLoaded"
              @loading-failed="onPdfError"
            />
          </div>
        </div>
        <!-- 其他格式预览 -->
        <div v-else class="h-full relative">
          <div ref="previewContainer" class="p-5 leading-relaxed overflow-auto h-full"></div>
        </div>
      </div>
    </ElDialog>

    <!-- 上传签约合同对话框 -->
    <ElDialog
      v-model="uploadVisible"
      :title="`上传签约合同 - ${currentContractNumber}`"
      width="500px"
      :before-close="closeUploadDialog"
      destroy-on-close
    >
      <div class="py-5">
        <!-- 文件限制提示 -->
        <div class="mb-4 p-3 bg-blue-50 border border-blue-200 rounded-lg">
          <div class="flex items-start gap-2">
            <AlertCircle class="w-4 h-4 text-blue-500 mt-0.5 flex-shrink-0" />
            <div class="text-sm">
              <p class="text-blue-800 font-medium mb-1">上传说明：</p>
              <ul class="text-blue-700 space-y-1">
                <li>• 每次只能上传一个文件</li>
                <li>• 支持格式：.docx、.pdf、.jpg、.png</li>
                <li>• 文件大小不超过 10MB</li>
                <li>• 上传新文件会替换已选择的文件</li>
              </ul>
            </div>
          </div>
        </div>

        <ElUpload
          v-model:file-list="fileList"
          class="upload-demo"
          drag
          :auto-upload="false"
          :before-upload="beforeUpload"
          :on-change="handleFileChange"
          :on-remove="handleRemove"
          accept=".docx,.pdf,.jpg,.jpeg,.png,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf,image/jpeg,image/png"
        >
          <div class="py-10 px-5 text-center">
            <Plus class="w-12 h-12 text-gray-400 mx-auto mb-4" />
            <div class="text-gray-600 text-base mb-2">
              将文件拖到此处，或<em class="text-blue-500 not-italic">点击上传</em>
            </div>
            <div class="text-gray-400 text-sm">支持.docx、.pdf、.jpg、.png格式，且不超过10MB</div>
            <div class="text-orange-500 text-xs mt-2 font-medium">
              ⚠️ 限制上传一个文件，选择新文件将替换当前文件
            </div>
          </div>
        </ElUpload>
      </div>

      <template #footer>
        <div class="text-right">
          <ElButton @click="closeUploadDialog">取消</ElButton>
          <ElButton
            type="primary"
            :loading="uploadLoading"
            :disabled="fileList.length === 0"
            @click="uploadSignContract"
          >
            {{ uploadLoading ? '上传中...' : '确定上传' }}
          </ElButton>
        </div>
      </template>
    </ElDialog>

    <!-- 收据生成对话框 -->
    <ElDialog
      v-model="receiptVisible"
      :title="`生成收据 - ${currentReceiptContractNumber}`"
      width="600px"
      :before-close="closeReceiptDialog"
      destroy-on-close
    >
      <div v-loading="receiptLoading" element-loading-text="正在获取收据数据...">
        <ElForm :model="receiptForm" label-width="100px" class="py-4">
          <div class="mb-4 p-3 bg-blue-50 border border-blue-200 rounded-lg">
            <div class="flex items-start gap-2">
              <AlertCircle class="w-4 h-4 text-blue-500 mt-0.5 flex-shrink-0" />
              <div class="text-sm">
                <p class="text-blue-800 font-medium mb-1">收据说明：</p>
                <ul class="text-blue-700 space-y-1">
                  <li>• 系统已自动填充合同相关的押金和租金信息</li>
                  <li>• 请根据实际情况填写物业费、水费等其他费用</li>
                  <li>• 总金额会根据各项费用自动计算</li>
                  <li>• 生成后的收据可以预览和下载</li>
                </ul>
              </div>
            </div>
          </div>

          <ElFormItem label="交款单位" required>
            <ElInput v-model="receiptForm.paymentUnit" placeholder="请输入交款单位名称" clearable />
          </ElFormItem>

          <ElFormItem label="付款方式">
            <ElSelect
              v-model="receiptForm.paymentMethod"
              placeholder="请选择付款方式"
              style="width: 100%"
            >
              <ElOption
                v-for="item in paymentMethods"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </ElSelect>
          </ElFormItem>

          <ElFormItem label="付款事由">
            <ElSelect
              v-model="receiptForm.paymentReason"
              placeholder="请选择付款事由"
              style="width: 100%"
            >
              <ElOption
                v-for="item in paymentReasons"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </ElSelect>
          </ElFormItem>

          <div class="grid grid-cols-2 gap-4">
            <ElFormItem label="押金(元)">
              <ElInputNumber
                v-model="receiptForm.yj"
                :min="0"
                :precision="2"
                style="width: 100%"
                @change="handleAmountChange"
              />
            </ElFormItem>
            <ElFormItem label="租金(元)">
              <ElInputNumber
                v-model="receiptForm.zj"
                :min="0"
                :precision="2"
                style="width: 100%"
                @change="handleAmountChange"
              />
            </ElFormItem>
            <ElFormItem label="物业费(元)">
              <ElInputNumber
                v-model="receiptForm.wyf"
                :min="0"
                :precision="2"
                style="width: 100%"
                @change="handleAmountChange"
              />
            </ElFormItem>
            <ElFormItem label="水费(元)">
              <ElInputNumber
                v-model="receiptForm.sf"
                :min="0"
                :precision="2"
                style="width: 100%"
                @change="handleAmountChange"
              />
            </ElFormItem>
          </div>

          <ElFormItem label="总金额(元)">
            <ElInputNumber
              v-model="receiptForm.rmb"
              :min="0"
              :precision="2"
              style="width: 100%"
              readonly
              class="total-amount"
            />
            <div class="text-sm text-gray-500 mt-1">总金额 = 押金 + 租金 + 物业费 + 水费</div>
          </ElFormItem>
        </ElForm>
      </div>

      <template #footer>
        <div class="text-right">
          <ElButton @click="closeReceiptDialog">取消</ElButton>
          <ElButton
            type="primary"
            :loading="receiptGenerating"
            :disabled="receiptLoading || !receiptForm.paymentUnit.trim() || receiptForm.rmb <= 0"
            @click="generateReceipt"
          >
            {{ receiptGenerating ? '生成中...' : '生成收据' }}
          </ElButton>
        </div>
      </template>
    </ElDialog>

    <!-- 退据生成对话框 -->
    <ElDialog
      v-model="returnReceiptVisible"
      :title="`生成退据 - ${currentReturnReceiptContractNumber}`"
      width="600px"
      :before-close="closeReturnReceiptDialog"
      destroy-on-close
    >
      <div v-loading="returnReceiptLoading" element-loading-text="正在获取退据数据...">
        <ElForm :model="returnReceiptForm" label-width="100px" class="py-4">
          <div class="mb-4 p-3 bg-orange-50 border border-orange-200 rounded-lg">
            <div class="flex items-start gap-2">
              <AlertCircle class="w-4 h-4 text-orange-500 mt-0.5 flex-shrink-0" />
              <div class="text-sm">
                <p class="text-orange-800 font-medium mb-1">退据说明：</p>
                <ul class="text-orange-700 space-y-1">
                  <li>• 系统已自动填充合同相关的租户和押金信息</li>
                  <li>• 请根据实际情况填写退还的租金、物业费等费用</li>
                  <li>• 总金额会根据各项费用自动计算</li>
                  <li>• 生成后的退据可以预览和下载</li>
                </ul>
              </div>
            </div>
          </div>

          <ElFormItem label="单位名称" required>
            <ElInput v-model="returnReceiptForm.dw" placeholder="请输入单位名称" clearable />
          </ElFormItem>

          <ElFormItem label="租户名称" required>
            <ElInput v-model="returnReceiptForm.zh" placeholder="请输入租户名称" clearable />
          </ElFormItem>

          <div class="grid grid-cols-2 gap-4">
            <ElFormItem label="押金(元)">
              <ElInputNumber
                v-model="returnReceiptForm.yj"
                :min="0"
                :precision="2"
                style="width: 100%"
                @change="handleReturnAmountChange"
              />
            </ElFormItem>
            <ElFormItem label="租金(元)">
              <ElInputNumber
                v-model="returnReceiptForm.zj"
                :min="0"
                :precision="2"
                style="width: 100%"
                @change="handleReturnAmountChange"
              />
            </ElFormItem>
            <ElFormItem label="物业费(元)" class="col-span-2">
              <ElInputNumber
                v-model="returnReceiptForm.wyf"
                :min="0"
                :precision="2"
                style="width: 100%"
                @change="handleReturnAmountChange"
              />
            </ElFormItem>
          </div>

          <ElFormItem label="总金额(元)">
            <ElInputNumber
              v-model="returnReceiptForm.rmb"
              :min="0"
              :precision="2"
              style="width: 100%"
              readonly
              class="total-amount"
            />
            <div class="text-sm text-gray-500 mt-1">总金额 = 押金 + 租金 + 物业费</div>
          </ElFormItem>
        </ElForm>
      </div>

      <template #footer>
        <div class="text-right">
          <ElButton @click="closeReturnReceiptDialog">取消</ElButton>
          <ElButton
            type="primary"
            :loading="returnReceiptGenerating"
            :disabled="
              returnReceiptLoading ||
              !returnReceiptForm.dw.trim() ||
              !returnReceiptForm.zh.trim() ||
              returnReceiptForm.rmb <= 0
            "
            @click="generateReturnReceipt"
          >
            {{ returnReceiptGenerating ? '生成中...' : '生成退据' }}
          </ElButton>
        </div>
      </template>
    </ElDialog>
  </div>
</template>

<style scoped>
/* Element Plus 样式覆盖 */
:deep(.el-table th) {
  background-color: #f8f9fa;
  color: #495057;
  font-weight: 600;
}

:deep(.el-table td) {
  padding: 12px 0;
}

:deep(.el-pagination) {
  margin-top: 20px;
}

/* DOCX 预览样式 */
:deep(.docx-container p) {
  margin: 8px 0;
}

:deep(.docx-container table) {
  border-collapse: collapse;
  width: 100%;
  margin: 16px 0;
}

:deep(.docx-container table td),
:deep(.docx-container table th) {
  border: 1px solid #ddd;
  padding: 8px;
  text-align: left;
}

:deep(.docx-container table th) {
  background-color: #f2f2f2;
  font-weight: bold;
}

/* 上传组件样式 */
:deep(.el-upload-dragger) {
  border: 2px dashed #d9d9d9;
  border-radius: 6px;
  width: 100%;
  height: auto;
  text-align: center;
  background: #fafafa;
  transition: border-color 0.3s;
}

:deep(.el-upload-dragger:hover) {
  border-color: #409eff;
}

:deep(.el-upload-dragger.is-dragover) {
  border-color: #409eff;
  background-color: rgba(64, 158, 255, 0.06);
}

:deep(.el-upload__text em) {
  color: #409eff;
  font-style: normal;
}

/* PDF预览样式 */
:deep(.vue-pdf-embed) {
  border: 1px solid #e0e0e0;
  border-radius: 4px;
}

/* 收据表单样式 */
:deep(.total-amount .el-input__inner) {
  background-color: #f5f7fa;
  font-weight: 600;
  color: #409eff;
}

/* 预览对话框样式优化 */
:deep(.preview-dialog .el-dialog__header) {
  padding: 16px 20px;
  border-bottom: 1px solid #ebeef5;
}

:deep(.preview-dialog .el-dialog__body) {
  padding: 0;
}
</style>
