<template>
  <div class="NCC-common-layout attendance-record-page" v-loading="pageLoading">
    <div class="NCC-common-layout-center">
      <div class="NCC-common-layout-main NCC-flex-main page-shell">
        <div class="record-hero">
          <div>
            <div class="record-hero__eyebrow">Attendance Record</div>
            <h2 class="record-hero__title">打卡记录</h2>
            <p class="record-hero__desc">
              按月查看员工每日打卡状态、上下班时间、打卡地点、照片与补卡信息，点击任意有记录的日期即可查看详情并进行后台补卡。
            </p>
          </div>
          <div class="record-hero__actions">
            <el-button icon="el-icon-refresh-right" @click="refreshPage">刷新</el-button>
          </div>
        </div>

        <el-alert
          title="状态会按当前考勤分组、公休、免考勤与迟到/早退规则实时重算；补卡后列表会自动刷新。"
          type="info"
          :closable="false"
          show-icon
        />

        <el-card class="filter-card" shadow="never">
          <el-form :inline="true" :model="query" class="filter-form" @submit.native.prevent>
            <el-form-item label="统计月份">
              <el-date-picker
                v-model="query.month"
                type="month"
                value-format="yyyy-MM"
                format="yyyy-MM"
                placeholder="选择月份"
              />
            </el-form-item>
            <el-form-item label="考勤分组">
              <el-select v-model="query.attendanceGroupId" clearable filterable placeholder="全部分组">
                <el-option v-for="item in attendanceGroupOptions" :key="item.id" :label="item.fullName" :value="item.id" />
              </el-select>
            </el-form-item>
            <el-form-item label="关键字">
              <el-input v-model.trim="query.keyword" clearable placeholder="员工 / 门店 / 分组" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="el-icon-search" @click="search">查询</el-button>
              <el-button icon="el-icon-refresh-right" @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>

        <div class="summary-grid">
          <div class="summary-card">
            <div class="summary-card__label">员工人数</div>
            <div class="summary-card__value">{{ summary.employeeCount }}</div>
            <div class="summary-card__hint">当前筛选条件下有打卡记录的员工数</div>
          </div>
          <div class="summary-card success">
            <div class="summary-card__label">正常打卡</div>
            <div class="summary-card__value">{{ summary.normalCount }}</div>
            <div class="summary-card__hint">状态为正常的记录数</div>
          </div>
          <div class="summary-card warning">
            <div class="summary-card__label">迟到/早退次数</div>
            <div class="summary-card__value">{{ summary.lateCount }}</div>
            <div class="summary-card__hint">命中迟到或早退规则的记录数</div>
          </div>
          <div class="summary-card danger">
            <div class="summary-card__label">请假/缺卡</div>
            <div class="summary-card__value">{{ summary.leaveAndMissingCount }}</div>
            <div class="summary-card__hint">请假、病假、缺卡、旷工等异常记录</div>
          </div>
        </div>

        <el-card class="table-card" shadow="never">
          <div slot="header" class="table-card__header">
            <div>
              <span>月度打卡明细</span>
              <span class="table-card__sub">{{ headerText }}</span>
            </div>
            <div class="table-card__legend">
              <span class="legend-item"><i class="dot success"></i>正常</span>
              <span class="legend-item"><i class="dot warning"></i>迟到</span>
              <span class="legend-item"><i class="dot info"></i>休息/无记录</span>
              <span class="legend-item"><i class="dot danger"></i>请假 / 缺卡 / 旷工</span>
            </div>
          </div>

          <NCC-table v-loading="tableLoading" :data="tableRows" border size="mini" height="calc(100vh - 390px)" class="record-table">
            <el-table-column prop="employeeName" label="员工姓名" fixed="left" min-width="140" align="left" />
            <el-table-column prop="storeName" label="门店" fixed="left" min-width="120" align="left" />
            <el-table-column prop="groupName" label="考勤分组" fixed="left" min-width="130" align="left" />
            <el-table-column label="月统计" fixed="left" min-width="180" align="left">
              <template slot-scope="scope">
                <div class="month-stat">
                  <span>正常 {{ scope.row.monthStats.normal }}</span>
                  <span>迟到 {{ scope.row.monthStats.late }}</span>
                  <span>异常 {{ scope.row.monthStats.abnormal }}</span>
                </div>
              </template>
            </el-table-column>

            <el-table-column
              v-for="day in monthDays"
              :key="day.key"
              :label="day.label"
              :min-width="110"
              align="left"
            >
              <template slot-scope="scope">
                <div
                  class="day-cell"
                  :class="[`status-${scope.row.dayRecords[day.key].statusKey}`, { clickable: scope.row.dayRecords[day.key].statusKey !== 'empty' }]"
                  @click="handleOpenDetail(scope.row, day.key, scope.row.dayRecords[day.key])"
                >
                  <div class="day-cell__time">{{ scope.row.dayRecords[day.key].timeText }}</div>
                  <el-tag :type="scope.row.dayRecords[day.key].tagType" size="mini" effect="plain">
                    {{ scope.row.dayRecords[day.key].statusText }}
                  </el-tag>
                </div>
              </template>
            </el-table-column>
          </NCC-table>

          <div v-if="!tableLoading && !tableRows.length" class="empty-wrap">
            <el-empty :image-size="68" description="当前筛选条件下暂无打卡记录" />
          </div>

          <pagination
            :hidden="!total"
            :total="total"
            :page.sync="query.currentPage"
            :limit.sync="query.pageSize"
            @pagination="loadData"
          />
        </el-card>

        <record-detail-dialog ref="recordDetailDialog" @refresh="loadData" />
      </div>
    </div>
  </div>
