<template>
  <article class="detail-card panel employee-risk-profile-card">
    <div class="employee-risk-head">
      <div>
        <h3 class="detail-card-title-with-icon">
          <i class="mdi mdi-account-search-outline"></i>
          <span>风险审核画像</span>
        </h3>
        <p>{{ subtitle }}</p>
      </div>
      <span v-if="!loading && !error" :class="['profile-level-pill', levelTone]">
        {{ levelLabel }}
      </span>
    </div>

    <div v-if="loading" class="employee-risk-state">
      <i class="mdi mdi-loading mdi-spin"></i>
      <span>正在读取画像快照</span>
    </div>

    <div v-else-if="error" class="employee-risk-state error">
      <i class="mdi mdi-alert-circle-outline"></i>
      <span>{{ error }}</span>
    </div>

    <div v-else-if="emptyReason" class="employee-risk-state">
      <i class="mdi mdi-database-search-outline"></i>
      <span>{{ emptyReason }}</span>
    </div>

    <div v-else class="employee-risk-body">
      <div class="employee-risk-summary">
        <div>
          <span>审核优先级</span>
          <strong>{{ reviewScore }}</strong>
        </div>
        <div>
          <span>计算窗口</span>
          <strong>{{ profile?.window_days || 90 }} 天</strong>
        </div>
        <div>
          <span>同组样本</span>
          <strong>{{ profile?.peer_group?.sample_size || 0 }} 人</strong>
        </div>
        <div>
          <span>更新时间</span>
          <strong>{{ calculatedAtText }}</strong>
        </div>
      </div>

      <div v-if="tags.length" class="employee-risk-tags">
        <span>特征标签</span>
        <div>
          <span
            v-for="tag in tags"
            :key="tag.code"
            :class="['employee-risk-tag', tagTone(tag)]"
            :title="tag.reason"
          >
            {{ tag.display_label || tag.label }}
            <strong>{{ tag.score }}</strong>
          </span>
        </div>
      </div>

      <div v-if="radarDimensions.length" class="employee-risk-radar">
        <div class="employee-risk-radar-head">
          <span>行为雷达</span>
          <small>分数越高，表示该行为特征越明显。</small>
        </div>
        <div class="employee-risk-radar-layout">
          <svg class="employee-risk-radar-chart" viewBox="0 0 104 104" aria-hidden="true">
            <polygon
              v-for="ring in radarRings"
              :key="ring.scale"
              class="employee-risk-radar-ring"
              :points="ring.points"
            />
            <line
              v-for="axis in radarAxes"
              :key="axis.key"
              class="employee-risk-radar-axis"
              x1="52"
              y1="52"
              :x2="axis.x"
              :y2="axis.y"
            />
            <polygon class="employee-risk-radar-area" :points="radarPolygonPoints" />
            <circle
              v-for="point in radarValuePoints"
              :key="point.key"
              class="employee-risk-radar-point"
              :cx="point.x"
              :cy="point.y"
              r="2"
            />
          </svg>
          <ul class="employee-risk-radar-list">
            <li v-for="item in radarDimensions" :key="item.code">
              <span>{{ item.label }}</span>
              <strong>{{ item.score }}</strong>
            </li>
          </ul>
        </div>
      </div>

      <div class="employee-risk-profile-list">
        <section v-for="item in profiles" :key="item.profile_type" class="employee-risk-profile">
          <div class="employee-risk-profile-title">
            <span>{{ item.profile_label }}</span>
            <strong :class="profileLevelClass(item.level)">{{ item.score }}</strong>
          </div>
          <ul v-if="item.top_contributors?.length" class="employee-risk-evidence-list">
            <li v-for="basis in item.top_contributors.slice(0, 3)" :key="basis.code">
              <span>{{ basis.label }}</span>
              <strong>{{ formatBasisValue(basis) }}</strong>
            </li>
          </ul>
          <p v-else class="employee-risk-muted">暂无显著贡献项。</p>
        </section>
      </div>

      <div v-if="suggestions.length" class="employee-risk-suggestions">
        <span>审核建议</span>
        <ul>
          <li v-for="item in suggestions" :key="item.type || item.message">
            {{ item.message }}
            <strong v-if="item.recommended_upper">建议上限 {{ item.recommended_upper }}{{ item.unit || '' }}</strong>
          </li>
        </ul>
      </div>
    </div>
  </article>
</template>

<script>
import { computed } from 'vue'

