<template>
  <el-drawer
    v-model="visible"
    title="流程详情"
    direction="rtl"
    size="55%"
    :close-on-click-modal="false"
    :destroy-on-close="true"
    @closed="handleClose"
  >
    <div v-loading="loading" class="detail-content">
      <FilePreview v-model="previewVisible" :url="previewUrl" />
      <!-- 流程基本信息 -->
      <div class="info-section">
        <el-descriptions :column="3" size="small" border>
          <el-descriptions-item label="流程名称">{{ progress?.definition?.name }}</el-descriptions-item>
          <el-descriptions-item label="实例编号">{{ progress?.instance?.instanceNo || progress?.instance?.id }}</el-descriptions-item>
          <el-descriptions-item label="状态">
            <el-tag :type="instanceStatusTagType(progress?.instance?.status)">
              {{ instanceStatusText(progress?.instance?.status) }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="剩余节点">
            <el-tag type="warning">{{ progress?.remainingNodeCount || 0 }} 个待审批</el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="发起时间">{{ progress?.instance?.startTime }}</el-descriptions-item>
          <el-descriptions-item label="结束时间">{{ progress?.instance?.endTime || '-' }}</el-descriptions-item>
        </el-descriptions>
      </div>

      <!-- 表单数据 -->
      <div v-if="formDataDisplay" class="form-data-section">
        <h4>表单数据</h4>
        <FormDataDisplay
          :form-schema="progress?.definition?.formSchema"
          :form-data="progress?.instance?.formData"
        />
      </div>

      <!-- 附件列表 -->
      <div class="attachment-section">
        <h4>附件列表</h4>
        <div v-if="attachments.length > 0" class="attachment-list">
          <div v-for="att in attachments" :key="att.id" class="attachment-item">
            <el-link type="primary" @click="openPreview(att.fileUrl)">
              <el-icon><Document /></el-icon>
              <span class="attachment-name" :title="att.fileName">{{ att.fileName }}</span>
            </el-link>
            <span class="attachment-meta">
              {{ att.nodeName || '发起' }}
              <template v-if="att.uploaderName">· {{ att.uploaderName }}</template>
              <template v-if="att.createTime">· {{ att.createTime }}</template>
            </span>
            <el-image
              v-if="isImage(att.fileUrl)"
              :src="getFileUrl(att.fileUrl)"
              :preview-src-list="imagePreviewList"
              fit="cover"
              style="width: 60px; height: 60px; margin-left: 8px;"
            />
          </div>
        </div>
        <el-empty v-else description="暂无附件" :image-size="60" style="padding: 10px 0;" />
      </div>

      <el-divider />

      <div class="detail-body">
        <!-- 左侧：流程节点时间线 -->
        <div class="timeline-section">
          <h4>流程进度</h4>
          <el-timeline>
            <el-timeline-item
              v-for="node in progress?.nodes"
              :key="node.nodeId"
              :type="timelineType(node.status)"
              :icon="timelineIcon(node.status)"
              :color="timelineColor(node.status)"
            >
              <div class="node-item" :class="{ 'current-node': node.status === 'current' }">
                <div class="node-title">
                  <span class="node-name">{{ node.nodeName }}</span>
                  <el-tag v-if="node.isMyTurn" type="danger" size="small" effect="dark">待我处理</el-tag>
                </div>
                <div v-if="node.tasks?.length" class="node-tasks">
                  <div
                    v-for="task in node.tasks"
                    :key="task.id"
                    class="task-item"
                  >
                    <span class="task-assignee">{{ task.assigneeName || '用户' + task.assigneeId }}</span>
                    <el-tag :type="taskStatusType(task.status)" size="small">
                      {{ taskStatusText(task.status) }}
                    </el-tag>
                    <span v-if="task.comment" class="task-comment">{{ task.comment }}</span>
                  </div>
                </div>
              </div>
            </el-timeline-item>
          </el-timeline>
        </div>

        <!-- 右侧：审批操作区 -->
        <div class="action-section">
          <template v-if="myPendingTask">
            <h4>审批操作</h4>
            <el-form ref="formRef" :model="form" label-width="80px">
              <el-form-item label="操作">
                <el-radio-group v-model="form.action">
                  <el-radio label="pass">通过</el-radio>
                  <el-radio label="reject">拒绝</el-radio>
                  <el-radio label="rollback">回退</el-radio>
                  <el-radio label="transfer">转办</el-radio>
                </el-radio-group>
              </el-form-item>
              <el-form-item v-if="form.action === 'rollback'" label="回退到">
                <el-select v-model="form.targetNodeId" filterable placeholder="请选择回退节点" style="width: 100%">
                  <el-option
                    v-for="node in rollbackNodeOptions"
                    :key="node.nodeId"
                    :label="node.nodeName"
                    :value="node.nodeId"
                  />
                </el-select>
              </el-form-item>
              <el-form-item v-if="form.action === 'transfer'" label="转给人">
                <el-select v-model="form.transferTo" filterable placeholder="请选择转办人" style="width: 100%">
                  <el-option v-for="u in userList" :key="u.id" :label="u.realName || u.username" :value="u.id" />
                </el-select>
              </el-form-item>
              <el-form-item label="附件">
                <el-upload
                  v-model:file-list="attachmentList"
                  action="#"
                  :http-request="handleUpload"
                  :before-upload="beforeFileUpload"
                  :before-remove="() => true"
                  :limit="5"
                  multiple
                  :on-preview="handleFilePreview"
                >
                  <el-button type="primary" size="small">上传附件</el-button>
                </el-upload>
              </el-form-item>
              <el-form-item label="意见">
                <el-input v-model="form.comment" type="textarea" placeholder="请输入审批意见" />
              </el-form-item>
              <el-form-item>
                <el-button type="primary" :loading="submitting" @click="submitApprove">提交</el-button>
                <el-button :loading="submitting" @click="handleAddSign">加签</el-button>
              </el-form-item>
            </el-form>
          </template>
          <template v-else>
            <el-empty description="当前没有需要您处理的审批任务" />
          </template>

          <el-divider />

          <!-- 审批历史 -->
          <h4>审批历史</h4>
          <div v-if="progress?.records?.length" class="record-list">
            <div
              v-for="record in progress.records"
              :key="record.id"
              class="record-item"
            >
              <div class="record-header">
                <span class="record-operator">{{ record.operatorName || '用户' + record.operatorId }}</span>
                <el-tag :type="recordActionType(record.actionResult)" size="small">
                  {{ recordActionText(record.actionResult) }}
                </el-tag>
                <span class="record-time">{{ record.createTime }}</span>
              </div>
              <div v-if="record.comment" class="record-comment">{{ record.comment }}</div>
              <div v-if="record.attachmentUrls" class="record-attachments">
                <el-link
                  v-for="(url, idx) in parseAttachments(record.attachmentUrls)"
                  :key="idx"
                  type="primary"
                  @click="openPreview(url)"
                  size="small"
                >
                  附件{{ idx + 1 }}: {{ getFileName(url) }}
                </el-link>
              </div>
            </div>
          </div>
          <el-empty v-else description="暂无审批记录" />
        </div>
      </div>
    </div>
  </el-drawer>

  <!-- 加签弹窗 -->
  <el-dialog
    v-model="addSignDialogVisible"
    title="加签"
    width="400px"
    :close-on-click-modal="false"
  >
    <el-select v-model="addSignUserId" filterable placeholder="请选择加签人" style="width: 100%">
      <el-option v-for="u in userList" :key="u.id" :label="u.realName || u.username" :value="u.id" />
    </el-select>
    <template #footer>
      <el-button @click="addSignDialogVisible = false">取消</el-button>
      <el-button type="primary" :loading="submitting" @click="confirmAddSign">确认</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { getProgress, getInstanceAttachments } from '@/api/flow/instance'
import { approveTask, rejectTask, returnTask, transferTask, addSignTask, getTransferableUsers } from '@/api/flow/task'
import { uploadFile } from '@/api/file'
import { beforeFileUpload, getFileUrl, getFileName, getUploadUrl, parseAttachments, collectAttachmentUrls } from '@/utils/file'
import { instanceStatusText, instanceStatusTagType, taskStatusText, taskStatusType, recordActionText, recordActionType } from '@/utils/flow'
import FilePreview from '@/components/FilePreview/index.vue'
import FormDataDisplay from '@/components/FormDataDisplay/index.vue'
import type { ProcessProgress, FlowTask, NodeProgress, ApprovalAction, Attachment } from '@/types/flow'
import type { User } from '@/types/system'
import { CircleCheck, Clock, Document } from '@element-plus/icons-vue'

const props = defineProps<{
  modelValue: boolean
  instanceId: number
}>()

const emit = defineEmits<{
  (e: 'update:modelValue', val: boolean): void
  (e: 'approved'): void
}>()

const visible = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})