</template>

<script>
import dayjs from 'dayjs'
import { getAttendanceGroupSelector } from '@/api/extend/attendanceSetting'
import { getAttendanceMonthReport } from '@/api/extend/attendanceRecord'
import RecordDetailDialog from './components/record-detail-dialog.vue'

export default {
  name: 'AttendanceRecordPage',
  components: {
    RecordDetailDialog
  },
  data() {
    return {
      pageLoading: false,
      tableLoading: false,
      query: this.createDefaultQuery(),
      attendanceGroupOptions: [],
      tableRows: [],
      total: 0,
      summary: this.createEmptySummary()
    }
  },
  computed: {
    monthDays() {
      const base = dayjs(`${this.query.month}-01`)
      const total = base.daysInMonth()
      return Array.from({ length: total }).map((_, index) => {
        const date = base.date(index + 1)
        return {
          key: date.format('YYYY-MM-DD'),
          label: `${index + 1}日\n${this.getWeekLabel(date.day())}`
        }
      })
    },
    headerText() {
      return `${this.query.month} · 共 ${this.monthDays.length} 天`
    }
  },
  created() {
    this.initPage()
  },
  methods: {
    createDefaultQuery() {
      return {
        month: dayjs().format('YYYY-MM'),
        attendanceGroupId: '',
        keyword: '',
        currentPage: 1,
        pageSize: 20
      }
    },
    createEmptySummary() {
      return {
        employeeCount: 0,
        normalCount: 0,
        lateCount: 0,
        leaveAndMissingCount: 0
      }
    },
    createEmptyDayRecord() {
      return {
        statusKey: 'empty',
        statusText: '无',
        tagType: 'info',
        timeText: '--'
      }
    },
    async initPage() {
      this.pageLoading = true
      try {
        const groupRes = await getAttendanceGroupSelector().catch(() => ({ data: { list: [] } }))
        this.attendanceGroupOptions = groupRes.data.list || []
        await this.loadData()
      } finally {
        this.pageLoading = false
      }
    },
    async loadData() {
      if (!this.query.month) {
        this.summary = this.createEmptySummary()
        this.total = 0
        this.tableRows = []
        this.tableLoading = false
        return
      }
      this.tableLoading = true
      try {
        const res = await getAttendanceMonthReport(this.query)
        const data = res.data || {}
        this.summary = data.summary || this.createEmptySummary()
        this.total = data.pagination ? data.pagination.total : 0
        this.tableRows = (data.list || []).map(item => this.normalizeRow(item))
      } catch (error) {
        this.summary = this.createEmptySummary()
        this.total = 0
        this.tableRows = []
      } finally {
        this.tableLoading = false
      }
    },
    normalizeRow(item) {
      const dayRecordMap = {}
      this.monthDays.forEach(day => {
        dayRecordMap[day.key] = this.createEmptyDayRecord()
      })
      ;(item.dayRecords || []).forEach(record => {
        dayRecordMap[record.date] = {
          ...this.createEmptyDayRecord(),
          ...record
        }
      })
      return {
        ...item,
        monthStats: item.monthStats || { normal: 0, late: 0, abnormal: 0 },
        dayRecords: dayRecordMap
      }
    },
    refreshPage() {
      this.loadData()
    },
    search() {
      if (!this.query.month) {
        this.$message.warning('请选择统计月份')
        return
      }
      this.query.currentPage = 1
      this.loadData()
    },
    resetQuery() {
      this.query = this.createDefaultQuery()
      this.loadData()
    },
    handleOpenDetail(row, attendanceDate, dayRecord) {
      if (!dayRecord || dayRecord.statusKey === 'empty') return
      this.$refs.recordDetailDialog.open({
        userId: row.userId,
        attendanceDate
      })
    },
    getWeekLabel(day) {
      return ['日', '一', '二', '三', '四', '五', '六'][day]
    }
  }
}
</script>