export default {
  name: 'EmployeeProfileRiskCard',
  props: {
    profile: {
      type: Object,
      default: null
    },
    loading: {
      type: Boolean,
      default: false
    },
    error: {
      type: String,
      default: ''
    }
  },
  setup(props) {
    const profiles = computed(() => Array.isArray(props.profile?.profiles) ? props.profile.profiles : [])
    const tags = computed(() => Array.isArray(props.profile?.profile_tags) ? props.profile.profile_tags.slice(0, 6) : [])
    const radarDimensions = computed(() => Array.isArray(props.profile?.radar?.dimensions) ? props.profile.radar.dimensions : [])
    const suggestions = computed(() => Array.isArray(props.profile?.review_suggestions) ? props.profile.review_suggestions : [])
    const emptyReason = computed(() => String(props.profile?.empty_reason || '').trim())
    const reviewScore = computed(() => Number(props.profile?.review_priority_score || 0))
    const level = computed(() => String(props.profile?.review_priority_level || 'normal').trim())
    const levelLabel = computed(() => String(props.profile?.review_priority_label || '正常').trim())
    const levelTone = computed(() => profileLevelClass(level.value))
    const subtitle = computed(() => {
      if (props.loading) {
        return '读取员工近期费用和流程质量画像。'
      }
      if (props.error || emptyReason.value) {
        return '当前画像不可用，审批时按单据事实继续核对。'
      }
      const windowDays = props.profile?.window_days || 90
      const sampleSize = props.profile?.peer_group?.sample_size || 0
      return `${windowDays} 天窗口，同组样本 ${sampleSize} 人，用于辅助复核费用节奏和材料质量。`
    })
    const calculatedAtText = computed(() => formatDateTime(props.profile?.calculated_at))
    const radarRings = computed(() => [0.25, 0.5, 0.75, 1].map((scale) => ({
      scale,
      points: radarDimensions.value.map((_, index) => radarPoint(index, radarDimensions.value.length, scale)).join(' ')
    })))
    const radarAxes = computed(() => radarDimensions.value.map((item, index) => ({
      key: item.code,
      ...radarPointObject(index, radarDimensions.value.length, 1)
    })))
    const radarValuePoints = computed(() => radarDimensions.value.map((item, index) => ({
      key: item.code,
      ...radarPointObject(index, radarDimensions.value.length, Number(item.score || 0) / 100)
    })))
    const radarPolygonPoints = computed(() => radarValuePoints.value.map((point) => `${point.x},${point.y}`).join(' '))

    function formatDateTime(value) {
      const normalized = String(value || '').trim()
      if (!normalized) {
        return '暂无'
      }
      const date = new Date(normalized)
      if (Number.isNaN(date.getTime())) {
        return normalized.slice(0, 16)
      }
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      const hour = String(date.getHours()).padStart(2, '0')
      const minute = String(date.getMinutes()).padStart(2, '0')
      return `${month}-${day} ${hour}:${minute}`
    }

    function profileLevelClass(value) {
      const normalized = String(value || '').trim()
      if (normalized === 'escalation') {
        return 'high'
      }
      if (normalized === 'review') {
        return 'medium'
      }
      if (normalized === 'watch') {
        return 'watch'
      }
      return 'normal'
    }

    function radarPoint(index, total, scale) {
      const point = radarPointObject(index, total, scale)
      return `${point.x},${point.y}`
    }

    function radarPointObject(index, total, scale) {
      if (!total) {
        return { x: 52, y: 52 }
      }
      const angle = (-90 + (360 / total) * index) * (Math.PI / 180)
      const radius = 42 * Math.max(0, Math.min(1, scale))
      return {
        x: Number((52 + Math.cos(angle) * radius).toFixed(2)),
        y: Number((52 + Math.sin(angle) * radius).toFixed(2))
      }
    }

    function tagTone(tag) {
      const polarity = String(tag?.polarity || '').trim()
      if (polarity === 'positive') {
        return 'positive'
      }
      if (Number(tag?.score || 0) >= 80 || polarity === 'risk') {
        return 'risk'
      }
      return 'behavior'
    }

    function formatBasisValue(basis) {
      const value = basis?.value
      const unit = String(basis?.unit || '').trim()
      if (value == null || value === '') {
        return basis?.score != null ? `${basis.score}分` : ''
      }
      if (unit === '占比') {
        const ratio = Number(value)
        return Number.isFinite(ratio) ? `${Math.round(ratio * 100)}%` : String(value)
      }
      return `${value}${unit && unit !== '比例' ? unit : ''}`
    }

    return {
      calculatedAtText,
      emptyReason,
      formatBasisValue,
      levelLabel,
      levelTone,
      profileLevelClass,
      profiles,
      radarAxes,
      radarDimensions,
      radarPolygonPoints,
      radarRings,
      radarValuePoints,
      reviewScore,
      subtitle,
      suggestions,
      tags,
      tagTone
    }
  }
}
</script>

<style scoped>
.employee-risk-profile-card {
  display: grid;
  gap: 14px;
}

.employee-risk-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.employee-risk-head p {
  margin: 6px 0 0;
  color: #64748b;
  font-size: 12px;
  line-height: 1.5;
}

.profile-level-pill {
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  padding: 0 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 850;
  white-space: nowrap;
}