const loading = ref(false)
const previewVisible = ref(false)
const previewUrl = ref('')
const progress = ref<ProcessProgress | null>(null)

type ApprovalActionType = 'pass' | 'reject' | 'rollback' | 'transfer'

const form = reactive<{
  action: ApprovalActionType
  comment: string
  transferTo: number | undefined
  targetNodeId: string | undefined
}>({
  action: 'pass',
  comment: '',
  transferTo: undefined,
  targetNodeId: undefined
})

const attachmentList = ref<any[]>([])
const submitting = ref(false)
const addSignDialogVisible = ref(false)
const addSignUserId = ref<number | undefined>(undefined)

const rollbackNodeOptions = computed<NodeProgress[]>(() => {
  if (!progress.value) return []
  return progress.value.nodes.filter(n => n.status === 'completed')
})

const userList = ref<User[]>([])

async function loadTransferableUsers() {
  const task = myPendingTask.value
  if (!task) {
    userList.value = []
    return
  }
  try {
    // 按当前节点审批角色过滤可选用户，已自动排除当前登录人
    userList.value = await getTransferableUsers(task.id)
  } catch {
    userList.value = []
  }
}

// 是否有表单数据用于展示
const formDataDisplay = computed(() => {
  return !!progress.value?.instance?.formData
})

