<template>
  <div class="app-page okr-workbench">
    <!-- v2 工具栏顶栏（替代旧版标题区）-->
    <div class="data-toolbar">
      <span class="data-toolbar__title">我的 OKR</span>
      <template v-if="period">
        <span class="data-toolbar__sep">|</span>
        <span class="data-toolbar__meta">{{ period.name }}</span>
        <span class="status-label">
          <span class="status-label__dot" :class="periodStatusDotClass"></span>
          {{ periodStatusLabel }}
        </span>
        <span class="data-toolbar__spacer"></span>
        <span class="data-toolbar__meta" v-if="daysLeft !== null">距周期结束 {{ daysLeft }} 天</span>
        <el-button v-if="period?.status === 'OKR_ALIGN' && myOkr" size="small" @click="startEdit">编辑 OKR</el-button>
        <el-button v-else-if="period?.status === 'OKR_ALIGN' && !myOkr && canSubmit" type="primary" size="small" @click="openCreateForm">制定 OKR</el-button>
        <el-button v-else-if="period?.status === 'ASSESSING'" type="warning" size="small" @click="$router.push('/scores/my')">去完成自评</el-button>
      </template>
    </div>

    <PeriodBanner v-if="periods.length" :periods="periods" v-model="selectedPeriodId" />
    <div v-if="!selectedPeriodId" class="okr-empty">暂无进行中的考核周期</div>

    <template v-else>
      <!-- 我的 OKR 表格视图（OKR_ALIGN 有 myOkr / EXECUTING）-->
      <div v-if="(period?.status === 'OKR_ALIGN' || period?.status === 'EXECUTING') && myOkr" class="data-table">
        <div class="data-table__header" style="grid-template-columns: 36px 1fr 56px 72px 120px 80px;">
          <span></span>
          <span>关键结果</span>
          <span>权重</span>
          <span>进度</span>
          <span>当前/目标</span>
          <span>状态</span>
        </div>
        <div v-for="(kr, i) in myOkr.keyResults" :key="kr.id"
             class="data-table__row data-table__row--clickable"
             style="grid-template-columns: 36px 1fr 56px 72px 120px 80px;"
             @click="openKrDrawer(kr)">
          <span style="color: var(--color-accent); font-weight: 700;">KR{{ i+1 }}</span>
          <span style="color: var(--color-text);">
            {{ kr.title }}
            <span v-if="kr.sourceKrId" class="kr-source-tag">承接上级</span>
            <span v-if="kr.assignedToName" class="kr-source-tag">指派给 {{ kr.assignedToName }}</span>
          </span>
          <span>{{ kr.weight }}</span>
          <span style="color: var(--color-brand); font-weight: 600;">{{ krPercent(kr) }}%</span>
          <span style="color: var(--color-text-secondary);">{{ kr.currentValue }}/{{ kr.targetValue }}</span>
          <span class="status-label" style="font-size: 11px;">
            <span class="status-dot" :class="krStatusDotClass(kr)"></span>
            {{ krStatusLabel(kr.status) }}
          </span>
        </div>
      </div>

      <!-- OKR 被驳回提示 -->
      <div v-if="period?.status === 'OKR_ALIGN' && myOkr?.status === 'REJECTED'" class="state-banner banner-REJECTED">
        你的 OKR 已被驳回，请修改后重新提交。
        <el-button type="primary" size="small" @click="startEdit" style="margin-left:12px">修改并重新提交</el-button>
      </div>

      <!-- OKR_ALIGN 空态：无 myOkr -->
      <template v-if="period?.status === 'OKR_ALIGN' && !myOkr">
        <div v-if="!canSubmit" class="state-banner banner-waiting">
          等待上级先制定 OKR · {{ superiorName }} 完成并审核通过后，你可对齐并提交。
        </div>
        <template v-else>
          <!-- 上级 OKR 表格化（对齐参考）-->
          <div v-if="superiorOkrs.length" style="margin-top: 20px;">
            <div class="section-band">上级 OKR · 对齐参考</div>
            <div class="data-table">
              <div class="data-table__header" style="grid-template-columns: 36px 1fr 120px;">
                <span></span>
                <span>关键结果</span>
                <span>指派</span>
              </div>
              <template v-for="o in superiorOkrs" :key="o.id">
                <div v-for="(kr, i) in o.keyResults" :key="kr.id"
                     class="data-table__row"
                     style="grid-template-columns: 36px 1fr 120px;">
                  <span style="color: var(--color-accent); font-weight: 700;">KR{{ i+1 }}</span>
                  <span style="color: var(--color-text);">{{ kr.title }}</span>
                  <span>
                    <span v-if="kr.assignedTo === auth.user?.id" class="kr-source-tag kr-source-tag--mine">指派给我</span>
                  </span>
                </div>
              </template>
            </div>
          </div>
          <div v-else class="state-banner banner-top-level">
            你是最高层级 · 制定公司级 OKR（1个O + 3条KR，团队将基于此对齐）
          </div>
        </template>
      </template>

      <!-- EXECUTING 锁定提示 -->
      <div v-if="period?.status === 'EXECUTING' && myOkr" class="state-banner banner-EXECUTING" style="margin-top: 12px;">
        OKR 已锁定 · 仅可更新进度和标记阻塞，点击 KR 行在抽屉中更新。
      </div>

      <!-- 待审核 OKR 表格化 -->
      <div v-if="pendingReviews.length" style="margin-top: 20px;">
        <div class="section-band">待审核 OKR · {{ pendingReviews.length }} 条</div>
        <div class="data-table">
          <div class="data-table__header" style="grid-template-columns: 36px 1fr 100px 120px;">
            <span></span>
            <span>关键结果</span>
            <span>提交人</span>
            <span>操作</span>
          </div>
          <template v-for="o in pendingReviews" :key="o.id">
            <div v-for="(kr, i) in o.keyResults" :key="kr.id"
                 class="data-table__row"
                 style="grid-template-columns: 36px 1fr 100px 120px;">
              <span style="color: var(--color-accent); font-weight: 700;">KR{{ i+1 }}</span>
              <span style="color: var(--color-text);">{{ kr.title }}</span>
              <span v-if="i === 0" :rowspan="o.keyResults.length" style="color: var(--color-text-secondary);">{{ o.userName }}</span>
              <span v-else></span>
              <span v-if="i === 0">
                <el-button size="small" type="success" @click="doReview(o.id, true)">通过</el-button>
                <el-button size="small" type="danger" @click="doReview(o.id, false)">驳回</el-button>
              </span>
            </div>
          </template>
        </div>
      </div>
    </template>

    <!-- 侧边抽屉：KR 详情 / 进度更新 -->
    <el-drawer v-model="drawerVisible" title="关键结果详情" size="420px" direction="rtl">
      <div v-if="drawerKr" class="side-drawer__content">
        <div class="uppercase-label">关键结果</div>
        <div style="margin: 4px 0 16px; font-weight: 600; color: var(--color-text);">{{ drawerKr.title }}</div>

        <div class="metric-bar">
          <div class="metric-bar__head">
            <span class="metric-bar__label">当前进度</span>
            <span class="metric-bar__value">{{ drawerKr.currentValue }} / {{ drawerKr.targetValue }}
              <span class="metric-bar__value--muted">({{ krPercent(drawerKr) }}%)</span>
            </span>
          </div>
          <div class="metric-bar__track">
            <div class="metric-bar__fill" :style="{ width: krPercent(drawerKr) + '%', background: 'var(--color-accent)' }"></div>
          </div>
        </div>

        <!-- 进度更新（仅 EXECUTING 阶段）-->
        <template v-if="period?.status === 'EXECUTING' && drawerKr.status !== 'COMPLETED'">
          <div class="uppercase-label" style="margin-top: 20px;">更新进度</div>
          <div style="font-size: 11px; color: var(--color-text-muted); margin: 4px 0 8px;">
            当前值：{{ drawerKr.currentValue }}
          </div>
          <el-input-number v-model="drawerKr._newValue" :min="0" :max="drawerKr.targetValue*2" style="width: 100%;"
                           :placeholder="'新值（当前 ' + drawerKr.currentValue + '）'" />
          <div class="uppercase-label" style="margin-top: 16px;">状态</div>
          <el-select v-model="drawerKr._newStatus" style="width: 100%; margin-top: 4px;">
            <el-option label="进行中" value="IN_PROGRESS" />
            <el-option label="阻塞" value="BLOCKED" />
            <el-option label="已完成" value="COMPLETED" />
            <el-option label="未开始" value="NOT_STARTED" />
          </el-select>
          <el-button type="primary" style="width: 100%; margin-top: 16px;"
                     :disabled="drawerKr._newValue == null" @click="submitDrawerProgress">保存进度</el-button>
          <div v-if="drawerKr.status === 'BLOCKED'" style="margin-top: 12px; font-size: 11px; color: var(--color-warning);">
            阻塞项，请说明原因与所需支持。上级已收到提醒。
          </div>
        </template>
        <div v-else-if="drawerKr.status === 'COMPLETED'" class="uppercase-label"
             style="margin-top: 20px; color: var(--color-success);">
          该 KR 已完成
        </div>
      </div>
    </el-drawer>

    <!-- Create OKR Dialog -->
    <el-dialog v-model="showForm" :title="editingOkr ? '编辑 OKR' : '制定个人 OKR'" width="720px" top="4vh" :close-on-click-modal="false">
      <div class="dialog-rules">
        <div class="dr-item"><b>1个O（目标）</b>：定性方向，15-30字，不含数字指标，必须对齐上级方向</div>
        <div class="dr-item"><b>2~5条KR</b>（推荐3条）：可量化结果，10-25字，必须有验收标准</div>
        <div class="dr-item"><b>权重之和 = 100</b>：每条KR分配权重，总和必须为100</div>
      </div>

      <!-- Position template reference in dialog -->
      <div v-if="positionTemplate" class="dialog-kpi-ref">
        <div class="dkr-title">你的岗位指标参考（{{ positionTemplate.name }}）</div>
        <div class="dkr-tags">
          <el-tag v-for="(item, i) in parseKpiItems(positionTemplate.itemsJson)" :key="i"
            size="small" type="info" effect="plain">
            {{ item.name }}（{{ item.maxScore }}分）
          </el-tag>
        </div>
        <div class="dkr-hint">你的 OKR 目标应与上述岗位 KPI 方向保持一致</div>
      </div>

      <!-- Superior's OKR reference — KR-level alignment -->
      <div v-if="superiorOkrs.length" class="align-section">
        <div class="align-head">
          <div class="align-head-left">
            
            <span class="align-head-title">对齐上级 OKR</span>
            <span class="align-head-hint">· 勾选你要承接的关键结果，将自动创建引用条目</span>
          </div>
          <el-tag v-if="mandatoryKrCount" type="warning" effect="plain" size="small">
            {{ mandatoryKrCount }} 项指派给我
          </el-tag>
        </div>

        <div v-for="o in superiorOkrs" :key="o.id" class="align-o-card">
          <div class="align-o-head">
            <span class="align-o-icon">O</span>
            <span class="align-o-title">{{ o.title }}</span>
          </div>
          <div class="align-kr-list">
            <div v-for="(kr, i) in o.keyResults" :key="kr.id"
              class="align-kr-row"
              :class="{
                'is-mandatory': kr.assignedTo === auth.user?.id,
                'is-selected': isKrAligned(kr.id) && kr.assignedTo !== auth.user?.id
              }"
              @click="toggleAlignKr(kr, o)">
              <div class="align-kr-left">
                <span class="align-checkbox" :class="{ checked: isKrAligned(kr.id), locked: kr.assignedTo === auth.user?.id }">
                  <span v-if="isKrAligned(kr.id)">已选</span>
                </span>
                <span class="align-kr-num">KR{{ i+1 }}</span>
                <span class="align-kr-title">{{ kr.title }}</span>
              </div>
              <div class="align-kr-right">
                <span class="align-kr-target">目标 {{ kr.targetValue }}</span>
                <el-tag v-if="kr.assignedTo === auth.user?.id" type="warning" effect="plain" size="small">
                  指派给我
                </el-tag>
                <span v-else-if="isKrAligned(kr.id)" class="align-check">已选</span>
              </div>
            </div>
          </div>
        </div>
      </div>

      <el-divider />

      <!-- O Input -->
      <div class="o-section">
        <div class="o-label">目标 O <span class="o-hint">（定性方向，15-30字，不含数字）</span></div>
        <el-input v-model="newOkr.title" type="textarea" :autosize="{ minRows: 1, maxRows: 3 }" :placeholder="currentHints.oHint" size="large" maxlength="35" show-word-limit />
      </div>

      <!-- Parent objective alignment -->
      <div class="parent-align-section">
        <div class="parent-align-label">对齐目标</div>
        <el-tree-select
          v-model="newOkr.parentObjectiveId"
          :data="alignmentOptions"
          :props="{ children: 'children', label: 'title', value: 'id' }"
          placeholder="选择对齐的上级目标（可选）"
          clearable
          check-strictly
          style="width:100%"
        />
      </div>

      <!-- Dynamic KRs with source reference -->
      <div class="kr-section">
        <div class="kr-section-title">
          关键结果 KR（{{ newOkr.krs.length }} 条）
          <span class="weight-sum" :class="{ 'weight-ok': weightSum === 100, 'weight-bad': weightSum !== 100 }">
            权重合计：{{ weightSum }} / 100
          </span>
        </div>
        <div v-for="(kr, i) in newOkr.krs" :key="i" class="kr-form-card" :class="{ 'has-source': kr._sourceKrId }">
          <div v-if="kr._sourceInfo" class="kr-source-bar">
            
            <span class="kr-source-text">承接上级 {{ kr._sourceInfo.userName }} 的 {{ kr._sourceInfo.krTitle }}</span>
          </div>
          <div class="kr-form-head">
            <span class="kr-form-num">KR{{ i+1 }}</span>
            <el-input v-model="kr.title" type="textarea" :autosize="{ minRows: 1, maxRows: 3 }" :placeholder="currentHints.krs[Math.min(i, currentHints.krs.length-1)]" size="large" style="flex:1" maxlength="28" show-word-limit />
            <div class="kr-form-right">
              <span class="kr-form-label-sm">权重</span>
              <el-input-number v-model="kr.weight" :min="0" :max="100" :step="5" size="large" controls-position="right" style="width:90px" />
              <span class="kr-form-label-sm">目标值</span>
              <el-input-number v-model="kr.targetValue" :min="0" :max="999" placeholder="目标" controls-position="right" style="width:110px" />
              <el-button v-if="newOkr.krs.length > 2" @click="removeKr(i)" type="danger" circle :icon="'Delete'" size="small" />
            </div>
          </div>
          <div class="kr-form-extra">
            <span class="kr-form-label">@指派</span>
            <el-select v-model="kr.assignedTo" clearable filterable placeholder="指派给下属（可选）" size="small" style="width:180px">
              <el-option v-for="s in subordinates" :key="s.id" :label="s.realName" :value="s.id" />
            </el-select>
          </div>
        </div>
        <el-button v-if="newOkr.krs.length < 5" @click="newOkr.krs.push({ title: '', targetValue: 100, weight: 0, assignedTo: null })" size="small" style="margin-top:8px">
          新增 KR
        </el-button>
      </div>

      <div class="dialog-footer-hint">
        提交后由直属上级审核。审核通过后锁定，周期内不可修改。
      </div>

      <template #footer>
        <el-button @click="showForm = false">取消</el-button>
        <el-button type="primary" size="large" @click="handleSubmit" :loading="submitting">
          {{ editingOkr ? '保存修改' : '提交审核' }}
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { useRoute } from 'vue-router'
import { periodApi, okrApi, orgApi, kpiApi } from '../../api'
import { useAuthStore } from '../../stores/auth'
import { ElMessage } from 'element-plus'
import PeriodBanner from '../../components/PeriodBanner.vue'