<style lang="scss" scoped>
.attendance-record-page {
  background: #f5f7fb;

  .page-shell {
    gap: 16px;
  }

  .record-hero {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    padding: 20px 24px;
    border-radius: 16px;
    background: linear-gradient(135deg, #ffffff 0%, #f7fbff 48%, #eef5ff 100%);
    border: 1px solid #e6eef8;
    box-shadow: 0 10px 30px rgba(31, 35, 41, 0.05);
  }

  .record-hero__eyebrow {
    margin-bottom: 8px;
    color: #409eff;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .record-hero__title {
    margin: 0;
    color: #1f2d3d;
    font-size: 24px;
    font-weight: 700;
  }

  .record-hero__desc {
    margin: 8px 0 0;
    max-width: 760px;
    color: #606266;
    font-size: 14px;
    line-height: 1.7;
  }

  .record-hero__actions {
    display: flex;
    flex-shrink: 0;
    gap: 12px;
  }

  .filter-card,
  .table-card {
    border-radius: 14px;
    border: 1px solid #ebeef5;
  }

  .filter-form {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 0;
  }

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

  .summary-card {
    padding: 16px;
    border-radius: 14px;
    background: #fff;
    border: 1px solid #edf2f7;
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04);
  }

  .summary-card.success {
    border-color: rgba(103, 194, 58, 0.18);
  }

  .summary-card.warning {
    border-color: rgba(230, 162, 60, 0.2);
  }

  .summary-card.danger {
    border-color: rgba(245, 108, 108, 0.18);
  }

  .summary-card__label {
    color: #909399;
    font-size: 13px;
  }

  .summary-card__value {
    margin-top: 8px;
    color: #1f2d3d;
    font-size: 28px;
    font-weight: 700;
    line-height: 1;
  }

  .summary-card__hint {
    margin-top: 8px;
    color: #606266;
    font-size: 12px;
  }

  .table-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    font-weight: 600;
  }

  .table-card__sub {
    margin-left: 10px;
    color: #909399;
    font-size: 12px;
    font-weight: 400;
  }

  .table-card__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    color: #606266;
    font-size: 12px;
    font-weight: 400;
  }

  .legend-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }

  .dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #909399;
  }

  .dot.success { background: #67c23a; }
  .dot.warning { background: #e6a23c; }
  .dot.info { background: #909399; }
  .dot.danger { background: #f56c6c; }

  .month-stat {
    display: flex;
    flex-direction: column;
    gap: 4px;
    color: #606266;
    font-size: 12px;
    line-height: 1.5;
  }

  .day-cell {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-height: 54px;
    padding: 4px 0;
  }

  .day-cell.clickable {
    cursor: pointer;
  }

  .day-cell.clickable:hover {
    transform: translateY(-1px);
  }

  .day-cell__time {
    color: #303133;
    font-size: 12px;
    line-height: 1.4;
    white-space: nowrap;
  }

  .status-normal .day-cell__time { color: #1f8f43; }
  .status-late .day-cell__time { color: #c67a10; }
  .status-leave .day-cell__time,
  .status-sick .day-cell__time,
  .status-missing .day-cell__time,
  .status-absenteeism .day-cell__time { color: #d93f3f; }
  .status-rest .day-cell__time,
  .status-empty .day-cell__time { color: #909399; }

  .record-table {
    ::v-deep .el-table__header-wrapper th {
      background: #f8fbff;
      color: #303133;
      font-weight: 600;
      vertical-align: top;
    }

    ::v-deep .el-table__header-wrapper th .cell {
      white-space: pre-line;
      line-height: 1.3;
    }

    ::v-deep .el-table__body td {
      vertical-align: top;
    }
  }

  .empty-wrap {
    padding: 16px 0 4px;
  }

  ::v-deep .el-card__header {
    padding: 14px 18px;
  }

  ::v-deep .el-card__body {
    padding: 18px;
  }

  @media (max-width: 1200px) {
    .summary-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }

  @media (max-width: 768px) {
    .record-hero {
      flex-direction: column;
      padding: 16px;
    }

    .summary-grid {
      grid-template-columns: minmax(0, 1fr);
    }

    .table-card__header {
      flex-direction: column;
      align-items: flex-start;
    }
  }
}
</style>