const attachments = ref<Attachment[]>([])

// 实例附件列表（从附件表读取，包含所有节点上传的历史附件）
const instanceAttachments = computed(() => {
  return attachments.value.map(a => a.fileUrl)
})

// 图片预览列表
const imagePreviewList = computed(() => {
  return attachments.value.filter(a => isImage(a.fileUrl)).map(a => getFileUrl(a.fileUrl))
})

async function loadAttachments() {
  if (!props.instanceId) return
  try {
    attachments.value = await getInstanceAttachments(props.instanceId)
  } catch {
    attachments.value = []
  }
}

function handleFilePreview(file: any) {
  const url = getUploadUrl(file)
  if (url) openPreview(url)
}

function openPreview(url: string) {
  previewUrl.value = url
  previewVisible.value = true
}

function isImage(url: string): boolean {
  return /\.(png|jpe?g|gif|webp|bmp)$/i.test(url)
}

async function handleUpload(options: any) {
  try {
    const res = await uploadFile(options.file)
    options.onSuccess(res)
  } catch (e) {
    options.onError(e)
  }
}

// 查找当前登录用户需要处理的待办任务
const myPendingTask = computed<FlowTask | null>(() => {
  if (!progress.value) return null
  for (const node of progress.value.nodes) {
    if (node.isMyTurn && node.tasks) {
      const pending = node.tasks.find(t => t.status === 0)
      if (pending) return pending
    }
  }
  return null
})

function timelineType(status: string) {
  if (status === 'completed') return 'success'
  if (status === 'current') return 'warning'
  return 'info'
}

function timelineIcon(status: string) {
  if (status === 'completed') return CircleCheck
  if (status === 'current') return Clock
  return undefined
}

function timelineColor(status: string) {
  if (status === 'completed') return '#67C23A'
  if (status === 'current') return '#E6A23C'
  return '#909399'
}

async function loadProgress() {
  if (!props.instanceId) return
  loading.value = true
  try {
    // 静默加载进度，无权限时不在详情页弹全局错误提示
    const res = await getProgress(props.instanceId, { silent: true })
    progress.value = res
  } catch {
    progress.value = null
  } finally {
    loading.value = false
  }
}