const auth = useAuthStore()
const route = useRoute()
const periods = ref([])
const superiorOkrs = ref([])
const myOkr = ref(null)
const pendingReviews = ref([])
const canSubmit = ref(false)
const subordinates = ref([])
const positionTemplate = ref(null)
const selectedPeriodId = ref(null)
const showForm = ref(false)
const editingOkr = ref(false)
const submitting = ref(false)

const alignmentOptions = ref([])

async function loadAlignmentOptions() {
  try {
    alignmentOptions.value = await okrApi.getTree(selectedPeriodId.value)
  } catch {
    alignmentOptions.value = []
  }
}

// Position-specific OKR hints
const okrHints = {
  'CEO / 总经理': {
    oHint: '本周期推动公司____战略落地，实现业务增长',
    krs: ['完成____营收目标，环比增长____%', '核心业务线____交付满意度≥____', '完成____关键岗位招聘，团队留存率≥____%']
  },
  '前端开发工程师': {
    oHint: '本周期提升前端工程化水平与用户体验',
    krs: ['完成____核心模块/页面开发并全量上线', '负责模块线上零严重Bug，Bug闭环≤24h', '组件库覆盖率达____%，文档完整']
  },
  '后端开发工程师': {
    oHint: '本周期支撑业务系统稳定高效运行',
    krs: ['完成____核心API开发并上线，文档齐全', '负责模块线上零P0事故，接口响应≤____ms', '数据库慢查询优化，查询耗时降低____%']
  },
  '全栈开发工程师': {
    oHint: '本周期完成____模块端到端交付与优化',
    krs: ['完成____功能前后端联调并全量上线', '系统整体可用性≥____%，无严重线上事故', '完成____技术方案设计与落地，输出文档']
  },
  '移动端开发工程师': {
    oHint: '本周期保障App核心体验与版本交付',
    krs: ['完成v____版本迭代开发并通过审核上架', 'Crash率<____%，启动耗时<____s', '核心流程用户投诉环比降低____%']
  },
  '产品经理': {
    oHint: '本周期推动____产品方向落地，提升用户价值',
    krs: ['完成____核心需求迭代，NPS≥____', '输出____竞品分析报告与下周期规划', '跨部门协作满意度≥____分']
  },
  '人力资源总监': {
    oHint: '本周期完善人才体系，支撑业务增长',
    krs: ['核心岗位到岗率≥____%，招聘周期≤____天', '员工满意度≥____分，离职率<____%', '完成____场培训，覆盖率达____%']
  },
  '财务总监': {
    oHint: '本周期保障财务合规与资金安全',
    krs: ['月度报表____号前完成，差异率<____%', '预算执行偏差率<____%，成本节约____万元', '完成____项税务/审计合规工作，零风险']
  },
  '区域经理': {
    oHint: '本周期推动区域市场占有率与营收增长',
    krs: ['区域营收达成____万元，同比增长____%', '新拓客户____家，老客户续约率≥____%', '区域团队人效提升____%，人员零流失']
  },
  '运营总监': {
    oHint: '本周期驱动核心业务指标与用户增长',
    krs: ['DAU/MAU ____万，环比增长____%', '用户7日留存率≥____%，转化率≥____%', '完成____场运营活动，ROI≥____']
  },
  '市场营销总监': {
    oHint: '本周期提升品牌影响力与获客效率',
    krs: ['品牌曝光量____万，自然流量占比≥____%', '线索获取成本<____元，转化率≥____%', '产出____篇高质量内容，全网阅读≥____万']
  },
  '医疗合规总监': {
    oHint: '本周期保障医疗合规体系有效运行',
    krs: ['完成____项法规落地，合规检查零问题', '数据安全事件=0，隐私合规审计通过', '完成全员合规培训____场，覆盖率100%']
  }
}

