<template>
  <div class="salary-panel">
    <!-- 工具栏 -->
    <div class="toolbar">
      <div class="toolbar-left">
        <el-input v-model="query.employeeId" size="small" placeholder="员工ID" clearable style="width: 140px" @keyup.enter.native="loadList" />
        <!-- 状态筛选：当前阶段为保证统计页能直接聚合展示，临时停用 status 参数筛选 -->
        <!-- <el-select v-model="query.status" size="small" placeholder="状态" clearable style="width: 110px" @change="loadList">
          <el-option label="草稿" :value="'0'" />
          <el-option label="已确认" :value="'1'" />
          <el-option label="已归档" :value="'2'" />
        </el-select> -->
        <el-button size="small" type="primary" icon="el-icon-search" @click="loadList">查询</el-button>
      </div>
      <div class="toolbar-right">
        <el-button size="small" type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
        <el-button size="small" type="success" icon="el-icon-s-operation" :loading="generating" @click="handleBatchGenerate">一键生成</el-button>
      </div>
    </div>

    <!-- 表格 -->
    <div class="table-wrap">
    <el-table :data="list" stripe size="small" v-loading="loading" empty-text="暂无薪资记录" class="inline-edit-table" border>
      <!-- 只读列 -->
      <!-- <el-table-column prop="employeeId" label="员工ID" width="90" /> -->
      <!-- 状态列：同上，临时停用 -->
      <!-- <el-table-column prop="status" label="状态" width="70" align="center">
        <template slot-scope="scope">
          <el-tag :type="statusType(scope.row.status)" size="small">{{ statusLabel(scope.row.status) }}</el-tag>
        </template>
      </el-table-column> -->

      <!-- 薪资基数 -->
      <el-table-column label="底薪" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.baseSalary" class="cell-input cell-input--base" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="绩效基数" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.perfBase" class="cell-input cell-input--base" @change="markDirty(s.row)" />
      </template></el-table-column>

      <!-- 考核得分 -->
      <el-table-column label="考核得分" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.perfScore" class="cell-input cell-input--coeff" @change="markDirty(s.row)" />
      </template></el-table-column>

      <!-- 系数 -->
      <el-table-column label="绩效系数" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.perfCoeff" class="cell-input cell-input--coeff" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="车间系数" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.deptCoeff" class="cell-input cell-input--coeff" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="岗位系数" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.posCoeff" class="cell-input cell-input--coeff" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="固定系数" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.fixedCoeff" class="cell-input cell-input--coeff" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="调整系数" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.adjCoeff" class="cell-input cell-input--coeff" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="手动调整系数" width="100" align="right"><template slot-scope="s">
        <input v-model="s.row.adjCoeffManual" class="cell-input cell-input--coeff" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="总系数" width="80" align="right"><template slot-scope="s">
        <input v-model="s.row.totalCoeff" class="cell-input cell-input--coeff" @change="markDirty(s.row)" />
      </template></el-table-column>

      <!-- 绩效工资 -->
      <el-table-column label="绩效工资" width="100" align="right"><template slot-scope="s">
        <input v-model="s.row.perfWage" class="cell-input cell-input--amount" @change="markDirty(s.row)" />
      </template></el-table-column>

      <!-- 动态扣款列 -->
      <el-table-column
        v-for="item in deductionItems" :key="'ded-'+item.itemName"
        :label="item.itemName" width="100" align="right"
      ><template slot-scope="s">
        <input v-model="s.row._d[item.itemName]" class="cell-input cell-input--deduct" @change="onDeductChange(s.row); markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="扣款合计" width="90" align="right">
        <template slot-scope="scope"><span class="cell-readonly cell-readonly--deduct">{{ scope.row._deductionsTotal }}</span></template>
      </el-table-column>

      <!-- 动态奖励列 -->
      <el-table-column
        v-for="item in bonusItems" :key="'bon-'+item.itemName"
        :label="item.itemName" width="100" align="right"
      ><template slot-scope="s">
        <input v-model="s.row._b[item.itemName]" class="cell-input cell-input--bonus" @change="onBonusChange(s.row); markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="奖励合计" width="90" align="right">
        <template slot-scope="scope"><span class="cell-readonly cell-readonly--bonus">{{ scope.row._bonusesTotal }}</span></template>
      </el-table-column>

      <!-- 金额 -->
      <el-table-column label="其他金额" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.otherAmount" class="cell-input cell-input--amount" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="实领薪资" width="100" align="right"><template slot-scope="s">
        <input v-model="s.row.actualSalary" class="cell-input cell-input--amount" @change="markDirty(s.row)" />
      </template></el-table-column>

      <!-- 参考值 -->
      <el-table-column label="固薪参考" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.fixedSalaryRef" class="cell-input cell-input--ref" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="调薪参考" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.adjSalaryRef" class="cell-input cell-input--ref" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="包薪每班参考" width="100" align="right"><template slot-scope="s">
        <input v-model="s.row.baoPerShiftRef" class="cell-input cell-input--ref" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="包薪参考" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.baoSalaryRef" class="cell-input cell-input--ref" @change="markDirty(s.row)" />
      </template></el-table-column>
      <el-table-column label="总薪参考" width="90" align="right"><template slot-scope="s">
        <input v-model="s.row.totalSalaryRef" class="cell-input cell-input--ref" @change="markDirty(s.row)" />
      </template></el-table-column>

      <!-- 备注 -->
      <el-table-column label="备注" min-width="140"><template slot-scope="s">
        <input v-model="s.row.remark" class="cell-input cell-input--remark" @change="markDirty(s.row)" />
      </template></el-table-column>

      <!-- 操作 -->
      <el-table-column label="操作" width="90" align="center" fixed="right">
        <template slot-scope="scope">
          <el-button v-if="scope.row._dirty" type="text" size="mini" icon="el-icon-check" :loading="scope.row._saving" class="btn-save" @click="saveRow(scope.row)">保存</el-button>
          <el-button type="text" size="mini" icon="el-icon-delete" @click="handleDel(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    </div>

    <div class="pagination-wrapper">
      <el-pagination
        :current-page="query.pageNum"
        :page-sizes="[10, 20, 50, 100]"
        :page-size="query.pageSize"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handlePageChange"
      />
    </div>
  </div>
