<template>
    <div class="mubiao-page">

        <!-- ── 顶部工具栏 ── -->
        <div class="toolbar">
            <div class="toolbar__left">
                <div class="toolbar__icon">
                    <el-icon><TrendCharts /></el-icon>
                </div>
                <div>
                    <div class="toolbar__title">制定业绩目标</div>
                    <div class="toolbar__desc">
                        按部门设置每月销售目标，填 0 并保存将删除该记录。列表按当前账号
                        <strong>角色数据权限</strong>
                        仅展示<strong>本部门及下级</strong>（不展示权限外的上级组织；口径与业绩看板数据范围一致）。
                    </div>
                </div>
            </div>
            <div class="toolbar__center">
                <div class="month-picker-wrap">
                    <span class="month-picker-wrap__label">目标月份</span>
                    <el-date-picker
                        v-model="yearMonth"
                        type="month"
                        value-format="YYYY-MM"
                        placeholder="选择月份"
                        :clearable="false"
                        size="default"
                        class="month-picker"
                        @change="loadMatrix"
                    />
                </div>
            </div>
            <div class="toolbar__right">
                <div class="summary-strip">
                    <div class="summary-item">
                        <span class="summary-item__val">{{ deptCount }}</span>
                        <span class="summary-item__label">部门</span>
                    </div>
                    <div class="summary-divider" />
                    <div class="summary-item">
                        <span class="summary-item__val primary">¥{{ formatMoneyShort(totalDraft) }}</span>
                        <span class="summary-item__label">目标合计</span>
                    </div>
                </div>
                <el-button circle :loading="loading" @click="loadMatrix" title="刷新">
                    <el-icon><Refresh /></el-icon>
                </el-button>
                <el-button
                    v-perms="['finance.dept_performance_target/batchSave']"
                    type="primary"
                    :loading="saving"
                    :disabled="loading || !yearMonth"
                    @click="handleSave"
                >
                    <el-icon><Check /></el-icon>保存目标
                </el-button>
            </div>
        </div>

        <!-- ── 看板区 ── -->
        <div v-loading="loading" element-loading-text="数据加载中…" class="board-wrap">

            <div v-if="!loading && formRows.length === 0" class="empty-state">
                <div class="empty-state__icon"><el-icon><OfficeBuilding /></el-icon></div>
                <p class="empty-state__title">
                    {{ dataScopeLimited ? '数据权限内无可选部门' : '暂无部门数据' }}
                </p>
                <p class="empty-state__desc">
                    {{
                        dataScopeLimited
                            ? '当前角色数据范围未包含任何部门，或需在权限中绑定部门后再试。'
                            : '请检查部门配置后重试'
                    }}
                </p>
                <el-button size="small" @click="loadMatrix"><el-icon><Refresh /></el-icon>重新加载</el-button>
            </div>

            <div v-else class="board-grid">
                <!-- 根级卡片 -->
                <TransitionGroup name="card" tag="div" class="board-grid__inner">
                    <MubiaoDeptCard
                        v-for="r in formRows"
                        :key="'root-' + r.dept_id"
                        :node="r"
                        :is-root="true"
                        :drilled-id="drilledId"
                        @drill-in="handleDrillIn"
                    />
                    <!-- 钻取卡片（顺序追加在根卡片后） -->
                    <MubiaoDeptCard
                        v-for="item in drillStack"
                        :key="'drill-' + item.dept_id"
                        :node="item"
                        :is-root="false"
                        :drilled-id="drilledId"
                        class="card--drilled"
                        @drill-in="handleDrillIn"
                        @close="handleClose(item.dept_id)"
                    />
                </TransitionGroup>
            </div>
        </div>

    </div>
</template>

<script lang="ts" setup name="financeMubiao">
import { computed, onMounted, ref } from 'vue'
import { TrendCharts, Refresh, Check, OfficeBuilding } from '@element-plus/icons-vue'
import MubiaoDeptCard from './mubiao-dept-card.vue'
import {
    deptPerformanceTargetBatchSave,
    deptPerformanceTargetMonthMatrix,
} from '@/api/finance'
import feedback from '@/utils/feedback'
import type { DeptTargetRow } from './mubiao-dept-node.vue'