const currentHints = computed(() => {
  const pos = auth.user?.position || ''
  for (const [key, val] of Object.entries(okrHints)) {
    if (pos.includes(key) || key.includes(pos)) return val
  }
  // fallback generic
  return {
    oHint: '本周期支撑核心业务目标高质量达成',
    krs: ['完成____核心任务并交付验收', '负责模块零问题，闭环时效≤____', '完成____落地，覆盖率达____%']
  }
})

const newOkr = reactive({
  title: '',
  krs: [
    { title: '', targetValue: 100, weight: 34, assignedTo: null },
    { title: '', targetValue: 100, weight: 33, assignedTo: null },
    { title: '', targetValue: 100, weight: 33, assignedTo: null }
  ],
  alignedIds: [],
  parentObjectiveId: null
})

const weightSum = computed(() => newOkr.krs.reduce((s, k) => s + (k.weight || 0), 0))

const activePeriods = computed(() => periods.value.filter(p =>
  p.status !== 'ARCHIVED'
))

const period = computed(() => periods.value.find(p => p.id === selectedPeriodId.value))
const superiorName = computed(() => superiorOkrs.value[0]?.userName || '（上级）')

// --- KR-level alignment ---

// Check if a superior KR is aligned (has a corresponding entry in newOkr.krs)
function isKrAligned(superiorKrId) {
  return newOkr.krs.some(k => k._sourceKrId === superiorKrId)
}

