<template>
  <view class="sub-page">
    <TopBar title="任务详情" show-back />

    <view v-if="loading" class="py-10 text-center">
      <text class="empty-text">加载中...</text>
    </view>

    <view v-else-if="task" class="px-4 py-4 space-y-3">
      <!-- 1. 施工流程进度条（与 admin 对齐：确认 + 7 张记录卡） -->
      <view class="flow-bar">
        <view class="flow-bar-bg"></view>
        <view class="flow-bar-fill" :style="{ width: flowProgress + '%' }"></view>
        <view v-for="(step, i) in FLOW_STEPS" :key="step.uiStep" class="flow-step-item">
          <view class="flow-step-dot" :class="flowDotClass(step.uiStep)">
            <text v-if="flowStepState(step.uiStep) === 'completed'" class="uni-icons uniui-checkmarkempty flow-step-check"></text>
            <text v-else-if="flowStepState(step.uiStep) === 'current'" class="uni-icons uniui-refresh-filled flow-step-spin"></text>
            <text v-else class="text-xs text-gray-400">{{ step.uiStep }}</text>
          </view>
          <text class="flow-step-label" :class="flowStepState(step.uiStep) !== 'pending' ? 'flow-step-label-active' : ''">{{ step.title }}</text>
        </view>
      </view>

      <!-- 2. 操作区 -->
      <!-- 待确认 -->
      <view v-if="isPendingConfirm" class="action-card">
        <view class="action-banner action-banner-blue">
          <text class="uni-icons uniui-flag-filled action-banner-icon text-blue-500"></text>
          <text class="action-banner-title">待确认任务</text>
          <text class="action-banner-desc">请查看任务详情，确认是否接受</text>
          <view class="action-summary">
            <view class="action-summary-row">
              <text class="action-summary-label">任务类型</text>
              <text class="action-summary-value">{{ constructionTypeText }}</text>
            </view>
            <view class="action-summary-row">
              <text class="action-summary-label">服务时间</text>
              <text class="action-summary-value">{{ serviceTimeText }}</text>
            </view>
          </view>
        </view>
        <view class="action-btn-list">
          <button class="action-main-btn action-main-btn--confirm" hover-class="action-main-btn-hover" :disabled="submitting" @click="onConfirm">
            <text class="uni-icons uniui-checkmarkempty action-main-btn__icon"></text>
            <text>确认任务</text>
          </button>
          <button class="action-main-btn action-main-btn--feedback" hover-class="action-main-btn-hover" @click="onFeedback">
            <text class="uni-icons uniui-compose action-main-btn__icon"></text>
            <text>反馈问题</text>
          </button>
          <button class="action-main-btn action-main-btn--reject" hover-class="action-main-btn-hover" @click="onReject">
            <text class="uni-icons uniui-close action-main-btn__icon"></text>
            <text>拒绝任务</text>
          </button>
        </view>
      </view>

      <!-- 已拒绝 / 已取消 -->
      <view v-else-if="task.status === 'rejected' || task.status === 'cancelled'" class="action-card">
        <view class="action-banner action-banner-red">
          <text class="uni-icons uniui-close action-banner-icon text-red-500"></text>
          <text class="action-banner-title">{{ task.status === 'rejected' ? '任务已拒绝' : '任务已取消' }}</text>
          <text v-if="task.cancelReason" class="action-banner-desc">原因：{{ task.cancelReason }}</text>
        </view>
      </view>

      <!-- 已完成 -->
      <view v-else-if="task.status === 'completed'" class="action-card">
        <view class="action-banner action-banner-green">
          <text class="uni-icons uniui-checkmarkempty action-banner-icon text-green-500"></text>
          <text class="action-banner-title">任务已完成</text>
          <text v-if="task.completionTime" class="action-banner-desc">完成时间：{{ formatDate(task.completionTime, 'YYYY-MM-DD HH:mm') }}</text>
        </view>
      </view>

      <!-- 3. 任务信息折叠区 -->
      <view class="info-section">
        <view class="info-section-title" @click="sections.info = !sections.info">
          <text class="uni-icons uniui-flag-filled text-green-500 text-base"></text>
          <text class="text-base font-semibold text-gray-800 flex-1 truncate">{{ taskName }}</text>
          <StatusTag :status="task.status" class="ml-2" />
          <text class="uni-icons text-gray-400 text-xs ml-2" :class="sections.info ? 'uniui-arrow-up' : 'uniui-arrow-down'"></text>
        </view>
        <view v-if="sections.info" class="info-section-content">
          <!-- 项目信息 -->
          <view v-if="project" class="info-block">
            <view class="info-block-title">
              <text class="uni-icons uniui-home-filled text-green-500 text-sm"></text>
              <text>项目信息</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">项目名称</text>
              <text class="info-row-value">{{ project.projectName || task.projectName || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">合作类型</text>
              <text class="info-row-value">{{ coopTypeText || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">项目地址</text>
              <text class="info-row-value">{{ projectAddress || task.address || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">项目联系人</text>
              <text class="info-row-value">{{ project.primaryContactName || task.primaryContactName || '-' }} {{ project.primaryContactPhone || task.primaryContactPhone || '' }}</text>
            </view>
          </view>

          <!-- 施工信息 -->
          <view class="info-block">
            <view class="info-block-title">
              <text class="uni-icons uniui-settings-filled text-blue-500 text-sm"></text>
              <text>施工信息</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">施工类型</text>
              <text class="info-row-value">{{ constructionTypeText || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">设施类型</text>
              <text class="info-row-value">{{ getFacilityTypeText(task.constructionFacility || task.facilityType) }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">服务方式</text>
              <text class="info-row-value">{{ getServiceMethodText(task.serviceMethod) }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">服务时间</text>
              <text class="info-row-value text-xs">{{ serviceTimeText }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">施工地址</text>
              <text class="info-row-value">{{ task.address || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">地理定位</text>
              <text class="info-row-value link-text" @click="openMap">{{ geoLocationText || '-' }}</text>
            </view>
          </view>

          <!-- 故障信息 -->
          <view class="info-block">
            <view class="info-block-title">
              <text class="uni-icons uniui-info-filled text-orange-500 text-sm"></text>
              <text>故障信息</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">故障位置</text>
              <text class="info-row-value">{{ task.faultLocation || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">故障描述</text>
              <text class="info-row-value">{{ faultDescText || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">客户原话</text>
              <text class="info-row-value">{{ task.customerWords || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">故障图片</text>
              <view class="info-row-value">
                <view v-if="faultMedia.length > 0" class="flex flex-wrap gap-2">
                  <image
                    v-for="(url, index) in faultMedia"
                    :key="index"
                    :src="url"
                    class="w-16 h-16 rounded-lg bg-gray-100"
                    mode="aspectFill"
                    @click="previewMedia(index)"
                  />
                </view>
                <text v-else>-</text>
              </view>
            </view>
          </view>

          <!-- 施工要求 -->
          <view class="info-block info-block-last">
            <view class="info-block-title">
              <text class="uni-icons uniui-checkmarkempty text-blue-500 text-sm"></text>
              <text>施工要求</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">取水距离</text>
              <text class="info-row-value">{{ getWaterDistanceText(task.waterDistance) }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">化粪池排口</text>
              <text class="info-row-value">{{ outletNormalText }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">施工助力</text>
              <text class="info-row-value">{{ task.assistantInfo || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">预计作业量</text>
              <text class="info-row-value">{{ task.estimatedWorkload || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">预计工时</text>
              <text class="info-row-value">{{ task.estimatedDuration || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">验收要求</text>
              <text class="info-row-value">{{ task.acceptanceRequirement || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">验收方式</text>
              <text class="info-row-value">{{ getAcceptanceMethodText(task.acceptanceMethod) }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">注意要点</text>
              <text class="info-row-value">{{ task.attentionPoint || '-' }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">工具要求</text>
              <text class="info-row-value">{{ getSuggestedVehicleText(task.toolRequirement) }}</text>
            </view>
            <view class="info-row">
              <text class="info-row-label">是否关联前期施工</text>
              <text class="info-row-value">{{ hasPreviousWorkText }}</text>
            </view>
          </view>

          <!-- 甲方确认人 -->
          <view class="info-block info-block-last pt-4">
            <view class="info-block-title">
              <text class="uni-icons uniui-person-filled text-green-500 text-sm"></text>
              <text>甲方确认人</text>
            </view>
            <view v-for="(contact, index) in partyAContacts" :key="index" class="info-row info-row-contact">
              <text class="info-row-label">联系人</text>
              <view class="info-row-value flex items-center justify-end gap-2">
                <text>{{ contact.name }} {{ contact.phone }}</text>
                <button v-if="contact.phone" class="phone-btn-mini" @click="callPhone(contact.phone)">
                  <text class="uni-icons uniui-phone-filled phone-icon-mini"></text>
                </button>
              </view>
            </view>
            <view v-if="partyAContacts.length === 0" class="info-row">
              <text class="info-row-label">联系人</text>
              <text class="info-row-value">-</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 4. 施工流程记录（与 admin RECORD_STEPS 对齐，并行可编辑） -->
      <view class="record-section">
        <view class="record-section-title">
          <text class="uni-icons uniui-list text-blue-500 text-base mr-2"></text>
          <text class="text-base font-semibold text-gray-800">施工流程记录</text>
        </view>

        <view
          v-for="step in recordSteps"
          :key="step.uiStep"
          class="record-card"
          :class="recordCardClass(step.uiStep)"
        >
          <view class="record-card-header">
            <view class="flex items-center gap-2">
              <text class="record-step-number" :class="recordStepNumberClass(step.uiStep)">{{ step.uiStep - 1 }}</text>
              <text class="record-step-title">{{ step.title }}</text>
            </view>
            <text class="record-step-status" :class="recordStepStatusClass(step.uiStep)">{{ recordStepStatusText(step.uiStep) }}</text>
          </view>

          <view class="record-card-body">
            <text v-if="step.description" class="record-step-desc">{{ step.description }}</text>

            <!-- 文本输入（仅堵塞物 / 设施反馈） -->
            <view v-if="step.input" class="record-input-wrap">
              <text class="record-input-label">{{ step.input.label }}</text>
              <textarea
                v-if="step.input.stateKey === 'feedbackText'"
                v-model="feedbackText"
                class="form-textarea"
                :placeholder="step.input.placeholder"
                :disabled="!taskActive"
              />
              <textarea
                v-else
                v-model="blockageText"
                class="form-textarea text-xs"
                style="min-height: 48px;"
                :placeholder="step.input.placeholder"
                :disabled="!taskActive"
              />
            </view>

            <!-- 各 phase 照片上传 -->
            <view v-for="phase in step.phases" :key="phase.phase" class="record-phase-wrap">
              <view class="record-phase-header">
                <text class="record-phase-title">{{ phase.title }}</text>
                <text class="record-phase-count" :class="phasePhotoCount(phase.phase) > 0 ? 'record-phase-count-done' : ''">
                  {{ phasePhotoCount(phase.phase) > 0 ? `已上传 ${phasePhotoCount(phase.phase)} 张` : '待上传' }}
                </text>
              </view>
              <text v-if="phase.description" class="record-phase-desc">{{ phase.description }}</text>
              <ImageUploader
                :model-value="photosMap[phase.phase] || []"
                @update:model-value="handlePhotoUpload(phase.phase, $event)"
                :max-count="phase.maxCount"
                type="taskPhoto"
                :task-id="taskId"
                :step="step.backendCode"
                :phase="phase.phase"
                :tip="`上传${phase.title}照片`"
                :disabled="!taskActive"
              />
            </view>
          </view>
        </view>
      </view>

      <!-- 5. 完成任务按钮（与 admin 对齐：所有记录卡完成后统一提交） -->
      <view v-if="taskActive" class="complete-card">
        <view class="complete-summary">
          <text :class="isAllRecordStepsComplete ? 'complete-summary-done' : 'complete-summary-pending'">
            {{ isAllRecordStepsComplete ? '所有步骤已完成，可以提交任务' : `已完成 ${completedRecordStepCount}/${recordSteps.length} 个步骤` }}
          </text>
        </view>
        <button
          class="complete-btn"
          :class="!isAllRecordStepsComplete || submitting ? 'complete-btn-disabled' : ''"
          hover-class="complete-btn-hover"
          :disabled="!isAllRecordStepsComplete || submitting"
          @click="handleCompleteTask"
        >
          <text class="uni-icons uniui-checkmarkempty complete-btn__icon"></text>
          <text>完成任务</text>
        </button>
      </view>

      <!-- 6. 处理记录 -->
      <view v-if="timelineRecords.length > 0" class="log-section">
        <view class="log-section-title" @click="logExpanded = !logExpanded">
          <text class="uni-icons uniui-reload text-green-500 text-base mr-2"></text>
          <text class="text-base font-semibold text-gray-800 flex-1">处理记录</text>
          <text
            class="uni-icons text-gray-400 text-xs transition-transform"
            :class="logExpanded ? 'uniui-arrow-up' : 'uniui-arrow-down'"
          ></text>
        </view>
        <view v-if="logExpanded" class="p-2">
          <Timeline :records="timelineRecords" />
        </view>
      </view>
    </view>

    <EmptyState v-else message="任务不存在" />
  </view>
</template>

<script setup lang="ts">
import { computed, reactive, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import TopBar from '../../components/common/TopBar.vue'
import StatusTag from '../../components/common/StatusTag.vue'
import EmptyState from '../../components/common/EmptyState.vue'
import ImageUploader from '../../components/common/ImageUploader.vue'
import Timeline from '../../components/common/Timeline.vue'
import type { TimelineRecord } from '../../components/common/Timeline.vue'
import {
  formatDate,
  showToast,
  getConstructionTypeText,
  getFacilityTypeText,
  getServiceMethodText,
  getWaterDistanceText,
  getAcceptanceMethodText,
  getSuggestedVehicleText,
  getCooperationTypeText,
  formatTaskLogAction,
  getTaskLogRole,
} from '../../utils'
import { useAuthStore } from '../../stores/auth'
import { getTaskDetail, executeSopStep, completeTask, updateTask, addTaskLog, type ExecuteSopStepData } from '../../api/task'
import { getTaskPhotos, type TaskPhoto } from '../../api/file'
import type { UploaderPhoto } from '../../components/common/ImageUploader.vue'
import { getProjectDetail } from '../../api/project'
import {
  FLOW_STEPS,
  RECORD_STEPS,
  getPhaseLabel,
  getPhaseDescription,
  getPhaseMaxCount,
  isRecordStepComplete,
  isAllRecordStepsComplete as isAllRecordStepsCompleteFn,
  completedRecordStepCount as completedRecordStepCountFn,
  getFlowStepState,
  computeFlowProgress,
  type RecordStepDef,
} from '../../constants/sop'

const task = ref<any>(null)
const authStore = useAuthStore()
const project = ref<any>(null)
const loading = ref(false)
const submitting = ref(false)
const taskId = ref<number>(0)

const photosMap = ref<Record<string, UploaderPhoto[]>>({})
const blockageText = ref('')
const feedbackText = ref('')

const sections = reactive({
  info: true,
})
const logExpanded = ref(true)

const ALL_PHASES = [
  'departure_vehicle',
  'parking_sign',
  'site_survey',
  'blockage',
  'construction_process',
  'construction_complete',
  'site_cleaning',
  'acceptance',
]

const currentStep = computed(() => Number(task.value?.currentStep) || 0)
const taskActive = computed(() => task.value ? !['completed', 'cancelled', 'rejected'].includes(task.value.status || '') : false)
const isPendingConfirm = computed(() => task.value?.status === 'assigned' && currentStep.value === 0)
const taskLogs = computed(() => task.value?.logList || [])

const timelineRecords = computed<TimelineRecord[]>(() => {
  const logs: any[] = taskLogs.value
  return logs.map(log => ({
    action: formatTaskLogAction(log.operationType || log.action, log.operation),
    time: log.createTime ? formatDate(log.createTime, 'YYYY-MM-DD HH:mm') : '',
    operator: log.operatorName || log.operator || log.createBy || '系统',
    role: log.operatorRole || getTaskLogRole(log.operationType || log.action),
  }))
})

const recordSteps = computed(() => RECORD_STEPS)

/** 扁平化照片列表，供共享进度函数使用 */
const flatPhotos = computed(() => {
  const list: { phase?: string; photoUrl?: string }[] = []
  Object.entries(photosMap.value).forEach(([phase, photos]) => {
    photos.forEach((p) => list.push({ phase, photoUrl: typeof p === 'string' ? p : p.url }))
  })
  return list
})

const completedRecordStepCount = computed(() => completedRecordStepCountFn(flatPhotos.value))
const isAllRecordStepsComplete = computed(() => isAllRecordStepsCompleteFn(flatPhotos.value))

function flowDotClass(uiStep: number): string {
  const state = flowStepState(uiStep)
  if (state === 'completed') return 'flow-step-dot-completed'
  if (state === 'current') return 'flow-step-dot-current'
  return ''
}

const flowProgress = computed(() => computeFlowProgress(task.value, flatPhotos.value))

function flowStepState(uiStep: number): 'completed' | 'current' | 'pending' {
  return getFlowStepState(task.value, flatPhotos.value, uiStep)
}

function recordCardClass(uiStep: number): string {
  if (isRecordStepComplete(flatPhotos.value, uiStep)) return 'record-card-done'
  if (flowStepState(uiStep) === 'current') return 'record-card-current'
  return 'record-card-pending'
}

function recordStepNumberClass(uiStep: number): string {
  if (isRecordStepComplete(flatPhotos.value, uiStep)) return 'record-step-number-done'
  if (flowStepState(uiStep) === 'current') return 'record-step-number-current'
  return 'record-step-number-pending'
}

function recordStepStatusClass(uiStep: number): string {
  if (isRecordStepComplete(flatPhotos.value, uiStep)) return 'record-step-status-done'
  if (flowStepState(uiStep) === 'current') return 'record-step-status-current'
  return 'record-step-status-pending'
}

function recordStepStatusText(uiStep: number): string {
  if (isRecordStepComplete(flatPhotos.value, uiStep)) return '已完成'
  if (flowStepState(uiStep) === 'current') return '进行中'
  return '待执行'
}

function phasePhotoCount(phase: string): number {
  return (photosMap.value[phase] || []).length
}

const extra = computed(() => {
  if (!task.value?.extraData) return {} as any
  try {
    return JSON.parse(task.value.extraData)
  } catch {
    return {} as any
  }
})

const taskName = computed(() => {
  if (!task.value) return ''
  return task.value.taskName || task.value.serviceContent || task.value.faultLocation || taskTypeText(task.value.taskType) || '未命名任务'
})

const constructionTypeText = computed(() => {
  if (!task.value) return ''
  const raw = task.value.constructionType || taskTypeText(task.value.taskType)
  return raw ? getConstructionTypeText(raw) : '-'
})

const serviceTimeText = computed(() => {
  if (!task.value) return '待定'
  const expected = (task.value as any).expectedArrivalTime
  if (expected) return formatDate(expected, 'YYYY-MM-DD HH:mm')
  const planDate = task.value.planDate || ''
  const planEndDate = (task.value as any).planEndDate || ''
  if (planDate && planEndDate && planDate !== planEndDate) return `${planDate} 至 ${planEndDate}`
  const rangeMap: Record<string, string> = { morning: '上午', afternoon: '下午', evening: '晚上' }
  const range = rangeMap[task.value.planTimeRange] || task.value.planTimeRange || ''
  return planDate || range ? `${planDate} ${range}`.trim() : '待定'
})

const coopTypeText = computed(() => {
  return getCooperationTypeText(project.value?.cooperationType)
})

const projectAddress = computed(() => {
  if (!project.value) return ''
  const p = project.value
  return [p.province, p.city, p.district, p.street, p.detailAddress || p.address].filter(Boolean).join('') || p.address || ''
})

const faultDescText = computed(() => {
  if (!task.value) return ''
  return task.value.serviceContent || [task.value.faultType, task.value.customerWords].filter(Boolean).join('；') || ''
})

const outletNormalText = computed(() => {
  const v = task.value?.outletNormal
  if (v === 1 || v === '1' || v === true) return '正常'
  if (v === 0 || v === '0' || v === false) return '异常'
  return '-'
})

const hasPreviousWorkText = computed(() => {
  const v = (task.value as any)?.hasPreviousWork
  if (v === 1 || v === '1' || v === true) return '是'
  if (v === 0 || v === '0' || v === false) return '否'
  return '-'
})

const geoLocationText = computed(() => {
  if (extra.value.geoLocation) return extra.value.geoLocation
  if (extra.value.latitude && extra.value.longitude) return `${extra.value.latitude}, ${extra.value.longitude}`
  return ''
})

const faultMedia = computed<string[]>(() => {
  const photos = extra.value.photos || extra.value.faultPhotos || extra.value.media
  if (!photos) return []
  if (Array.isArray(photos)) return photos
  return String(photos).split(',').filter(Boolean)
})

const partyAContacts = computed<Array<{ name: string; phone: string }>>(() => {
  const list = extra.value.partyAContacts || extra.value.partyA
  if (!list) return []
  if (Array.isArray(list)) return list
  return []
})

function taskTypeText(type: string): string {
  const map: Record<string, string> = {
    dredge: '疏通', repair: '维修', clean: '清掏', inspect: '检查', emergency: '应急',
    '疏通': '疏通', '维修': '维修', '清掏': '清掏', '检查': '检查', '应急': '应急',
  }
  return type ? map[type] || type : ''
}

function callPhone(phone: string) {
  if (!phone) return
  uni.makePhoneCall({ phoneNumber: phone })
}

function openMap() {
  const lat = Number(extra.value.latitude)
  const lng = Number(extra.value.longitude)
  if (!lat || !lng) return
  uni.openLocation({ latitude: lat, longitude: lng, name: task.value?.faultLocation || '故障位置' })
}

function previewMedia(index: number) {
  uni.previewImage({ urls: faultMedia.value, current: index })
}

function emptyPhotos(): Record<string, UploaderPhoto[]> {
  const map: Record<string, UploaderPhoto[]> = {}
  ALL_PHASES.forEach((phase) => { map[phase] = [] })
  return map
}

onLoad((options) => {
  if (options?.id) {
    taskId.value = Number(options.id)
    loadDetail()
  }
})

async function loadDetail() {
  loading.value = true
  try {
    const res: any = await getTaskDetail(taskId.value)
    task.value = res
    if (res?.projectId) {
      getProjectDetail(res.projectId).then(p => { project.value = p }).catch(() => {})
    }
    await loadPhotos()
  } catch (e) {
    console.error('加载任务详情失败', e)
    showToast('加载任务详情失败')
  } finally {
    loading.value = false
  }
}

async function loadPhotos() {
  try {
    const list: TaskPhoto[] = await getTaskPhotos(taskId.value)
    const grouped = emptyPhotos()
    list.forEach((photo) => {
      const phase = photo.phase || ''
      if (!grouped[phase]) return
      grouped[phase].push({
        id: photo.photoId,
        url: photo.photoUrl || '',
      })
    })
    photosMap.value = grouped
  } catch (e) {
    console.error('加载任务照片失败', e)
  }
}

function handlePhotoUpload(phase: string, photos: Array<string | UploaderPhoto>) {
  photosMap.value[phase] = photos
    .map((p) => (typeof p === 'string' ? { url: p } : p))
    .filter((p): p is UploaderPhoto => !!p.url)
}

async function handleCompleteTask() {
  if (!isAllRecordStepsComplete.value) {
    showToast('请完成所有步骤的照片上传')
    return
  }

  submitting.value = true
  try {
    const remarkParts: string[] = []
    if (blockageText.value.trim()) remarkParts.push(`堵塞物: ${blockageText.value.trim()}`)
    if (feedbackText.value.trim()) remarkParts.push(`设施反馈: ${feedbackText.value.trim()}`)
    const remark = remarkParts.join('；') || undefined

    // 与 admin 对齐：按顺序执行后端 SOP 步骤（已执行过的步骤由后端忽略）
    const backendCodes = ['confirm', 'prepare', 'arrive', 'work', 'photo', 'clean', 'accept']
    for (const stepCode of backendCodes) {
      const data: ExecuteSopStepData = {
        taskId: taskId.value,
        stepCode,
        action: 'execute',
        operatorId: authStore.user?.id ? Number(authStore.user.id) : undefined,
        operatorName: authStore.user?.name,
      }
      if (remark) data.remark = remark
      await executeSopStep(data)
    }

    await completeTask(taskId.value, {
      taskId: taskId.value,
      remark,
      operatorId: authStore.user?.id ? Number(authStore.user.id) : undefined,
      operatorName: authStore.user?.name,
    })

    showToast('任务已完成')
    blockageText.value = ''
    feedbackText.value = ''
    await loadDetail()
  } catch (e) {
    console.error('完成任务失败', e)
  } finally {
    submitting.value = false
  }
}

function onConfirm() {
  submitting.value = true
  const data: ExecuteSopStepData = {
    taskId: taskId.value,
    stepCode: 'confirm',
    action: 'execute',
    operatorId: authStore.user?.id ? Number(authStore.user.id) : undefined,
    operatorName: authStore.user?.name,
  }
  executeSopStep(data)
    .then(() => {
      showToast('任务已确认')
      loadDetail()
    })
    .catch((e) => {
      console.error('确认任务失败', e)
    })
    .finally(() => {
      submitting.value = false
    })
}

async function onReject() {
  const res = await new Promise<any>((resolve) => {
    uni.showModal({
      title: '拒绝任务',
      editable: true,
      placeholderText: '请输入拒绝原因（可选）',
      confirmText: '确认拒绝',
      success: resolve,
      fail: () => resolve({ confirm: false }),
    })
  })
  if (!res.confirm) return
  submitting.value = true
  try {
    const t = task.value
    await updateTask(taskId.value, {
      taskNo: t.taskNo,
      address: t.address,
      taskType: t.taskType,
      projectId: t.projectId,
      planDate: t.planDate,
      status: 'rejected',
      remark: res.content || t.remark || '',
    } as any)

    await addTaskLog(taskId.value, {
      operationType: 'reject',
      operation: '拒绝任务',
      remark: res.content?.trim() || '',
      operatorId: authStore.user?.id ? Number(authStore.user.id) : undefined,
      operatorName: authStore.user?.name,
    })

    showToast('已拒绝任务')
    await loadDetail()
  } catch (e) {
    console.error('拒绝任务失败', e)
    showToast('拒绝任务失败')
  } finally {
    submitting.value = false
  }
}

async function onFeedback() {
  const res = await new Promise<any>((resolve) => {
    uni.showModal({
      title: '反馈问题',
      editable: true,
      placeholderText: '请描述遇到的问题，将提交给调度中心处理',
      confirmText: '提交',
      success: resolve,
      fail: () => resolve({ confirm: false }),
    })
  })
  if (!res.confirm) return

  const content = res.content?.trim()
  if (!content) {
    showToast('请输入反馈内容')
    return
  }

  submitting.value = true
  try {
    await addTaskLog(taskId.value, {
      operationType: 'feedback',
      operation: '反馈问题',
      remark: content,
      operatorId: authStore.user?.id ? Number(authStore.user.id) : undefined,
      operatorName: authStore.user?.name,
    })
    showToast('反馈已提交')
    await loadDetail()
  } catch (e) {
    console.error('提交反馈失败', e)
    showToast('反馈提交失败')
  } finally {
    submitting.value = false
  }
}
</script>

<style scoped>
/* 页面外壳 */
.sub-page {
  max-width: 430px;
  margin: 0 auto;
  min-height: 100vh;
  background-color: #f6fbf9;
  padding-bottom: 96px;
}

.empty-text {
  font-size: 13px;
  color: #9ca3af;
}

/* 流程条 */
.flow-bar {
  background-color: #fff;
  border-radius: 16px;
  padding: 18px 10px 14px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  position: relative;
}
.flow-bar-bg {
  position: absolute;
  top: 31px;
  left: 28px;
  right: 28px;
  height: 3px;
  background-color: #e5e7eb;
  border-radius: 2px;
  z-index: 0;
}
.flow-bar-fill {
  position: absolute;
  top: 31px;
  left: 28px;
  height: 3px;
  background: linear-gradient(90deg, #368f6f 0%, #5ab8d0 100%);
  border-radius: 2px;
  z-index: 0;
  transition: width 0.3s ease;
}
.flow-step-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 1;
  width: 34px;
}
.flow-step-dot {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-color: #fff;
  border: 2px solid #d1d5db;
  display: flex;
  align-items: center;
  justify-content: center;
}
.flow-step-dot-completed {
  background-color: #368f6f;
  border-color: #368f6f;
}
.flow-step-dot-current {
  background-color: #fff;
  border-color: #368f6f;
  box-shadow: 0 0 0 3px rgba(54, 143, 111, 0.15);
}
.flow-step-check {
  color: #fff;
  font-size: 12px;
}
.flow-step-spin {
  color: #368f6f;
  font-size: 12px;
}
.flow-step-label {
  margin-top: 6px;
  font-size: 10px;
  color: #9ca3af;
  text-align: center;
  line-height: 1.2;
}
.flow-step-label-active {
  color: #368f6f;
  font-weight: 500;
}

/* 操作区卡片 */
.action-card {
  background-color: #fff;
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.action-banner {
  border-radius: 12px;
  padding: 18px 16px;
  text-align: center;
}
.action-banner-blue {
  background-color: #eff6ff;
}
.action-banner-green {
  background-color: #f0fdf4;
}
.action-banner-red {
  background-color: #fef2f2;
}
.action-banner-icon {
  font-size: 40px;
  line-height: 1;
  margin-bottom: 8px;
  display: block;
}
.action-banner-title {
  display: block;
  font-size: 16px;
  font-weight: 600;
  color: #1f2937;
}
.action-banner-desc {
  display: block;
  font-size: 12px;
  color: #6b7280;
  margin-top: 4px;
}
.action-summary {
  background-color: #fff;
  border-radius: 8px;
  padding: 10px 12px;
  margin-top: 14px;
  text-align: left;
}
.action-summary-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 13px;
}
.action-summary-row:not(:last-child) {
  margin-bottom: 6px;
}
.action-summary-label {
  color: #9ca3af;
}
.action-summary-value {
  color: #1f2937;
  font-weight: 500;
}

.action-btn-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 14px;
}
.action-main-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
  line-height: 44px;
  border: 1px solid transparent;
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.action-main-btn::after {
  border: none;
}
.action-main-btn__icon {
  font-size: 16px;
  margin-right: 6px;
}
.action-main-btn-hover {
  transform: scale(0.98);
  opacity: 0.9;
}
.action-main-btn--confirm {
  background: linear-gradient(135deg, #368f6f 0%, #5ab8d0 100%);
  color: #ffffff;
  box-shadow: 0 8px 20px -8px rgba(54, 143, 111, 0.5);
}
.action-main-btn--feedback {
  background-color: #fffbeb;
  border-color: #fcd34d;
  color: #d97706;
}
.action-main-btn--reject {
  background-color: #fef2f2;
  border-color: #fca5a5;
  color: #dc2626;
}

/* 任务信息折叠区 */
.info-section {
  background-color: #fff;
  border-radius: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
  overflow: hidden;
}
.info-section-title {
  padding: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.info-section-content {
  padding: 0 16px 16px;
}
.info-block {
  padding: 14px 0;
  border-bottom: 1px solid #f3f4f6;
}
.info-block-last {
  border-bottom: none;
}
.info-block-title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: #6b7280;
  margin-bottom: 12px;
}
.info-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  font-size: 13px;
  padding: 5px 0;
}
.info-row-label {
  color: #9ca3af;
  flex-shrink: 0;
  margin-right: 12px;
}
.info-row-value {
  color: #1f2937;
  text-align: right;
  flex: 1;
}
.info-row-contact {
  align-items: center;
}
.link-text {
  color: #368f6f;
}
.tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.4;
}
.tag-blue {
  background-color: #eff6ff;
  color: #2563eb;
}

/* 电话按钮 */
.phone-btn-mini {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(54, 143, 111, 0.1);
  margin-left: 8px;
  flex-shrink: 0;
}
.phone-btn-mini::after {
  border: none;
}
.phone-icon-mini {
  font-size: 14px;
  color: #368f6f;
}

/* 施工流程记录 */
.record-section {
  background-color: #fff;
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.record-section-title {
  display: flex;
  align-items: center;
  margin-bottom: 14px;
}
.record-card {
  border-radius: 12px;
  padding: 12px;
  margin-bottom: 10px;
  border: 1px solid #e5e7eb;
  background-color: #f9fafb;
}
.record-card:last-child {
  margin-bottom: 0;
}
.record-card-done {
  background-color: #f0fdf4;
  border-color: #bbf7d0;
}
.record-card-current {
  background-color: #fff;
  border-color: #368f6f;
  box-shadow: 0 0 0 1px rgba(54, 143, 111, 0.1);
}
.record-card-pending {
  opacity: 0.75;
}
.record-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.record-step-number {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  background-color: #f97316;
}
.record-step-number-done {
  background-color: #368f6f;
}
.record-step-number-current {
  background-color: #368f6f;
}
.record-step-number-pending {
  background-color: #9ca3af;
}
.record-step-title {
  font-size: 14px;
  font-weight: 500;
  color: #1f2937;
}
.record-step-status {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 9999px;
}
.record-step-status-done {
  background-color: #dcfce7;
  color: #166534;
}
.record-step-status-current {
  background-color: #dbeafe;
  color: #1e40af;
}
.record-step-status-pending {
  background-color: #e5e7eb;
  color: #4b5563;
}
.record-card-body {
  margin-top: 10px;
}
.record-step-desc {
  display: block;
  font-size: 12px;
  color: #6b7280;
  margin-bottom: 10px;
  line-height: 1.5;
}
.record-input-wrap {
  margin-bottom: 12px;
}
.record-input-label {
  display: block;
  font-size: 12px;
  color: #6b7280;
  margin-bottom: 6px;
}
.record-phase-wrap {
  margin-bottom: 12px;
}
.record-phase-wrap:last-child {
  margin-bottom: 0;
}
.record-phase-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}
.record-phase-title {
  font-size: 13px;
  font-weight: 500;
  color: #1f2937;
}
.record-phase-count {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 9999px;
  background-color: #e5e7eb;
  color: #4b5563;
}
.record-phase-count-done {
  background-color: #dcfce7;
  color: #166534;
}
.record-phase-desc {
  display: block;
  font-size: 11px;
  color: #9ca3af;
  margin-bottom: 8px;
  line-height: 1.4;
}

/* 完成任务卡片 */
.complete-card {
  background-color: #fff;
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.complete-summary {
  text-align: center;
  margin-bottom: 12px;
  font-size: 13px;
}
.complete-summary-done {
  color: #368f6f;
  font-weight: 500;
}
.complete-summary-pending {
  color: #d97706;
}
.complete-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 46px;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 600;
  color: #ffffff;
  background: linear-gradient(135deg, #368f6f 0%, #4ba98a 100%);
  box-shadow: 0 10px 24px -10px rgba(54, 143, 111, 0.5);
  line-height: 1.4;
}
.complete-btn::after {
  border: none;
}
.complete-btn-hover {
  opacity: 0.9;
}
.complete-btn-disabled {
  background: #e5e7eb;
  color: #9ca3af;
  box-shadow: none;
}
.complete-btn__icon {
  font-size: 16px;
  margin-right: 6px;
}

/* 任务日志 */
.log-section {
  background-color: #fff;
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.log-section-title {
  display: flex;
  align-items: center;
  margin-bottom: 14px;
}
.log-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.log-item {
  display: flex;
  align-items: flex-start;
  font-size: 13px;
}
.log-time {
  color: #9ca3af;
  width: 72px;
  flex-shrink: 0;
}
.log-remark {
  display: block;
  font-size: 12px;
  color: #9ca3af;
  margin-top: 4px;
}

.transition-transform {
  transition: transform 0.2s ease;
}

/* 表单 */
.form-textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  font-size: 13px;
  color: #333;
  background: #fff;
  min-height: 72px;
}
.form-textarea[disabled] {
  background-color: #f3f4f6;
  color: #9ca3af;
}
</style>