type Row = DeptTargetRow

function normalizeRow(r: Record<string, any>): Row {
    const row: Row = {
        dept_id: Number(r.dept_id ?? 0),
        dept_name: String(r.dept_name ?? ''),
        dept_path: String(r.dept_path ?? ''),
        target_id: Number(r.target_id ?? 0),
        target_amount: Number(r.target_amount ?? 0),
        remark: String(r.remark ?? ''),
    }
    const ch = r.children
    if (Array.isArray(ch) && ch.length > 0) row.children = ch.map(normalizeRow)
    return row
}

function sumTree(nodes: Row[]): number {
    let s = 0
    for (const n of nodes) {
        s += Number(n.target_amount ?? 0)
        if (n.children?.length) s += sumTree(n.children)
    }
    return Math.round(s * 100) / 100
}

function countTree(nodes: Row[]): number {
    let c = 0
    for (const n of nodes) {
        c += 1
        if (n.children?.length) c += countTree(n.children)
    }
    return c
}

function flattenForSave(nodes: Row[]): Array<{ dept_id: number; target_amount: number; remark: string }> {
    const out: Array<{ dept_id: number; target_amount: number; remark: string }> = []
    for (const n of nodes) {
        out.push({ dept_id: n.dept_id, target_amount: Number(n.target_amount ?? 0), remark: n.remark || '' })
        if (n.children?.length) out.push(...flattenForSave(n.children))
    }
    return out
}