// Toggle alignment: add/remove a KR entry referencing the superior's KR
function toggleAlignKr(superiorKr, superiorO) {
  if (superiorKr.assignedTo === auth.user?.id) return // mandatory, can't untoggle

  const existingIdx = newOkr.krs.findIndex(k => k._sourceKrId === superiorKr.id)
  if (existingIdx >= 0) {
    // Remove the aligned KR entry
    newOkr.krs.splice(existingIdx, 1)
  } else {
    // Add a new KR entry referencing this superior KR
    newOkr.krs.push({
      title: '承接：' + superiorKr.title,
      targetValue: superiorKr.targetValue,
      weight: 0,
      assignedTo: null,
      _sourceKrId: superiorKr.id,
      _sourceInfo: {
        userName: superiorO.userName || superiorName.value,
        krTitle: superiorKr.title
      }
    })
  }
}

// Remove a KR — but not if it's mandatory (has @me source)
function removeKr(i) {
  const kr = newOkr.krs[i]
  if (kr._sourceKrId) {
    // Check if it's mandatory
    for (const o of superiorOkrs.value) {
      const srcKr = o.keyResults?.find(k => k.id === kr._sourceKrId)
      if (srcKr && srcKr.assignedTo === auth.user?.id) return // mandatory, can't remove
    }
  }
  newOkr.krs.splice(i, 1)
}