async function submitApprove() {
  const task = myPendingTask.value
  if (!task) return
  if (form.action === 'transfer' && !form.transferTo) {
    ElMessage.warning('请选择转办人')
    return
  }
  if (form.action === 'rollback' && !form.targetNodeId) {
    ElMessage.warning('请选择回退节点')
    return
  }
  submitting.value = true
  try {
    const data: ApprovalAction = {
      action: form.action,
      comment: form.comment
    }
    if (form.action === 'transfer' && form.transferTo) {
      data.transferTo = Number(form.transferTo)
    }
    if (form.action === 'rollback' && form.targetNodeId) {
      data.targetNodeId = form.targetNodeId
    }
    if (attachmentList.value.length > 0) {
      data.attachmentUrls = collectAttachmentUrls(attachmentList.value)
    }
    switch (form.action) {
      case 'pass':
        await approveTask(task.id, data)
        break
      case 'reject':
        await rejectTask(task.id, data)
        break
      case 'rollback':
        await returnTask(task.id, data)
        break
      case 'transfer':
        await transferTask(task.id, data)
        break
    }
    ElMessage.success('审批提交成功')
    form.action = 'pass'
    form.comment = ''
    form.transferTo = undefined
    form.targetNodeId = undefined
    attachmentList.value = []
    // 刷新进度展示最新状态，不关闭抽屉
    await loadProgress()
    emit('approved')
  } finally {
    submitting.value = false
  }
}

function handleClose() {
  progress.value = null
  attachmentList.value = []
  attachments.value = []
}

function handleAddSign() {
  const task = myPendingTask.value
  if (!task) return
  addSignUserId.value = undefined
  addSignDialogVisible.value = true
}

async function confirmAddSign() {
  const task = myPendingTask.value
  if (!task || !addSignUserId.value) {
    ElMessage.warning('请选择加签人')
    return
  }
  submitting.value = true
  try {
    await addSignTask(task.id, addSignUserId.value)
    ElMessage.success('加签成功')
    addSignDialogVisible.value = false
    addSignUserId.value = undefined
    await loadProgress()
  } finally {
    submitting.value = false
  }
}

watch(() => props.instanceId, (id) => {
  if (id && props.modelValue) {
    loadProgress()
  }
})

watch(() => props.modelValue, async (val) => {
  if (val && props.instanceId) {
    await loadProgress()
    await loadTransferableUsers()
    loadAttachments()
  }
})
</script>

<style scoped>
.detail-content {
  height: calc(100vh - 120px);
  overflow-y: auto;
  padding-right: 8px;
}
.info-section {
  margin-bottom: 10px;
}
.form-data-section,
.attachment-section {
  margin-bottom: 10px;
}
.form-data-section h4,
.attachment-section h4 {
  margin: 0 0 8px 0;
  font-size: 15px;
  color: #303133;
}
.attachment-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.attachment-item {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 12px;
  background: #f5f7fa;
  border-radius: 4px;
}
.attachment-name {
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.attachment-meta {
  font-size: 12px;
  color: #909399;
}
.detail-body {
  display: flex;
  gap: 24px;
}
.timeline-section {
  flex: 1;
  min-width: 0;
}
.action-section {
  flex: 1;
  min-width: 0;
  border-left: 1px solid #ebeef5;
  padding-left: 24px;
}
.timeline-section h4,
.action-section h4 {
  margin: 0 0 16px 0;
  font-size: 15px;
  color: #303133;
}
.node-item {
  padding: 4px 0;
}
.node-item.current-node {
  background: #fdf6ec;
  padding: 8px;
  border-radius: 4px;
}
.node-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.node-name {
  font-weight: bold;
  color: #303133;
}
.node-tasks {
  padding-left: 8px;
}
.task-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: #606266;
  margin: 4px 0;
}
.task-comment {
  color: #909399;
}
.record-list {
  max-height: 300px;
  overflow-y: auto;
}
.record-item {
  padding: 10px 0;
  border-bottom: 1px solid #ebeef5;
}
.record-item:last-child {
  border-bottom: none;
}
.record-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}
.record-operator {
  font-weight: bold;
  color: #303133;
}
.record-time {
  font-size: 12px;
  color: #909399;
}
.record-comment {
  font-size: 13px;
  color: #606266;
  background: #f5f7fa;
  padding: 6px 10px;
  border-radius: 4px;
  margin-bottom: 6px;
}
.record-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
</style>