.profile-level-pill.normal,
.employee-risk-profile-title strong.normal {
  background: #ecfdf5;
  color: #047857;
}

.profile-level-pill.watch,
.employee-risk-profile-title strong.watch {
  background: #eff6ff;
  color: #2563eb;
}

.profile-level-pill.medium,
.employee-risk-profile-title strong.medium {
  background: #fff7ed;
  color: #c2410c;
}

.profile-level-pill.high,
.employee-risk-profile-title strong.high {
  background: #fef2f2;
  color: #b91c1c;
}

.employee-risk-state {
  min-height: 78px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px dashed #cbd5e1;
  border-radius: 8px;
  color: #64748b;
  font-size: 13px;
  font-weight: 750;
}

.employee-risk-state.error {
  border-color: #fecaca;
  background: #fef2f2;
  color: #b91c1c;
}

.employee-risk-body {
  display: grid;
  gap: 12px;
}

.employee-risk-summary {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}

.employee-risk-summary > div {
  min-width: 0;
  display: grid;
  gap: 4px;
  padding: 9px 10px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background: #f8fafc;
}

.employee-risk-summary span,
.employee-risk-suggestions > span {
  color: #64748b;
  font-size: 10px;
  font-weight: 850;
}

.employee-risk-summary strong {
  min-width: 0;
  color: #0f172a;
  font-size: 13px;
  font-weight: 850;
  overflow-wrap: anywhere;
}

.employee-risk-tags {
  display: grid;
  gap: 8px;
}

.employee-risk-tags > span,
.employee-risk-radar-head span {
  color: #64748b;
  font-size: 10px;
  font-weight: 850;
}

.employee-risk-tags > div {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.employee-risk-tag {
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 8px;
  border: 1px solid #e2e8f0;
  border-radius: 999px;
  background: #fff;
  color: #334155;
  font-size: 11px;
  font-weight: 850;
}

.employee-risk-tag strong {
  color: inherit;
  font-size: 10px;
}

.employee-risk-tag.risk {
  border-color: #fed7aa;
  background: #fff7ed;
  color: #c2410c;
}

.employee-risk-tag.behavior {
  border-color: #bfdbfe;
  background: #eff6ff;
  color: #2563eb;
}

.employee-risk-tag.positive {
  border-color: #bbf7d0;
  background: #f0fdf4;
  color: #15803d;
}

.employee-risk-radar {
  display: grid;
  gap: 8px;
  padding: 10px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background: #fff;
}

.employee-risk-radar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.employee-risk-radar-head small {
  color: #94a3b8;
  font-size: 10px;
  font-weight: 700;
}

.employee-risk-radar-layout {
  display: grid;
  grid-template-columns: 112px minmax(0, 1fr);
  gap: 12px;
  align-items: center;
}

.employee-risk-radar-chart {
  width: 112px;
  height: 112px;
}

.employee-risk-radar-ring {
  fill: none;
  stroke: #e2e8f0;
  stroke-width: 0.75;
}

.employee-risk-radar-axis {
  stroke: #e2e8f0;
  stroke-width: 0.75;
}

.employee-risk-radar-area {
  fill: rgba(37, 99, 235, 0.16);
  stroke: #2563eb;
  stroke-width: 1.8;
}

.employee-risk-radar-point {
  fill: #2563eb;
}

.employee-risk-radar-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.employee-risk-radar-list li {
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: #475569;
  font-size: 11px;
  font-weight: 750;
}

.employee-risk-radar-list strong {
  color: #0f172a;
  font-size: 12px;
  font-weight: 900;
}

.employee-risk-profile-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.employee-risk-profile {
  min-width: 0;
  display: grid;
  gap: 8px;
  padding: 10px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background: #fff;
}

.employee-risk-profile-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: #0f172a;
  font-size: 13px;
  font-weight: 850;
}

.employee-risk-profile-title strong {
  min-width: 36px;
  height: 22px;
  display: inline-grid;
  place-items: center;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 900;
}

.employee-risk-evidence-list,
.employee-risk-suggestions ul {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.employee-risk-evidence-list li,
.employee-risk-suggestions li {
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: #475569;
  font-size: 12px;
  line-height: 1.45;
}

.employee-risk-evidence-list strong,
.employee-risk-suggestions strong {
  color: #0f172a;
  white-space: nowrap;
}

.employee-risk-muted {
  margin: 0;
  color: #94a3b8;
  font-size: 12px;
}

.employee-risk-suggestions {
  display: grid;
  gap: 7px;
  padding: 10px;
  border-radius: 8px;
  background: #f8fafc;
}

@media (max-width: 960px) {
  .employee-risk-summary,
  .employee-risk-profile-list {
    grid-template-columns: 1fr;
  }

  .employee-risk-radar-layout {
    grid-template-columns: 1fr;
  }

  .employee-risk-radar-chart {
    justify-self: center;
  }
}
</style>