// Count mandatory KRs
const mandatoryKrCount = computed(() => {
  let count = 0
  for (const o of superiorOkrs.value) {
    count += (o.keyResults || []).filter(k => k.assignedTo === auth.user?.id).length
  }
  return count
})

// On dialog open, auto-add mandatory @me KRs if not already present
function initAlignment() {
  for (const o of superiorOkrs.value) {
    for (const kr of (o.keyResults || [])) {
      if (kr.assignedTo === auth.user?.id) {
        const exists = newOkr.krs.some(k => k._sourceKrId === kr.id)
        if (!exists) {
          newOkr.krs.push({
            title: '承接：' + kr.title,
            targetValue: kr.targetValue,
            weight: 0,
            assignedTo: null,
            _sourceKrId: kr.id,
            _sourceInfo: { userName: o.userName || superiorName.value, krTitle: kr.title }
          })
        }
      }
    }
  }
}
onMounted(async () => {
  periods.value = await periodApi.list()
  // Respect periodId from query param first, then default to first active
  const qPeriodId = route.query.periodId ? Number(route.query.periodId) : null
  if (qPeriodId && periods.value.some(p => p.id === qPeriodId)) {
    selectPeriod(qPeriodId)
  } else if (activePeriods.value.length) {
    selectPeriod(activePeriods.value[0].id)
  } else if (periods.value.length) {
    selectPeriod(periods.value[0].id)
  }
  try { subordinates.value = await orgApi.getMySubordinates() } catch { subordinates.value = [] }
  if (auth.user?.position) {
    try { positionTemplate.value = await kpiApi.getTemplateByPosition(auth.user.position) } catch { positionTemplate.value = null }
  }
})