</template>

<script>
import { listPerfSalary, addPerfSalary, updatePerfSalary, delPerfSalary } from '@/api/perf/salary'
import { listEmployeeInfo } from '@/api/wms/employeeInfo'
import { listPerfDeptItemConfig } from '@/api/perf/deptItemConfig'

export default {
  name: 'SalaryPanel',
  props: {
    deptId: { type: [Number, String], default: null },
    deptName: { type: String, default: '' },
    period: { type: String, default: '' }
  },
  data() {
    return {
      loading: false,
      list: [],
      total: 0,
      query: {
        pageNum: 1,
        pageSize: 10,
        employeeId: '',
        // status: ''
      },
      deductionItems: [],
      bonusItems: [],
      generating: false
    }
  },
  watch: {
    deptId: { immediate: true, handler: 'onDeptChange' },
    period: 'onDeptChange'
  },
  methods: {
    fmt(val) {
      return val != null ? val : '-'
    },
    // statusType(status) {
    //   return { '0': 'info', '1': 'warning', '2': 'success' }[status] || 'info'
    // },
    // statusLabel(status) {
    //   return { '0': '草稿', '1': '已确认', '2': '已归档' }[status] || '草稿'
    // },
    onDeptChange() {
      this.loadItemConfig()
      this.loadList()
    },
    loadItemConfig() {
      if (!this.deptId || !this.period) return
      listPerfDeptItemConfig({ deptId: this.deptId, month: this.period + '-01' }).then(res => {
        const rows = res.rows || []
        this.deductionItems = rows.filter(r => r.itemType === 1 && r.isEnabled === 1)
        this.bonusItems = rows.filter(r => r.itemType === 2 && r.isEnabled === 1)
      }).catch(() => {
        this.deductionItems = []
        this.bonusItems = []
      })
    },
    /* 解析扣款/奖励 JSON 到行对象 */
    parseRowItems(row) {
      if (!row._d) {
        const d = {}
        try { Object.assign(d, JSON.parse(row.deductionsJson || '{}')) } catch {}
        this.deductionItems.forEach(item => { if (!(item.itemName in d)) d[item.itemName] = '' })
        this.$set(row, '_d', d)
      }
      if (!row._b) {
        const b = {}
        try { Object.assign(b, JSON.parse(row.bonusesJson || '{}')) } catch {}
        this.bonusItems.forEach(item => { if (!(item.itemName in b)) b[item.itemName] = '' })
        this.$set(row, '_b', b)
      }
      this.recalcTotals(row)
    },
    recalcTotals(row) {
      const sumD = Object.values(row._d || {}).reduce((s, v) => s + (parseFloat(v) || 0), 0)
      const sumB = Object.values(row._b || {}).reduce((s, v) => s + (parseFloat(v) || 0), 0)
      this.$set(row, '_deductionsTotal', sumD)
      this.$set(row, '_bonusesTotal', sumB)
    },
    onDeductChange(row) { this.recalcTotals(row) },
    onBonusChange(row) { this.recalcTotals(row) },
    markDirty(row) { this.$set(row, '_dirty', true) },

    loadList() {
      if (!this.deptId || !this.period) return
      this.loading = true
      const params = {
        pageNum: this.query.pageNum,
        pageSize: this.query.pageSize,
        deptId: this.deptId,
        period: this.period,
        employeeId: this.query.employeeId || undefined
      }
      listPerfSalary(params).then(res => {
        this.list = (res.rows || []).map(r => {
          this.$set(r, '_dirty', false)
          this.$set(r, '_saving', false)
          this.parseRowItems(r)
          return r
        })
        this.total = res.total || 0
      }).finally(() => {
        this.loading = false
      })
    },
    handleSizeChange(val) {
      this.query.pageSize = val
      this.loadList()
    },
    handlePageChange(val) {
      this.query.pageNum = val
      this.loadList()
    },
    handleAdd() {
      const row = {
        employeeId: '',
        deptId: this.deptId,
        period: this.period,
        baseSalary: '',
        perfBase: '',
        perfScore: '',
        perfCoeff: '',
        deptCoeff: '',
        posCoeff: '',
        fixedCoeff: '',
        adjCoeff: '',
        adjCoeffManual: '',
        totalCoeff: '',
        perfWage: '',
        deductionsJson: '{}',
        bonusesJson: '{}',
        otherAmount: '',
        actualSalary: '',
        fixedSalaryRef: '',
        adjSalaryRef: '',
        baoPerShiftRef: '',
        baoSalaryRef: '',
        totalSalaryRef: '',
        status: '0',
        remark: '',
        _dirty: true,
        _saving: false,
        _d: {},
        _b: {},
        _deductionsTotal: 0,
        _bonusesTotal: 0
      }
      this.deductionItems.forEach(item => { row._d[item.itemName] = '' })
      this.bonusItems.forEach(item => { row._b[item.itemName] = '' })
      this.list.unshift(row)
    },
    saveRow(row) {
      this.$set(row, '_saving', true)
      const data = { ...row }
      // 序列化扣款/奖励 JSON
      data.deductionsJson = JSON.stringify(row._d || {})
      data.bonusesJson = JSON.stringify(row._b || {})
      data.deductionsTotal = row._deductionsTotal
      data.bonusesTotal = row._bonusesTotal
      // 清理内部字段
      delete data._d; delete data._b; delete data._dirty; delete data._saving
      delete data._deductionsTotal; delete data._bonusesTotal

      const api = data.id ? updatePerfSalary : addPerfSalary
      api(data).then(res => {
        // 乐观更新：如果是新增，用返回值更新 id
        if (!data.id && res.data) {
          this.$set(row, 'id', res.data.id || res.data)
        }
        this.$set(row, '_dirty', false)
        this.$message.success('保存成功')
      }).catch(() => {
        this.$message.error('保存失败')
        this.loadList() // 失败则重新加载以回滚
      }).finally(() => {
        this.$set(row, '_saving', false)
      })
    },
    handleDel(row) {
      if (!row.id) {
        // 未保存的新行直接移除
        const idx = this.list.indexOf(row)
        if (idx >= 0) this.list.splice(idx, 1)
        return
      }
      this.$confirm(`确认删除该薪资记录吗？`, '提示', { type: 'warning' }).then(() => {
        delPerfSalary(row.id).then(() => {
          this.$message.success('删除成功')
          this.loadList()
        })
      }).catch(() => {})
    },
    handleBatchGenerate() {
      if (!this.deptName) {
        this.$message.warning('缺少部门名称')
        return
      }
      this.$confirm(`确认根据"${this.deptName}"下的在职员工，一键生成本月薪资记录吗？`, '提示', { type: 'info' }).then(() => {
        this.generating = true
        listEmployeeInfo({ dept: this.deptName, isLeave: 0, pageSize: 9999 }).then(empRes => {
          const employees = empRes.rows || []
          if (employees.length === 0) {
            this.$message.warning('该部门下暂无在职员工')
            return
          }
          listPerfSalary({ deptId: this.deptId, period: this.period, pageSize: 9999 }).then(salaryRes => {
            const existing = new Set((salaryRes.rows || []).map(r => String(r.employeeId)))
            const toInsert = employees.filter(e => !existing.has(String(e.employeeId) || String(e.infoId)))
            if (toInsert.length === 0) {
              this.$message.info('该部门下所有在职员工已有本月薪资记录')
              return
            }
            const emptyJson = JSON.stringify({})
            const tasks = toInsert.map(emp => addPerfSalary({
              employeeId: emp.employeeId || emp.infoId || '',
              deptId: this.deptId,
              period: this.period,
              baseSalary: emp.baseSalary || 0,
              perfBase: emp.perfBase || 0,
              posCoeff: emp.posCoeffDefault || 0,
              perfScore: 0,
              perfCoeff: 0,
              deptCoeff: 0,
              fixedCoeff: 0,
              adjCoeff: 0,
              adjCoeffManual: 0,
              totalCoeff: 0,
              perfWage: 0,
              deductionsJson: emptyJson,
              deductionsTotal: 0,
              bonusesJson: emptyJson,
              bonusesTotal: 0,
              otherAmount: 0,
              actualSalary: 0,
              fixedSalaryRef: '',
              adjSalaryRef: '',
              baoPerShiftRef: '',
              baoSalaryRef: '',
              totalSalaryRef: '',
              status: '0',
              remark: ''
            }))
            return Promise.allSettled(tasks)
          }).then(results => {
            if (!results) return
            const ok = results.filter(r => r.status === 'fulfilled').length
            const fail = results.filter(r => r.status === 'rejected').length
            this.$message.success(`生成完成：成功 ${ok} 条${fail > 0 ? `，失败 ${fail} 条` : ''}`)
            this.loadList()
          })
        }).finally(() => {
          this.generating = false
        })
      }).catch(() => {})
    }
  }
}
</script>

