<template>
  <div class="step-detail-panel">
    <div class="panel-header">
      <el-button type="text" icon="el-icon-arrow-left" @click="$emit('back')">
        返回
      </el-button>
      <h3>行动项明细</h3>
    </div>

    <div v-if="loading" class="loading-container">
      <el-skeleton :rows="4" animated />
    </div>

    <template v-else>
      <div v-if="loadedStep" class="panel-body">
        <el-descriptions :column="2" border size="small">
          <el-descriptions-item label="标题">
            {{ loadedStep.name || loadedStep.title || '未命名行动项' }}
          </el-descriptions-item>
          <el-descriptions-item label="状态">
            <el-tag size="mini" :type="formatStepStatusTag(loadedStep.status)">
              {{ formatStepStatus(loadedStep.status) }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="执行人">
            {{ getExecutorDisplay(loadedStep) || '-' }}
          </el-descriptions-item>
          <el-descriptions-item label="排序">
            {{ loadedStep.stepOrder || '-' }}
          </el-descriptions-item>
          <el-descriptions-item label="描述" :span="2">
            {{ loadedStep.description || '暂无描述' }}
          </el-descriptions-item>
        </el-descriptions>

        <div class="step-resource-section">
          <el-empty v-if="!hasResources" description="暂无资源信息" />
          <template v-else>
            <div v-if="resources.materials.length" class="resource-table">
              <div class="resource-table-header">
                <h4>物资</h4>
                <span>共 {{ resources.materials.length }} 项</span>
              </div>
              <el-table
                :data="resources.materials"
                size="mini"
                border
                :header-cell-style="{ background: '#f8f8f8' }"
              >
                <el-table-column prop="resourceName" label="物资名称" min-width="150" show-overflow-tooltip />
                <el-table-column label="数量" width="100">
                  <template slot-scope="scope">
                    {{ getMaterialQuantity(scope.row) }}
                  </template>
                </el-table-column>
                <el-table-column label="单位" width="80">
                  <template slot-scope="scope">
                    <dict-tag 
                      v-if="getMaterialUnit(scope.row)"
                      :options="dict.type.material_unit || []" 
                      :value="getMaterialUnit(scope.row)" 
                    />
                    <span v-else>-</span>
                  </template>
                </el-table-column>
                <el-table-column label="仓库" min-width="120">
                  <template slot-scope="scope">
                    {{ getWarehouseName(scope.row) }}
                  </template>
                </el-table-column>
                <el-table-column label="仓库距离" width="100" v-if="eventLocation">
                  <template slot-scope="scope">
                    {{ getWarehouseDistance(scope.row) }}
                  </template>
                </el-table-column>
                <el-table-column label="状态" width="100">
                  <template slot-scope="scope">
                    <el-tag :type="getStatusTagType(scope.row.status)" size="mini">
                      {{ getStatusLabel(scope.row.status) }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column label="操作" width="180" fixed="right" v-if="isStepInProgress">
                  <template slot-scope="scope">
                    <div class="action-buttons">
                      <!-- 占用后归还模式：锁定状态显示"出库"按钮 -->
                      <el-button
                        v-if="scope.row.status === 'locked' && scope.row.usageMode === 'occupy'"
                        type="text"
                        size="mini"
                        :loading="processingLinkId === scope.row.id"
                        @click="handleMaterialAction('consume', scope.row)"
                      >
                        出库
                      </el-button>
                      <!-- 占用后归还模式：消耗后显示"归还"按钮 -->
                      <el-button
                        v-if="scope.row.status === 'consumed' && scope.row.usageMode === 'occupy'"
                        type="text"
                        size="mini"
                        :loading="processingLinkId === scope.row.id"
                        @click="handleMaterialAction('return', scope.row)"
                      >
                        归还
                      </el-button>
                      <!-- 占用后消耗模式：锁定状态显示"消耗"按钮 -->
                      <el-button
                        v-if="scope.row.status === 'locked' && scope.row.usageMode === 'consume'"
                        type="text"
                        size="mini"
                        :loading="processingLinkId === scope.row.id"
                        @click="handleMaterialAction('consume', scope.row)"
                      >
                        消耗
                      </el-button>
                      <span v-if="!canOperateMaterial(scope.row)">-</span>
                    </div>
                  </template>
                </el-table-column>
              </el-table>
            </div>

            <div v-if="resources.equipment.length" class="resource-table">
              <div class="resource-table-header">
                <h4>装备</h4>
                <span>共 {{ resources.equipment.length }} 项</span>
              </div>
              <el-table
                :data="resources.equipment"
                size="mini"
                border
                :header-cell-style="{ background: '#f8f8f8' }"
              >
                <el-table-column prop="resourceName" label="装备名称" min-width="150" show-overflow-tooltip />
                <el-table-column label="仓库" min-width="120">
                  <template slot-scope="scope">
                    {{ getWarehouseName(scope.row) }}
                  </template>
                </el-table-column>
                <el-table-column label="仓库距离" width="100" v-if="eventLocation">
                  <template slot-scope="scope">
                    {{ getWarehouseDistance(scope.row) }}
                  </template>
                </el-table-column>
                <el-table-column label="预计开始时间" width="160">
                  <template slot-scope="scope">
                    {{ formatDateTime(scope.row.expectedFrom) }}
                  </template>
                </el-table-column>
                <el-table-column label="预计结束时间" width="160">
                  <template slot-scope="scope">
                    {{ formatDateTime(scope.row.expectedUntil) }}
                  </template>
                </el-table-column>
                <el-table-column label="状态" width="100">
                  <template slot-scope="scope">
                    <el-tag :type="getStatusTagType(scope.row.status)" size="mini">
                      {{ getStatusLabel(scope.row.status) }}
                    </el-tag>
                  </template>
                </el-table-column>
              </el-table>
            </div>

            <div v-if="resources.vehicles.length" class="resource-table">
              <div class="resource-table-header">
                <h4>车辆</h4>
                <span>共 {{ resources.vehicles.length }} 辆</span>
              </div>
              <el-table
                :data="resources.vehicles"
                size="mini"
                border
                :header-cell-style="{ background: '#f8f8f8' }"
              >
                <el-table-column prop="resourceName" label="车辆名称" min-width="150" show-overflow-tooltip />
                <el-table-column label="路线/目的地" min-width="150">
                  <template slot-scope="scope">
                    {{ scope.row.route || '-' }}
                  </template>
                </el-table-column>
                <el-table-column label="调度时间" width="160">
                  <template slot-scope="scope">
                    {{ formatDateTime(scope.row.dispatchTime) }}
                  </template>
                </el-table-column>
                <el-table-column label="预计时长" width="100">
                  <template slot-scope="scope">
                    {{ scope.row.durationMinutes ? scope.row.durationMinutes + '分钟' : '-' }}
                  </template>
                </el-table-column>
                <el-table-column prop="notes" label="备注" min-width="150" show-overflow-tooltip />
                <el-table-column label="状态" width="100">
                  <template slot-scope="scope">
                    <el-tag :type="getStatusTagType(scope.row.status)" size="mini">
                      {{ getStatusLabel(scope.row.status) }}
                    </el-tag>
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </template>
        </div>

        <!-- 处置记录 -->
        <el-card shadow="never" class="disposal-card">
          <div slot="header" class="section-header">
            <span>处置记录</span>
            <el-button 
              v-if="isStepInProgress"
              type="primary" 
              size="mini" 
              plain 
              icon="el-icon-plus"
              @click="handleAddDisposal"
            >
              记录处置
            </el-button>
          </div>
          <div v-if="disposalsLoading" class="disposal-loading">
            <i class="el-icon-loading" />
            <span>加载处置记录...</span>
          </div>
          <el-empty v-else-if="disposals.length === 0" description="暂无处置记录" />
          <div v-else class="disposal-list">
            <div 
              v-for="disposal in disposals" 
              :key="disposal.id" 
              class="disposal-item"
            >
              <div class="disposal-header">
                <div class="disposal-meta">
                  <span class="disposal-time">{{ formatDateTime(disposal.createTime) }}</span>
                  <el-tag 
                    size="mini" 
                    :type="getOutcomeTagType(disposal.outcome)"
                  >
                    {{ getOutcomeLabel(disposal.outcome) }}
                  </el-tag>
                </div>
                <div class="disposal-actions" v-if="isStepInProgress">
                  <el-button 
                    type="text" 
                    size="mini" 
                    icon="el-icon-edit"
                    @click="handleEditDisposal(disposal)"
                  >
                    编辑
                  </el-button>
                  <el-button 
                    type="text" 
                    size="mini" 
                    icon="el-icon-delete"
                    style="color: #f56c6c;"
                    @click="handleDeleteDisposal(disposal)"
                  >
                    删除
                  </el-button>
                </div>
              </div>
              <div class="disposal-content">
                {{ disposal.description || '暂无描述' }}
              </div>
              <!-- 附件列表 -->
              <div v-if="getDisposalAttachments(disposal).length > 0" class="disposal-attachments">
                <div class="attachments-title">附件：</div>
                <div class="attachments-list">
                  <el-link
                    v-for="(attachment, idx) in getDisposalAttachments(disposal)"
                    :key="idx"
                    :href="getAttachmentUrl(attachment)"
                    target="_blank"
                    type="primary"
                    :underline="false"
                    class="attachment-item"
                  >
                    <i class="el-icon-document"></i>
                    {{ getAttachmentName(attachment) }}
                  </el-link>
                </div>
              </div>
            </div>
          </div>
        </el-card>
      </div>
      <el-empty v-else description="未找到行动项数据" />
    </template>

    <!-- 处置记录对话框 -->
    <el-dialog
      :title="currentDisposal ? '编辑处置记录' : '新增处置记录'"
      :visible.sync="disposalDialogVisible"
      width="600px"
      :close-on-click-modal="false"
    >
      <el-form
        ref="disposalForm"
        :model="disposalForm"
        :rules="disposalRules"
        label-width="100px"
      >
        <el-form-item label="参与方" prop="participantId">
          <el-select 
            v-model="disposalForm.participantId" 
            placeholder="请选择参与方" 
            style="width: 100%"
            filterable
          >
            <el-option
              v-for="participant in participants"
              :key="participant.id"
              :label="getParticipantDisplayName(participant)"
              :value="participant.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="处置描述" prop="description">
          <el-input
            v-model="disposalForm.description"
            type="textarea"
            :rows="4"
            placeholder="请输入处置过程与采取措施"
            maxlength="1000"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="处置结果" prop="outcome">
          <el-select v-model="disposalForm.outcome" placeholder="请选择处置结果" style="width: 100%">
            <el-option label="完成" value="success" />
            <el-option label="部分完成" value="partial" />
            <el-option label="未完成" value="failed" />
          </el-select>
        </el-form-item>
        <el-form-item label="附件">
          <FileUpload
            v-model="disposalForm.attachmentIds"
            :limit="10"
            :file-size="50"
            :file-type="['jpg', 'jpeg', 'png', 'gif', 'bmp', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'zip', 'rar', 'mp4', 'avi', 'mov', 'wmv']"
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="disposalDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleDisposalSubmit">确定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { listDispatchSteps, listDispatchStepResources, getDispatchTask, releaseMaterialLink, consumeMaterialLink, returnMaterialLink, listDispatchDisposals, addDispatchDisposal, updateDispatchDisposal, listDispatchParticipants } from '@/api/emergency/dispatchTask'
import { getEvent } from '@/api/emergency/event'
import { listWarehouse } from '@/api/resource/warehouse'
import { listMaterial } from '@/api/resource/material'
import { listEquipment } from '@/api/resource/equipment'
import { listVehicle } from '@/api/resource/vehicle'
import { formatDateTime as formatDateTimeUtil } from '@/views/duty/alert/utils/dateHelpers'
import FileUpload from '@/components/FileUpload'

export default {
  name: 'StepDetailPanel',
  components: {
    FileUpload
  },
  dicts: ['material_unit'],
  props: {
    taskId: {
      type: [Number, String],
      required: true
    },
    stepId: {
      type: [Number, String],
      required: true
    }
  },
  data() {
    return {
      loading: false,
      loadedStep: null,
      resources: {
        materials: [],
        equipment: [],
        vehicles: []
      },
      warehouses: [],
      eventLocation: null,
      availableMaterials: [],
      availableEquipment: [],
      availableVehicles: [],
      processingLinkId: null,
      taskStatus: null,
      participants: [],
      disposals: [],
      disposalsLoading: false,
      disposalDialogVisible: false,
      currentDisposal: null,
      disposalForm: {
        participantId: null,
        description: '',
        outcome: 'success',
        attachmentIds: ''
      },
      disposalRules: {
        participantId: [{ required: true, message: '请选择参与方', trigger: 'change' }],
        description: [{ required: true, message: '请输入处置描述', trigger: 'blur' }],
        outcome: [{ required: true, message: '请选择处置结果', trigger: 'change' }]
      }
    }
  },
  computed: {
    requestKey() {
      return `${this.taskId || ''}-${this.stepId || ''}`
    },
    hasResources() {
      return (
        this.resources.materials.length > 0 ||
        this.resources.equipment.length > 0 ||
        this.resources.vehicles.length > 0
      )
    },
    isTaskInProgress() {
      return this.taskStatus === 'in_progress'
    },
    isStepInProgress() {
      return this.loadedStep && this.loadedStep.status === 'in_progress'
    }
  },
  watch: {
    requestKey: {
      immediate: true,
      handler() {
        if (this.taskId && this.stepId) {
          this.fetchData()
        } else {
          this.resetState()
        }
      }
    }
  },
  methods: {
    async fetchData() {
      this.loading = true
      try {
        // 先加载任务状态和资源列表
        await Promise.all([
          this.loadTaskStatus(),
          this.loadWarehouses(),
          this.loadMaterials(),
          this.loadEquipment(),
          this.loadVehicles(),
          this.loadEventLocation(),
          this.loadParticipants()
        ])
        
        // 然后加载行动项和资源链接数据
        const [stepsRes, resourcesRes] = await Promise.all([
          listDispatchSteps(this.taskId),
          listDispatchStepResources(this.taskId, this.stepId)
        ])

        const steps = stepsRes?.data || []
        this.loadedStep =
          steps.find(item => String(item.id) === String(this.stepId)) || null

        // 加载处置记录
        await this.loadDisposals()
        
        // 提取资源信息并分组（在资源列表加载完成后）
        // 参考 StepResourceAllocationDialog 的逻辑，先处理 resourceName，再提取其他信息
        const extractedResources = (resourcesRes?.data || []).map(link => {
          // 先确定资源名称
          let resourceName = `资源 #${link.resourceId}`
          
          // 1. 从 note 的 snapshot 中获取
          if (link.note) {
            try {
              const snapshot = typeof link.note === 'string' ? JSON.parse(link.note) : link.note
              resourceName = snapshot.name || snapshot.materialName || snapshot.equipmentName || snapshot.vehicleName || resourceName
            } catch (e) {
              // If note is not JSON, use it as resourceName (for old format)
              if (link.resourceType === 'vehicle') {
                resourceName = link.note
              }
            }
          }
          
          // 2. 从 resourceSnapshot 获取
          if ((!resourceName || resourceName.startsWith('资源 #')) && link.resourceSnapshot) {
            try {
              const snapshot = typeof link.resourceSnapshot === 'string' 
                ? JSON.parse(link.resourceSnapshot) 
                : link.resourceSnapshot
              if (snapshot.name || snapshot.materialName || snapshot.equipmentName || snapshot.vehicleName) {
                resourceName = snapshot.name || snapshot.materialName || snapshot.equipmentName || snapshot.vehicleName
              }
            } catch (e) {
              // Ignore parse errors
            }
          }
          
          // 3. 从资源列表中查找
          if ((!resourceName || resourceName.startsWith('资源 #')) && link.resourceId) {
            if (link.resourceType === 'material') {
              const material = this.availableMaterials.find(m => 
                m.id === link.resourceId || 
                String(m.id) === String(link.resourceId) ||
                Number(m.id) === Number(link.resourceId)
              )
              if (material) {
                resourceName = material.materialName
              }
            } else if (link.resourceType === 'equipment') {
              const equipment = this.availableEquipment.find(e => 
                e.id === link.resourceId || 
                String(e.id) === String(link.resourceId) ||
                Number(e.id) === Number(link.resourceId)
              )
              if (equipment) {
                resourceName = equipment.equipmentName
              }
            } else if (link.resourceType === 'vehicle') {
              const vehicle = this.availableVehicles.find(v => 
                v.id === link.resourceId || 
                String(v.id) === String(link.resourceId) ||
                Number(v.id) === Number(link.resourceId)
              )
              if (vehicle) {
                resourceName = vehicle.vehicleName || vehicle.plateNo
              }
            }
          }
          
          // 4. 使用 link.resourceName 作为后备
          if ((!resourceName || resourceName.startsWith('资源 #')) && link.resourceName) {
            resourceName = link.resourceName
          }
          
          // 然后提取其他信息
          const extractedInfo = this.extractResourceInfo(link)
          
          // 如果 resourceName 还是默认值，尝试从 extractedInfo 获取
          if (resourceName.startsWith('资源 #') || !resourceName) {
            if (link.resourceType === 'material' && extractedInfo.materialName) {
              resourceName = extractedInfo.materialName
            } else if (link.resourceType === 'equipment' && extractedInfo.equipmentName) {
              resourceName = extractedInfo.equipmentName
            } else if (link.resourceType === 'vehicle' && extractedInfo.vehicleName) {
              resourceName = extractedInfo.vehicleName
            }
          }
          
          return {
            ...link,
            resourceName,
            ...extractedInfo
          }
        })
        this.resources = this.groupResources(extractedResources)
      } catch (error) {
        console.error('Failed to load step detail', error)
        this.resetState()
      } finally {
        this.loading = false
      }
    },
    async loadWarehouses() {
      try {
        const res = await listWarehouse({ pageNum: 1, pageSize: 1000 })
        this.warehouses = res.rows || res.data || []
      } catch (error) {
        console.warn('加载仓库列表失败:', error)
        this.warehouses = []
      }
    },
    async loadMaterials() {
      try {
        const res = await listMaterial({ pageNum: 1, pageSize: 1000 })
        this.availableMaterials = res.rows || res.data || []
      } catch (error) {
        console.warn('加载物资列表失败:', error)
        this.availableMaterials = []
      }
    },
    async loadEquipment() {
      try {
        const res = await listEquipment({ pageNum: 1, pageSize: 1000 })
        this.availableEquipment = res.rows || res.data || []
      } catch (error) {
        console.warn('加载装备列表失败:', error)
        this.availableEquipment = []
      }
    },
    async loadVehicles() {
      try {
        const res = await listVehicle({ pageNum: 1, pageSize: 1000 })
        this.availableVehicles = res.rows || res.data || []
      } catch (error) {
        console.warn('加载车辆列表失败:', error)
        this.availableVehicles = []
      }
    },
    async loadTaskStatus() {
      if (!this.taskId) return
      try {
        const taskRes = await getDispatchTask(this.taskId)
        if (taskRes && taskRes.code === 200 && taskRes.data) {
          this.taskStatus = taskRes.data.status
        }
      } catch (error) {
        console.warn('加载任务状态失败:', error)
      }
    },
    async loadEventLocation() {
      if (!this.taskId) return
      try {
        const taskRes = await getDispatchTask(this.taskId)
        if (taskRes && taskRes.code === 200 && taskRes.data && taskRes.data.eventId) {
          const eventRes = await getEvent(taskRes.data.eventId)
          if (eventRes && eventRes.code === 200 && eventRes.data) {
            const event = eventRes.data
            if (event.latitude && event.longitude) {
              this.eventLocation = {
                lat: parseFloat(event.latitude),
                lng: parseFloat(event.longitude)
              }
            }
          }
        }
      } catch (error) {
        console.warn('加载事件位置失败，无法计算距离:', error)
      }
    },
    async loadParticipants() {
      if (!this.taskId) return
      try {
        const res = await listDispatchParticipants(this.taskId)
        if (res && res.code === 200) {
          this.participants = res.data || []
        } else {
          this.participants = []
        }
      } catch (error) {
        console.warn('加载参与方列表失败:', error)
        this.participants = []
      }
    },
    getExecutorDisplay(step) {
      if (!step) return '-'
      const executorId = step.executorId
      if (!executorId || !this.participants.length) {
        return step.executorName || step.executor || (executorId ? `ID:${executorId}` : '-')
      }
      // executorId 表示 dispatch_task_participant.id
      const matched = this.participants.find(p =>
        String(p.id) === String(executorId)
      )
      if (matched) {
        return matched.displayName || matched.personName || matched.memberName || this.getParticipantName(matched)
      }
      return step.executorName || step.executor || (executorId ? `ID:${executorId}` : '-')
    },
    getParticipantName(participant) {
      if (!participant) return '-'
      return participant.personName
        || participant.memberName
        || participant.displayName
        || (participant.personSnapshot && typeof participant.personSnapshot === 'object' 
          ? (participant.personSnapshot.name || participant.personSnapshot.personName || participant.personSnapshot.memberName)
          : (typeof participant.personSnapshot === 'string' 
            ? (() => {
              try {
                const snapshot = JSON.parse(participant.personSnapshot)
                return snapshot.name || snapshot.personName || snapshot.memberName
              } catch (e) {
                return null
              }
            })()
            : null))
        || '-'
    },
    getParticipantDisplayName(participant) {
      if (!participant) return '-'
      const name = this.getParticipantName(participant)
      const teamName = participant.teamName || 
        (participant.personSnapshot && typeof participant.personSnapshot === 'object' 
          ? participant.personSnapshot.teamName 
          : (typeof participant.personSnapshot === 'string' 
            ? (() => {
              try {
                const snapshot = JSON.parse(participant.personSnapshot)
                return snapshot.teamName
              } catch (e) {
                return null
              }
            })()
            : null))
      if (teamName) {
        return `${name} (${teamName})`
      }
      return name
    },
    findCurrentUserParticipantId() {
      const currentUserId = this.$store.getters.id
      if (!currentUserId || !this.participants || this.participants.length === 0) {
        return null
      }
      
      // 尝试通过 personId 匹配
      const matched = this.participants.find(p => 
        String(p.personId) === String(currentUserId) ||
        String(p.userId) === String(currentUserId)
      )
      if (matched) {
        return matched.id
      }
      
      // 如果找不到，尝试从 personSnapshot 中查找
      for (const p of this.participants) {
        if (p.personSnapshot) {
          try {
            const snapshot = typeof p.personSnapshot === 'string' 
              ? JSON.parse(p.personSnapshot) 
              : p.personSnapshot
            if (snapshot && (String(snapshot.userId) === String(currentUserId) || 
                String(snapshot.id) === String(currentUserId))) {
              return p.id
            }
          } catch (e) {
            // 忽略解析错误
          }
        }
      }
      
      return null
    },
    extractResourceInfo(link) {
      const info = { ...link }
      
      // 首先确定资源名称（参考 StepResourceAllocationDialog 的逻辑）
      let resourceName = `资源 #${link.resourceId}`
      
      // 1. 尝试从 note 的 snapshot 中获取
      if (link.note) {
        try {
          const snapshot = typeof link.note === 'string' ? JSON.parse(link.note) : link.note
          resourceName = snapshot.name || snapshot.materialName || snapshot.equipmentName || snapshot.vehicleName || resourceName
        } catch (e) {
          // If note is not JSON, use it as resourceName (for old format)
          if (link.resourceType === 'vehicle') {
            resourceName = link.note
          }
        }
      }
      
      // 2. 从 resourceSnapshot 获取
      if ((!resourceName || resourceName.startsWith('资源 #')) && link.resourceSnapshot) {
        try {
          const snapshot = typeof link.resourceSnapshot === 'string' 
            ? JSON.parse(link.resourceSnapshot) 
            : link.resourceSnapshot
          if (snapshot.name || snapshot.materialName || snapshot.equipmentName || snapshot.vehicleName) {
            resourceName = snapshot.name || snapshot.materialName || snapshot.equipmentName || snapshot.vehicleName
          }
        } catch (e) {
          // Ignore parse errors
        }
      }
      
      // 3. 从资源列表中查找（如果还没有找到）
      if ((!resourceName || resourceName.startsWith('资源 #')) && link.resourceId) {
        if (link.resourceType === 'material') {
          const material = this.availableMaterials.find(m => 
            m.id === link.resourceId || 
            String(m.id) === String(link.resourceId) ||
            Number(m.id) === Number(link.resourceId)
          )
          if (material) {
            resourceName = material.materialName
            // 同时获取单位
            if (!info.unit && material.unit) {
              info.unit = material.unit
            }
          }
        } else if (link.resourceType === 'equipment') {
          const equipment = this.availableEquipment.find(e => 
            e.id === link.resourceId || 
            String(e.id) === String(link.resourceId) ||
            Number(e.id) === Number(link.resourceId)
          )
          if (equipment) {
            resourceName = equipment.equipmentName
          }
        } else if (link.resourceType === 'vehicle') {
          const vehicle = this.availableVehicles.find(v => 
            v.id === link.resourceId || 
            String(v.id) === String(link.resourceId) ||
            Number(v.id) === Number(link.resourceId)
          )
          if (vehicle) {
            resourceName = vehicle.vehicleName || vehicle.plateNo
          }
        }
      }
      
      // 4. 使用 link.resourceName 作为后备
      if ((!resourceName || resourceName.startsWith('资源 #')) && link.resourceName) {
        resourceName = link.resourceName
      }
      
      info.resourceName = resourceName
      
      // 从 note 中提取其他信息
      if (link.note) {
        try {
          const snapshot = typeof link.note === 'string' ? JSON.parse(link.note) : link.note
          if (link.resourceType === 'material') {
            // InventoryAction uses 'qty' not 'quantity'
            info.quantity = snapshot.qty || snapshot.quantity
            info.warehouseId = snapshot.warehouseId
            // Extract usageMode from snapshot
            info.usageMode = snapshot.usageMode || 'occupy'
            // Unit 可能在 snapshot 中，如果还没有则从 material 中获取（已在上面处理）
            if (snapshot.unit && !info.unit) {
              info.unit = snapshot.unit
            }
          } else if (link.resourceType === 'equipment') {
            info.warehouseId = snapshot.warehouseId
            info.expectedFrom = snapshot.expectedFrom
            info.expectedUntil = snapshot.expectedUntil
            // 备注应该从 snapshot.notes 获取，不是 link.note
            info.notes = snapshot.notes || ''
          } else if (link.resourceType === 'vehicle') {
            // 检查是否是新的 JSON 格式
            if (snapshot.vehicleId !== undefined || (snapshot.route !== undefined && snapshot.route !== null)) {
              // New format: JSON snapshot
              info.route = snapshot.route || ''
              info.dispatchTime = snapshot.dispatchTime
              info.durationMinutes = snapshot.durationMinutes
              info.notes = snapshot.notes || ''
            } else {
              // Old format: plain string (was stored as route)
              info.route = link.note || ''
              info.notes = ''
            }
          }
        } catch (e) {
          // Not JSON, might be plain text (old format)
          if (link.resourceType === 'vehicle') {
            info.route = link.note || ''
            info.notes = ''
          }
        }
      }
      
      return info
    },
    resetState() {
      this.disposals = []
      this.disposalsLoading = false
      this.disposalDialogVisible = false
      this.currentDisposal = null
      this.disposalForm = {
        participantId: null,
        description: '',
        outcome: 'success',
        attachmentIds: ''
      }
      this.loadedStep = null
      this.participants = []
      this.resources = {
        materials: [],
        equipment: [],
        vehicles: []
      }
    },
    groupResources(list = []) {
      const groups = {
        materials: [],
        equipment: [],
        vehicles: []
      }
      list.forEach(item => {
        switch (item?.resourceType) {
          case 'material':
            groups.materials.push(item)
            break
          case 'equipment':
            groups.equipment.push(item)
            break
          case 'vehicle':
            groups.vehicles.push(item)
            break
          default:
            break
        }
      })
      return groups
    },
    formatStepStatus(status) {
      const map = {
        pending: '待执行',
        published: '待执行',
        in_progress: '执行中',
        completed: '已完成',
        done: '已完成',
        failed: '已失败',
        cancelled: '已取消'
      }
      return map[status] || status || '未知'
    },
    formatStepStatusTag(status) {
      const map = {
        pending: 'info',
        published: 'info',
        in_progress: 'warning',
        completed: 'success',
        done: 'success',
        failed: 'danger',
        cancelled: 'danger'
      }
      return map[status] || 'info'
    },
    getMaterialQuantity(resource) {
      if (resource.quantity !== undefined && resource.quantity !== null) {
        return resource.quantity
      }
      if (resource.note) {
        try {
          const snapshot = typeof resource.note === 'string' ? JSON.parse(resource.note) : resource.note
          return snapshot.qty || snapshot.quantity || '-'
        } catch (e) {
          return '-'
        }
      }
      return '-'
    },
    getMaterialUnit(resource) {
      return resource.unit || '-'
    },
    getWarehouseName(resource) {
      if (!resource.warehouseId) return '-'
      const warehouse = this.warehouses.find(w => 
        w.id === resource.warehouseId || 
        String(w.id) === String(resource.warehouseId) ||
        Number(w.id) === Number(resource.warehouseId)
      )
      return warehouse ? warehouse.warehouseName : '-'
    },
    getWarehouseDistance(resource) {
      if (!resource.warehouseId || !this.eventLocation) return '-'
      const warehouse = this.warehouses.find(w => 
        w.id === resource.warehouseId || 
        String(w.id) === String(resource.warehouseId) ||
        Number(w.id) === Number(resource.warehouseId)
      )
      if (!warehouse || !warehouse.latitude || !warehouse.longitude) return '-'
      
      const distance = this.calculateDistance(
        parseFloat(warehouse.latitude),
        parseFloat(warehouse.longitude),
        this.eventLocation.lat,
        this.eventLocation.lng
      )
      if (distance === null) return '-'
      
      if (distance < 1) {
        return `${(distance * 1000).toFixed(0)}m`
      } else {
        return `${distance.toFixed(1)}km`
      }
    },
    calculateDistance(lat1, lon1, lat2, lon2) {
      if (!lat1 || !lon1 || !lat2 || !lon2) return null
      
      const R = 6371 // Earth's radius in km
      const dLat = (lat2 - lat1) * Math.PI / 180
      const dLon = (lon2 - lon1) * Math.PI / 180
      const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
                Math.sin(dLon / 2) * Math.sin(dLon / 2)
      const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
      return R * c
    },
    formatDateTime(value) {
      if (!value) return '-'
      if (typeof value === 'string') {
        return value
      }
      return formatDateTimeUtil(value)
    },
    getStatusTagType(status) {
      const statusMap = {
        'locked': 'warning',
        'assigned': 'info',
        'busy': 'danger',
        'released': 'success',
        'consumed': 'danger',
        'returned': 'success',
        'unlocked': 'info'
      }
      return statusMap[status] || 'info'
    },
    getStatusLabel(status) {
      const labelMap = {
        'locked': '已锁定',
        'assigned': '已分配',
        'busy': '使用中',
        'released': '已释放',
        'consumed': '已消耗',
        'returned': '已归还',
        'unlocked': '已解锁'
      }
      return labelMap[status] || status || '-'
    },
    async handleMaterialAction(action, resource) {
      if (!resource || !resource.id) {
        this.$message.error('资源信息不完整')
        return
      }

      const actionMap = {
        release: {
          title: '释放物资',
          message: '确定要释放该物资的锁定吗？释放后可用数量将增加。',
          apiMethod: releaseMaterialLink
        },
        consume: {
          title: resource?.usageMode === 'occupy' ? '出库物资' : '消耗物资',
          message: resource?.usageMode === 'occupy' 
            ? '确定要出库该物资吗？出库后物资将从库存中扣除，之后可以进行归还操作。'
            : '消耗为不可逆操作，确定要消耗该物资吗？消耗后物资将从库存中扣除。',
          apiMethod: consumeMaterialLink
        },
        return: {
          title: '归还物资',
          message: '确定要归还该物资吗？归还后可用数量将增加。',
          apiMethod: returnMaterialLink
        }
      }

      const actionConfig = actionMap[action]
      if (!actionConfig) {
        this.$message.error('未知的操作类型')
        return
      }

      try {
        await this.$confirm(actionConfig.message, actionConfig.title, {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })

        this.processingLinkId = resource.id
        await actionConfig.apiMethod(this.taskId, resource.id)
        this.$message.success('操作成功')
        await this.fetchData()
      } catch (error) {
        if (error !== 'cancel') {
          console.error('Material action failed:', error)
          this.$message.error(error.msg || '操作失败')
        }
      } finally {
        this.processingLinkId = null
      }
    },
    canOperateMaterial(resource) {
      // 如果传入的是字符串（旧格式），转换为对象格式
      const status = typeof resource === 'string' ? resource : resource?.status
      const usageMode = typeof resource === 'object' ? resource?.usageMode : undefined
      
      // 锁定状态且根据使用模式判断是否可操作
      if (status === 'locked') {
        return usageMode === 'occupy' || usageMode === 'consume'
      }
      
      // 占用后归还模式：消耗后可以归还
      if (status === 'consumed' && usageMode === 'occupy') {
        return true
      }
      
      return false
    },
    async loadDisposals() {
      if (!this.taskId) return
      this.disposalsLoading = true
      try {
        const res = await listDispatchDisposals(this.taskId)
        if (res && res.code === 200) {
          // 过滤出当前行动项的处置记录
          this.disposals = (res.data || []).filter(d => 
            d.stepId && String(d.stepId) === String(this.stepId)
          )
        } else {
          this.disposals = []
        }
      } catch (error) {
        console.error('Failed to load disposals:', error)
        this.disposals = []
      } finally {
        this.disposalsLoading = false
      }
    },
    handleAddDisposal() {
      this.currentDisposal = null
      // 尝试找到当前登录用户对应的参与方ID作为默认值
      const defaultParticipantId = this.findCurrentUserParticipantId()
      this.disposalForm = {
        participantId: defaultParticipantId,
        description: '',
        outcome: 'success',
        attachmentIds: ''
      }
      this.disposalDialogVisible = true
    },
    handleEditDisposal(disposal) {
      this.currentDisposal = { ...disposal }
      // 解析附件ID列表
      let attachmentIds = ''
      if (disposal.attachmentIds) {
        try {
          const attachments = typeof disposal.attachmentIds === 'string' 
            ? JSON.parse(disposal.attachmentIds) 
            : disposal.attachmentIds
          if (Array.isArray(attachments)) {
            attachmentIds = attachments.map(a => typeof a === 'string' ? a : a.url || a.id || a).join(',')
          } else if (typeof attachments === 'string') {
            attachmentIds = attachments
          }
        } catch (e) {
          // 如果不是JSON，直接使用字符串
          attachmentIds = disposal.attachmentIds
        }
      }
      this.disposalForm = {
        participantId: disposal.participantId || null,
        description: disposal.description || '',
        outcome: disposal.outcome || 'success',
        attachmentIds: attachmentIds
      }
      this.disposalDialogVisible = true
    },
    handleDisposalSubmit() {
      this.$refs.disposalForm.validate((valid) => {
        if (valid) {
          this.handleDisposalSave(this.disposalForm)
        }
      })
    },
    async handleDeleteDisposal(disposal) {
      try {
        await this.$confirm('确定要删除该处置记录吗？', '删除确认', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        // TODO: 需要添加删除接口
        this.$message.warning('删除功能待实现')
        // await deleteDispatchDisposal(this.taskId, disposal.id)
        // this.$message.success('删除成功')
        // await this.loadDisposals()
      } catch (error) {
        if (error !== 'cancel') {
          console.error('Failed to delete disposal:', error)
        }
      }
    },
    async handleDisposalSave(disposalData) {
      try {
        // 使用表单中选择的参与方ID
        if (!disposalData.participantId) {
          this.$message.error('请选择参与方')
          return
        }

        // 处理附件ID列表：将逗号分隔的字符串转换为JSON数组
        let attachmentIds = null
        if (disposalData.attachmentIds && disposalData.attachmentIds.trim()) {
          const attachmentList = disposalData.attachmentIds.split(',').map(id => id.trim()).filter(id => id)
          if (attachmentList.length > 0) {
            attachmentIds = JSON.stringify(attachmentList)
          }
        }

        const saveData = {
          description: disposalData.description,
          outcome: disposalData.outcome,
          stepId: this.stepId,
          participantId: disposalData.participantId,
          attachmentIds: attachmentIds
        }

        if (this.currentDisposal && this.currentDisposal.id) {
          // 更新
          await updateDispatchDisposal(this.taskId, this.currentDisposal.id, saveData)
          this.$message.success('更新成功')
        } else {
          // 新增
          await addDispatchDisposal(this.taskId, saveData)
          this.$message.success('添加成功')
        }
        this.disposalDialogVisible = false
        await this.loadDisposals()
      } catch (error) {
        console.error('Failed to save disposal:', error)
        this.$message.error(error.msg || '保存失败')
      }
    },
    getOutcomeTagType(outcome) {
      const map = {
        'success': 'success',
        'partial': 'warning',
        'failed': 'danger'
      }
      return map[outcome] || 'info'
    },
    getOutcomeLabel(outcome) {
      const map = {
        'success': '完成',
        'partial': '部分完成',
        'failed': '未完成'
      }
      return map[outcome] || outcome || '-'
    },
    getDisposalAttachments(disposal) {
      if (!disposal || !disposal.attachmentIds) {
        return []
      }
      try {
        const attachments = typeof disposal.attachmentIds === 'string' 
          ? JSON.parse(disposal.attachmentIds) 
          : disposal.attachmentIds
        if (Array.isArray(attachments)) {
          return attachments
        }
        // 如果不是数组，尝试按逗号分割
        if (typeof attachments === 'string') {
          return attachments.split(',').map(id => id.trim()).filter(id => id)
        }
        return []
      } catch (e) {
        // 如果不是JSON，尝试按逗号分割
        if (typeof disposal.attachmentIds === 'string') {
          return disposal.attachmentIds.split(',').map(id => id.trim()).filter(id => id)
        }
        return []
      }
    },
    getAttachmentUrl(attachment) {
      const baseUrl = process.env.VUE_APP_BASE_API
      const url = typeof attachment === 'string' ? attachment : (attachment.url || attachment.id || attachment)
      return url.startsWith('http') ? url : `${baseUrl}${url.startsWith('/') ? url : '/' + url}`
    },
    getAttachmentName(attachment) {
      if (typeof attachment === 'string') {
        // 如果是字符串，提取文件名
        const parts = attachment.split('/')
        return parts[parts.length - 1] || attachment
      }
      return attachment.name || attachment.url || attachment.id || '附件'
    }
  }
}
</script>

<style lang="scss" scoped>
.step-detail-panel {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 0;
  padding: 16px;
  overflow: hidden;
}

.panel-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;

  h3 {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: #303133;
  }
}

.panel-body {
  overflow-y: auto;
  padding-right: 8px;
}

.loading-container {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.step-resource-section {
  margin-top: 16px;
}

.resource-table {
  margin-bottom: 16px;
}

.resource-table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;

  h4 {
    margin: 0;
    font-size: 14px;
    color: #303133;
  }

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

.action-buttons {
  display: flex;
  gap: 8px;
  align-items: center;
}

.disposal-card {
  margin-top: 16px;
}

.disposal-loading {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 20px;
  color: #909399;
  justify-content: center;
}

.disposal-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.disposal-item {
  padding: 12px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  background: #fafafa;
}

.disposal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.disposal-meta {
  display: flex;
  align-items: center;
  gap: 8px;
}

.disposal-time {
  font-size: 12px;
  color: #909399;
}

.disposal-actions {
  display: flex;
  gap: 8px;
}

.disposal-content {
  font-size: 14px;
  color: #606266;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
  margin-bottom: 8px;
}

.disposal-attachments {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid #ebeef5;
}

.attachments-title {
  font-size: 12px;
  color: #909399;
  margin-bottom: 8px;
}

.attachments-list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.attachment-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
}
</style>