function selectPeriod(pid) {
  selectedPeriodId.value = pid
  load()
}

function parseKpiItems(json) {
  try { return JSON.parse(json) || [] } catch { return [] }
}

async function load() {
  if (!selectedPeriodId.value) return
  const pid = selectedPeriodId.value
  try { superiorOkrs.value = await okrApi.getSuperiorOkrs(pid) } catch { superiorOkrs.value = [] }
  try { myOkr.value = await okrApi.getMyOkr(pid) } catch { myOkr.value = null }
  try { const r = await okrApi.canSubmit(pid); canSubmit.value = r.canSubmit } catch { canSubmit.value = false }
  try { pendingReviews.value = await okrApi.getPendingReviews(pid) } catch { pendingReviews.value = [] }
  loadAlignmentOptions()
  if (myOkr.value) {
    myOkr.value.keyResults?.forEach(kr => { kr._newValue = kr.currentValue; kr._newStatus = kr.status })
  }
}

function openCreateForm() {
  editingOkr.value = false
  resetForm()
  initAlignment()
  showForm.value = true
}

function startEdit() {
  editingOkr.value = true
  if (myOkr.value) {
    newOkr.title = myOkr.value.title
    // Pre-compute aligned IDs from the OKR's alignedObjectives
    const existingAligned = myOkr.value.alignedObjectives?.map(a => a.id) || []
    // Also add mandatory (assigned-to-me) KR-level alignments from superior OKRs
    const mandatoryIds = new Set(existingAligned)
    if (superiorOkrs.value.length) {
      for (const o of superiorOkrs.value) {
        const hasMandatoryKR = o.keyResults?.some(kr => kr.assignedTo === auth.user?.id)
        if (hasMandatoryKR) mandatoryIds.add(o.id)
      }
    }
    newOkr.alignedIds = [...mandatoryIds]
    newOkr.krs = (myOkr.value.keyResults || []).map(k => ({
      title: k.title || '',
      targetValue: k.targetValue || 100,
      weight: k.weight || Math.floor(100 / (myOkr.value.keyResults?.length || 3)),
      assignedTo: k.assignedTo || null,
      _sourceKrId: k.sourceKrId || null,
      _sourceInfo: k.sourceKrId ? findSourceInfo(k.sourceKrId, k.sourceKrTitle, k.sourceKrUserName) : null
    }))
  }
  initAlignment()
  showForm.value = true
}

function findSourceInfo(sourceKrId, sourceKrTitle, sourceKrUserName) {
  // Look up in loaded superior OKRs for full info
  for (const o of superiorOkrs.value) {
    const kr = (o.keyResults || []).find(k => k.id === sourceKrId)
    if (kr) return { userName: o.userName, krTitle: kr.title }
  }
  // Fallback: use stored info from backend
  if (sourceKrTitle) return { userName: sourceKrUserName || '', krTitle: sourceKrTitle }
  return null
}

async function handleSubmit() {
  if (!newOkr.title) { ElMessage.warning('请填写目标 O'); return }
  const filledKrs = newOkr.krs.filter(k => k.title)
  if (filledKrs.length < 2) { ElMessage.warning('至少填写2条KR'); return }
  const totalWeight = newOkr.krs.reduce((s, k) => s + (k.weight || 0), 0)
  if (totalWeight !== 100) { ElMessage.warning('KR权重之和必须为100，当前为' + totalWeight); return }
  submitting.value = true
  try {
    const payload = {
      periodId: selectedPeriodId.value,
      title: newOkr.title,
      keyResults: filledKrs.map(k => ({ title: k.title, targetValue: k.targetValue, weight: k.weight, assignedTo: k.assignedTo, sourceKrId: k._sourceKrId || null })),
      alignedObjectiveIds: newOkr.alignedIds,
      parentObjectiveId: newOkr.parentObjectiveId || null
    }
    if (editingOkr.value && myOkr.value) {
      await okrApi.update(myOkr.value.id, payload)
    } else {
      await okrApi.submit(payload)
    }
    ElMessage.success(editingOkr.value ? 'OKR 已更新' : 'OKR 已提交，等待上级审核')
    showForm.value = false; editingOkr.value = false
    resetForm()
    load()
  } finally { submitting.value = false }
}

function resetForm() {
  newOkr.title = ''
  newOkr.krs = [
    { title: '', targetValue: 100, weight: 34, assignedTo: null },
    { title: '', targetValue: 100, weight: 33, assignedTo: null },
    { title: '', targetValue: 100, weight: 33, assignedTo: null }
  ]
  newOkr.alignedIds = []
  newOkr.parentObjectiveId = null
}