function ymNow(): string {
    const d = new Date()
    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`
}

function formatMoneyShort(v: number): string {
    if (v >= 10000) return (v / 10000).toFixed(1) + 'w'
    return v.toLocaleString('zh-CN', { maximumFractionDigits: 0 })
}

const yearMonth = ref<string>(ymNow())
const loading = ref(false)
const saving = ref(false)
const formRows = ref<Row[]>([])
/** 接口返回：当前账号是否受数据权限收窄（非「全部」等） */
const dataScopeLimited = ref(false)

// 钻取卡片栈：每次 drill-in 追加，close 时移除及其后续
const drillStack = ref<Row[]>([])
// 当前被钻取高亮的 dept_id（让来源卡片的那一行高亮）
const drilledId = ref<number | null>(null)

const totalDraft = computed(() => sumTree(formRows.value))
const deptCount = computed(() => countTree(formRows.value))

function handleDrillIn(node: Row) {
    // 已存在则不重复开
    if (drillStack.value.some(d => d.dept_id === node.dept_id)) {
        drilledId.value = node.dept_id
        return
    }
    drillStack.value.push(node)
    drilledId.value = node.dept_id
}

function handleClose(deptId: number) {
    const idx = drillStack.value.findIndex(d => d.dept_id === deptId)
    if (idx !== -1) {
        // 关闭该卡及其之后所有钻取卡（子级）
        drillStack.value.splice(idx)
    }
    drilledId.value = drillStack.value.length > 0
        ? drillStack.value[drillStack.value.length - 1].dept_id
        : null
}

async function loadMatrix() {
    if (!yearMonth.value) return
    loading.value = true
    drillStack.value = []
    drilledId.value = null
    try {
        const res: any = await deptPerformanceTargetMonthMatrix({ year_month: yearMonth.value })
        formRows.value = ((res?.rows || []) as Record<string, any>[]).map(normalizeRow)
        dataScopeLimited.value = Boolean(res?.data_scope_limited)
    } catch {
        formRows.value = []
        dataScopeLimited.value = false
    } finally {
        loading.value = false
    }
}

async function handleSave() {
    if (!yearMonth.value) { feedback.msgWarning('请选择月份'); return }
    await feedback.confirm('确认保存「' + yearMonth.value + '」各部门业绩目标？')
    saving.value = true
    try {
        const res: any = await deptPerformanceTargetBatchSave({
            year_month: yearMonth.value,
            items: flattenForSave(formRows.value),
        })
        if (res?.rows) {
            formRows.value = (res.rows as Record<string, any>[]).map(normalizeRow)
            dataScopeLimited.value = Boolean(res?.data_scope_limited)
            drillStack.value = []
            drilledId.value = null
        } else {
            await loadMatrix()
        }
    } finally {
        saving.value = false
    }
}

onMounted(loadMatrix)
</script>

<style lang="scss" scoped>
.mubiao-page {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 20px 20px 40px;
}

/* ── 工具栏 ── */
.toolbar {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px 20px;
    background: var(--el-bg-color);
    border: 1px solid var(--el-border-color-lighter);
    border-radius: 14px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
    flex-wrap: wrap;
}

.toolbar__left {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;
    min-width: 0;
}

.toolbar__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 12px;
    background: linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3));
    color: #fff;
    font-size: 19px;
    flex-shrink: 0;
    box-shadow: 0 4px 10px color-mix(in srgb, var(--el-color-primary) 30%, transparent);
}

.toolbar__title {
    font-size: 14px;
    font-weight: 700;
    color: var(--el-text-color-primary);
    line-height: 1.3;
}

.toolbar__desc {
    font-size: 11.5px;
    color: var(--el-text-color-placeholder);
    line-height: 1.4;
    margin-top: 2px;
}

.toolbar__center {
    display: flex;
    align-items: center;
}

.month-picker-wrap {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px;
    background: var(--el-fill-color-extra-light);
    border: 1px solid var(--el-border-color-lighter);
    border-radius: 10px;

    &__label {
        font-size: 12px;
        color: var(--el-text-color-secondary);
        font-weight: 600;
        white-space: nowrap;
    }
}

.month-picker {
    width: 130px;

    :deep(.el-input__wrapper) {
        box-shadow: none !important;
        background: transparent;
        padding: 0 2px;
    }

    :deep(.el-input__inner) {
        font-size: 15px;
        font-weight: 700;
        color: var(--el-text-color-primary);
        cursor: pointer;
    }

    :deep(.el-input__prefix) {
        display: none;
    }
}

.toolbar__right {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

.summary-strip {
    display: flex;
    align-items: center;
    background: var(--el-fill-color-extra-light);
    border: 1px solid var(--el-border-color-lighter);
    border-radius: 10px;
    overflow: hidden;
}

.summary-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 6px 16px;
    gap: 1px;

    &__val {
        font-size: 16px;
        font-weight: 800;
        color: var(--el-text-color-primary);
        line-height: 1.2;
        letter-spacing: -0.02em;

        &.primary { color: var(--el-color-primary); }
    }

    &__label {
        font-size: 10.5px;
        color: var(--el-text-color-placeholder);
        letter-spacing: 0.04em;
    }
}

.summary-divider {
    width: 1px;
    height: 32px;
    background: var(--el-border-color-lighter);
}

/* ── 看板 ── */
.board-wrap {
    min-height: 200px;
}

.board-grid__inner {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 14px;
}

/* 钻取卡片入场动画 */
.card-enter-active {
    animation: card-in 0.25s ease;
}
.card-leave-active {
    animation: card-in 0.2s ease reverse;
}

@keyframes card-in {
    from {
        opacity: 0;
        transform: translateY(10px) scale(0.97);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* 钻取来源高亮标记 */
:deep(.card--drilled) {
    --drill-glow: color-mix(in srgb, var(--el-color-primary) 18%, transparent);
    box-shadow: 0 0 0 2px var(--el-color-primary-light-5), 0 4px 16px var(--drill-glow);
}

/* ── 空状态 ── */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 80px 0;
    text-align: center;
}

.empty-state__icon {
    width: 64px;
    height: 64px;
    border-radius: 20px;
    background: var(--el-fill-color-light);
    color: var(--el-text-color-placeholder);
    font-size: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.empty-state__title {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--el-text-color-primary);
}

.empty-state__desc {
    margin: -4px 0 0;
    font-size: 13px;
    color: var(--el-text-color-placeholder);
}
</style>
