<template>
  <!-- 人工审批对话框(从 ProjectDetail.vue 抽离 UX-260618-17 submitting 保留)-->
  <div v-if="visible" class="modal-overlay">
    <div class="modal-box" style="width: 500px">
      <h3 class="modal-title">{{ $t('projectDetail.approvalTitle') }}</h3>
      <div v-if="pendingApproval">
        <h3>{{ pendingApproval.title }}</h3>
        <p style="margin: 16px 0; color: var(--df-text-secondary);">{{ pendingApproval.description }}</p>
        <div style="margin-bottom: 20px;">
          <p style="margin-bottom: 8px; font-size: 14px;">{{ $t('projectDetail.approvalHint') }}</p>
          <!-- F-260615-01: select_type=multiple → checkbox 多选,缺省 single → 按钮单选 -->
          <template v-if="isMultipleSelect">
            <!-- 全选/反选(多选审批快捷操作):复用 btn-ghost 弱视觉,常驻显隐按钮态 -->
            <div style="display: flex; gap: 8px; margin-bottom: 8px;">
              <button
                class="btn btn-ghost btn-sm"
                :disabled="submitting || allSelected"
                @click="selectAll"
              >{{ $t('projectDetail.approvalSelectAll') }}</button>
              <button
                class="btn btn-ghost btn-sm"
                :disabled="submitting || pendingApproval.options.length === 0"
                @click="invertSelection"
              >{{ $t('projectDetail.approvalInvert') }}</button>
            </div>
            <div style="display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px;">
              <label
                v-for="(option, idx) in pendingApproval.options"
                :key="idx"
                style="display: flex; align-items: center; gap: 8px; cursor: pointer;"
              >
                <input type="checkbox" :value="option" v-model="multiDecisions" />
                <span>{{ option }}</span>
              </label>
            </div>
            <button
              class="btn btn-primary"
              :disabled="submitting || multiDecisions.length === 0"
              @click="handleApprovalMulti"
            >
              {{ $t('projectDetail.approvalConfirm', { count: multiDecisions.length }) }}
            </button>
          </template>
          <template v-else>
            <div style="display: flex; gap: 12px; flex-wrap: wrap;">
              <button
                v-for="(option, idx) in pendingApproval.options"
                :key="idx"
                class="btn"
                :class="idx === 0 ? 'btn-primary' : 'btn-ghost'"
                :disabled="submitting"
                @click="handleApproval(option)"
              >
                {{ option }}
              </button>
            </div>
          </template>
        </div>
      </div>
      <div class="modal-actions">
        <button class="btn btn-ghost" @click="emit('cancel')">{{ $t('projectDetail.approvalCancel') }}</button>
        <button class="btn btn-ghost" @click="emit('later')">{{ $t('projectDetail.approvalLater') }}</button>
      </div>
    </div>
    <!-- M31: 审批失败反馈(store approveHumanApproval 内部 catch 吞错,失败时 pendingApproval 不清空)
         对话框保持开启,用户可看到错误并重试 -->
    <div v-if="toast.visible" class="ad-toast" :class="'ad-toast-' + toast.type">{{ toast.msg }}</div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useProjectStore } from '@/stores/project'
import { useToast } from '@/composables/useToast'

// 抽离自 ProjectDetail.vue(L175-225 模板 + L416-471 审批逻辑/watch)
// store 共享:父级 useProjectStore() 实例传入(同源 store,响应式共享 pendingApproval)
// submitting 自治:本组件持有禁用态(UX-260618-17 双击防抖)
// ProjectStore 类型未 export(store.ts:135 内部 type),用 ReturnType 自推导同源类型
type ProjectStore = ReturnType<typeof useProjectStore>

const props = defineProps<{
  visible: boolean
  store: ProjectStore
}>()

const emit = defineEmits<{
  cancel: []
  later: []
}>()

const pendingApproval = computed(() => props.store.pendingApproval)
const isMultipleSelect = computed(() => pendingApproval.value?.select_type === 'multiple')
const multiDecisions = ref<string[]>([])
const submitting = ref(false)
const { t } = useI18n()
const { toast, showToast } = useToast()

// 全选态(全部 options 已选):驱动「全选」按钮 disabled,避免无意义点击
const allSelected = computed(() => {
  const opts = pendingApproval.value?.options ?? []
  return opts.length > 0 && multiDecisions.value.length === opts.length
})

/** 全选:填入全部 options(去重保险)。submitting 中禁用防与提交并发 */
function selectAll() {
  if (submitting.value) return
  const opts = pendingApproval.value?.options ?? []
  multiDecisions.value = [...opts]
}

/** 反选:options 中未在 multiDecisions 的项成为新选中集 */
function invertSelection() {
  if (submitting.value) return
  const opts = pendingApproval.value?.options ?? []
  const selected = new Set(multiDecisions.value)
  multiDecisions.value = opts.filter(o => !selected.has(o))
}

// M31: store.approveHumanApproval 内部 try/catch 吞错(只 console.error + 写 state.error,不 rethrow),
// 失败时 state.pendingApproval 不清空 → 以此为失败信号。失败显 toast、对话框保持开启,用户可重试或改取消。
async function handleApproval(decision: string) {
  submitting.value = true
  try {
    await props.store.approveHumanApproval([decision])
    if (props.store.pendingApproval) {
      // 仍 pending = IPC 失败(成功路径 store 已置 null)
      showToast(props.store.error || t('projects.err.approveFailed'), 'error', 5000)
      return
    }
    emit('cancel')
  } finally {
    submitting.value = false
  }
}

// F-260615-01: 多选审批(UX-260618-17 submitting 防双击保留)
async function handleApprovalMulti() {
  if (multiDecisions.value.length === 0) return
  submitting.value = true
  try {
    // 统一传 decisions 数组,store 按 select_type 分派单/多选
    await props.store.approveHumanApproval([...multiDecisions.value])
    if (props.store.pendingApproval) {
      showToast(props.store.error || t('projects.err.approveFailed'), 'error', 5000)
      return
    }
    multiDecisions.value = []
    emit('cancel')
  } finally {
    submitting.value = false
  }
}

// F-260615-01: 每次新审批清空多选状态(避免上轮残留)
watch(() => pendingApproval.value, (newApproval) => {
  if (newApproval) {
    multiDecisions.value = []
  }
}, { immediate: true })
</script>

<style scoped>
/* M31: 审批失败 toast(scoped 自治,不引入全局样式;沿用 Projects.vue .toast 视觉规范) */
.ad-toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10001;
  padding: 10px 18px;
  border-radius: var(--df-radius-md);
  font-size: 13px;
  font-weight: 500;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);
  pointer-events: none;
}
.ad-toast-error { background: var(--df-danger); color: #fff; }
</style>