async function updateProgress(kr) {
  await okrApi.updateProgress(kr.id, { newValue: kr._newValue, status: kr._newStatus, remark: '' })
  ElMessage.success('进度已更新'); load()
}

// v2 侧边抽屉：KR 详情 / 进度更新
const drawerVisible = ref(false)
const drawerKr = ref(null)

function openKrDrawer(kr) {
  // 复制一份并初始化 updateProgress 机制所需的临时字段
  drawerKr.value = { ...kr, _newValue: kr.currentValue, _newStatus: kr.status }
  drawerVisible.value = true
}

async function submitDrawerProgress() {
  if (!drawerKr.value) return
  await updateProgress(drawerKr.value)
  drawerVisible.value = false
}

// v2 工具栏状态显示
const periodStatusLabel = computed(() => {
  const map = { DRAFT: '草稿', OKR_ALIGN: '对齐中', EXECUTING: '执行中', ASSESSING: '考评中', ARCHIVED: '已归档' }
  return map[period.value?.status] || '—'
})
const periodStatusDotClass = computed(() => {
  const map = { EXECUTING: 'status-label__dot--active', OKR_ALIGN: 'status-label__dot--warn', ASSESSING: 'status-label__dot--warn', ARCHIVED: 'status-label__dot--info' }
  return map[period.value?.status] || ''
})
const daysLeft = computed(() => {
  if (!period.value?.endDate) return null
  const diff = Math.ceil((new Date(period.value.endDate) - new Date()) / 86400000)
  return diff > 0 ? diff : 0
})
function krStatusDotClass(kr) {
  if (kr.status === 'BLOCKED') return 'status-dot--warn'
  if (kr.status === 'COMPLETED') return 'status-dot--active'
  return 'status-dot--info'
}

async function doReview(id, approved) {
  await okrApi.review(id, { approved, remark: '' })
  ElMessage.success(approved ? '已通过' : '已驳回'); load()
}

function krPercent(kr) { if (!kr.targetValue || kr.targetValue === 0) return 0; return Math.min((kr.currentValue / kr.targetValue) * 100, 100) }
function krStatusLabel(s) { return { NOT_STARTED: '未开始', IN_PROGRESS: '进行中', COMPLETED: '已完成', BLOCKED: '阻塞' }[s] || s }
</script>

<style scoped>
.page { width: 100%; }

/* v2 状态标签色点变体 */
.status-label__dot--active { background: var(--color-success); }
.status-label__dot--warn { background: var(--color-warning); }
.status-label__dot--info { background: var(--color-text-muted); }
.status-dot--active { background: var(--color-success); }
.status-dot--warn { background: var(--color-warning); }
.status-dot--info { background: var(--color-text-muted); }

.okr-empty {
  display: flex; align-items: center; justify-content: center;
  height: 240px; color: var(--color-text-muted); font-size: var(--font-size-base);
}

/* 状态提示横幅（v2，驳回/等待/锁定提示）*/
.state-banner {
  padding: 12px 16px; border-radius: var(--radius-sm); margin-bottom: 12px;
  display: flex; align-items: center; gap: 10px; font-size: var(--font-size-sm);
}
.banner-EXECUTING { background: var(--color-surface-tint-success); color: var(--color-success); border: 1px solid var(--color-border-soft); }
.banner-REJECTED { background: var(--color-surface-tint-danger); color: var(--color-danger); border: 1px solid var(--color-border-soft); }
.banner-waiting { background: var(--color-surface-tint-warning); color: var(--color-warning); border: 1px solid var(--color-border-soft); }
.banner-top-level { background: var(--color-surface-tint-success); color: var(--color-success); border: 1px solid var(--color-border-soft); }

/* KR 来源标签（承接上级/指派）*/
.kr-source-tag {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  background: var(--color-surface-tint-info); color: var(--color-medical);
  border-radius: 3px; font-size: 10px; font-weight: 500;
}
.kr-source-tag--mine {
  background: var(--color-surface-tint-warning); color: var(--color-warning);
}

/* Dialog */
.dialog-rules { background: var(--color-surface-tint-info); border-radius: var(--radius-md); padding: 14px 18px; margin-bottom: 16px; }
.dr-item { font-size: var(--font-size-sm); color: var(--color-text); line-height: 1.8; }

/* Alignment section */
.align-section { background: var(--color-surface); border: 1px solid var(--color-border-soft); border-radius: var(--radius-md); margin-bottom: 20px; overflow: hidden; }
.align-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 22px; border-bottom: 1px solid var(--color-border-soft); }
.align-head-left { display: flex; align-items: center; gap: 6px; }
.align-head-icon { font-size: var(--font-size-xl); font-weight: 700; color: var(--color-brand); }
.align-head-title { font-size: 15px; font-weight: 700; color: var(--color-text); }
.align-head-hint { font-size: var(--font-size-sm); color: var(--color-text-muted); }