<style lang="scss" scoped>
.salary-panel {
  padding: 8px;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
  flex-shrink: 0;
}

.toolbar-left,
.toolbar-right {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.table-wrap {
  flex: 1;
  overflow: auto;
}

::v-deep .inline-edit-table {
  border: none;
  &::before, &::after { display: none; }
  th { border: none; padding: 2px 4px; font-size: 12px; color: #909399; }
  td {
    border: none;
    border-right: 1px solid #ebeef5;
    padding: 0;
  }
  .el-table__body tr:hover td { background-color: #f5f7fa !important; }
  .cell { padding: 0; height: 100%; }
}

/* 原生 input */
.cell-input {
  width: 100%;
  height: 28px;
  border: none;
  outline: none;
  text-align: right;
  padding: 0 6px;
  font-size: 12px;
  color: #303133;
  font-family: inherit;
  box-sizing: border-box;
  display: block;
  line-height: 28px;
  transition: background-color 0.15s;

  &:focus {
    background-color: #fff;
    box-shadow: 0 0 0 1px #409eff inset;
    border-radius: 0;
  }

  &--base  { background-color: #e8f4fd; }
  &--coeff { background-color: #fff8e1; }
  &--deduct { background-color: #ffebee; }
  &--bonus { background-color: #e8f5e9; }
  &--amount { background-color: #f3e5f5; }
  &--ref   { background-color: #f5f5f5; }
  &--remark { background-color: #fafafa; text-align: left; }
}

.cell-readonly {
  display: block;
  text-align: right;
  padding: 0 6px;
  font-size: 12px;
  color: #303133;
  font-weight: 500;
  line-height: 28px;
  height: 28px;

  &--deduct { color: #e53935; }
  &--bonus  { color: #43a047; }
}

.btn-save {
  color: #67c23a !important;
}

.pagination-wrapper {
  margin-top: 6px;
  display: flex;
  justify-content: flex-end;
  flex-shrink: 0;
}

.el-table .el-button + .el-button {
  margin-left: 0;
}
</style>