.align-o-card { padding: 0; border-bottom: 1px solid var(--color-border-soft); }
.align-o-card:last-child { border-bottom: none; }
.align-o-head { display: flex; align-items: center; gap: 10px; padding: 14px 22px 8px; }
.align-o-icon { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: var(--radius-sm); background: var(--color-brand); color: var(--color-white); font-size: var(--font-size-xs); font-weight: 700; }
.align-o-title { font-size: var(--font-size-base); font-weight: 600; color: var(--color-text); }

.align-kr-list { padding: 0 22px 14px; display: flex; flex-direction: column; gap: 6px; }
.align-kr-row { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-radius: var(--radius-md); cursor: pointer; transition: all 0.15s; border: 1px solid transparent; }
.align-kr-row:hover { background: var(--color-surface-subtle); }
.align-kr-row.is-selected { background: var(--color-surface-tint-brand); border-color: var(--color-border); }
.align-kr-row.is-mandatory { background: var(--color-surface-tint-warning); border-color: var(--color-border-soft); cursor: default; }
.align-kr-left { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.align-kr-num { font-size: 11px; font-weight: 700; color: var(--color-text-muted); width: 30px; flex-shrink: 0; letter-spacing: 0; }
.align-checkbox { min-width: 34px; height: 18px; border-radius: var(--radius-xs); border: 1px solid var(--color-border); display: inline-flex; align-items: center; justify-content: center; font-size: 10px; color: transparent; flex-shrink: 0; transition: all 0.15s; cursor: pointer; padding: 0 4px; }
.align-checkbox.checked { background: var(--color-brand); border-color: var(--color-brand); color: var(--color-white); }
.align-checkbox.locked { background: var(--color-surface-tint-warning); border-color: var(--color-warning); color: var(--color-warning); cursor: default; }
.align-kr-title { font-size: var(--font-size-sm); color: var(--color-text); }
.align-kr-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.align-kr-target { font-size: var(--font-size-xs); color: var(--color-text-muted); }

.align-footer { padding: 12px 22px; background: var(--color-surface-subtle); border-top: 1px solid var(--color-border-soft); font-size: var(--font-size-sm); color: var(--color-text-secondary); text-align: center; }
.align-footer strong { color: var(--color-brand); }

.parent-align-section { margin-bottom: 20px; }
.parent-align-label { font-weight: 600; font-size: 15px; color: var(--color-text); margin-bottom: 8px; }

.o-section { margin-bottom: 20px; }
.o-label { font-weight: 600; font-size: 15px; color: var(--color-text); margin-bottom: 8px; }
.o-hint { font-size: var(--font-size-xs); color: var(--color-text-muted); font-weight: 400; }

.kr-section { margin-bottom: 16px; }
.kr-section-title { font-weight: 600; font-size: 15px; color: var(--color-text); margin-bottom: 12px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.weight-sum { font-size: var(--font-size-sm); padding: 2px 10px; border-radius: var(--radius-md); }
.weight-ok { background: var(--color-surface-tint-success); color: var(--color-success); font-weight: 700; }
.weight-bad { background: var(--color-surface-tint-danger); color: var(--color-danger); font-weight: 700; }
.kr-form-card { background: var(--color-surface-subtle); border-radius: var(--radius-md); padding: 14px 16px; margin-bottom: 10px; border: 1px solid var(--color-border-soft); }
.kr-form-card.has-source { border-left: 3px solid var(--color-brand); }
.kr-source-bar { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; padding: 6px 10px; background: var(--color-surface-tint-brand); border-radius: var(--radius-sm); font-size: var(--font-size-xs); }
.kr-source-icon { color: var(--color-brand); font-weight: 700; }
.kr-source-text { color: var(--color-text-secondary); }
.kr-form-head { display: flex; align-items: flex-start; gap: 10px; }
.kr-form-head .el-textarea { flex: 1; }
.kr-form-num { font-size: var(--font-size-sm); font-weight: 700; color: var(--color-accent); width: 36px; }
.kr-form-right { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.kr-form-label-sm { font-size: 11px; color: var(--color-text-muted); }
.kr-form-extra { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.kr-form-label { font-size: var(--font-size-xs); color: var(--color-text-muted); }

.dialog-kpi-ref { background: var(--color-surface-tint-info); border: 1px solid var(--color-border-soft); border-radius: var(--radius-md); padding: 12px 16px; margin-bottom: 12px; }
.dkr-title { font-size: var(--font-size-sm); font-weight: 600; color: var(--color-brand); margin-bottom: 6px; }
.dkr-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.dkr-hint { font-size: 11px; color: var(--color-text-muted); margin-top: 6px; }

.dialog-footer-hint { text-align: center; font-size: var(--font-size-xs); color: var(--color-text-muted); margin-top: 12px; }
</style>
