<template>
  <div class="matrix-wrapper" :class="{ 'matrix-wrapper--landscape': landscape }">
    <div v-if="!timeSlots.length" class="matrix-empty">
      本周暂无排课数据
    </div>

    <!-- ═══ 竖屏布局：天为行、时段为列，左右滚动 ═══ -->
    <div v-else-if="!landscape" class="matrix-inner">
      <div class="matrix-sidebar">
        <div class="sidebar-corner"></div>
        <div
          v-for="day in weekDays"
          :key="day.dateKey"
          class="sidebar-row"
          :class="{ 'sidebar-row--today': day.isToday }"
        >
          <div class="day-name">{{ day.name }}</div>
          <div class="day-date">{{ day.date }}</div>
        </div>
      </div>
      <div class="matrix-scroll">
        <div class="scroll-inner">
          <div class="sr-header">
            <div class="sr-spacer"></div>
            <div
              v-for="slot in timeSlots"
              :key="slot.key"
              class="header-cell sr-cell"
              :style="{ width: columnWidths[slot.key] }"
            >
              <div class="header-label">{{ slot.label }}</div>
              <div class="header-time">{{ slot.time }}</div>
            </div>
          </div>
          <div
            v-for="day in weekDays"
            :key="day.dateKey"
            class="sr-row"
          >
            <div class="sr-spacer"></div>
            <div
              v-for="slot in timeSlots"
              :key="`${day.dateKey}_${slot.key}`"
              class="event-cell sr-cell"
              :style="{ width: columnWidths[slot.key] }"
            >
              <template v-if="eventMap[day.dateKey]?.[slot.key]?.length">
                <div
                  v-for="ev in eventMap[day.dateKey][slot.key]"
                  :key="ev.id"
                  class="event-block"
                  :style="eventStyle(ev)"
                  @click.stop="onEventClick(ev)"
                >
                  <div class="ev-title">{{ ev.clazzName }}</div>
                  <div class="ev-meta">{{ slot.label }} {{ fmtTime(ev.startAt) }}-{{ fmtTime(ev.endAt) }}</div>
                  <div class="ev-teacher">{{ ev.teacherName || '未设置老师' }}</div>
                  <div class="ev-students">{{ ev.studentNames.length ? ev.studentNames.join('、') : '未设置学生' }}</div>
                </div>
              </template>
              <div v-else class="cell-empty" @click="onCellClick(day.dateKey, slot.key)">+</div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- ═══ 横屏布局：周几为 X 轴，节次为 Y 轴，表头固定，上下滚动 ═══ -->
    <div v-else class="ml-wrap">
      <div v-if="!hideLandscapeHeader" class="ml-header">
        <div class="ml-corner">时段</div>
        <div
          v-for="day in weekDays"
          :key="day.dateKey"
          class="ml-day-header"
          :class="{ 'ml-day-header--today': day.isToday }"
        >
          <div class="day-name">{{ day.name }}</div>
          <div class="day-date">{{ day.date }}</div>
        </div>
      </div>
      <div class="ml-body">
        <div v-for="slot in timeSlots" :key="slot.key" class="ml-row">
          <div class="ml-label">
            <div class="header-label">{{ slot.label }}</div>
            <div class="header-time">{{ slot.time }}</div>
          </div>
          <div
            v-for="day in weekDays"
            :key="`${day.dateKey}_${slot.key}`"
            class="ml-cell"
            @click="onCellClick(day.dateKey, slot.key)"
          >
            <template v-if="eventMap[day.dateKey]?.[slot.key]?.length">
              <div
                v-for="ev in eventMap[day.dateKey][slot.key]"
                :key="ev.id"
                class="event-block"
                :style="eventStyle(ev)"
                @click.stop="onEventClick(ev)"
              >
                <div class="ev-title">{{ ev.clazzName }}</div>
                <div class="ev-meta">{{ slot.label }} {{ fmtTime(ev.startAt) }}-{{ fmtTime(ev.endAt) }}</div>
                <div class="ev-teacher">{{ ev.teacherName || '未设置老师' }}</div>
                <div class="ev-students">{{ ev.studentNames.length ? ev.studentNames.join('、') : '未设置学生' }}</div>
              </div>
            </template>
            <div v-else class="cell-empty">+</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType } from 'vue';
import { NormalizedClazzEvent } from '../useClazzViewModel';
import { DateFormatter, formatDate, hexToRgb } from '~/utils';

interface TimeSlot {
  key: string;
  label: string;
  time: string;
}

interface WeekDay {
  dateKey: string;
  name: string;
  date: string;
  isToday: boolean;
}

const WEEKDAYS = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];

function isSameDay(a: Date, b: Date): boolean {
  return a.getFullYear() === b.getFullYear()
    && a.getMonth() === b.getMonth()
    && a.getDate() === b.getDate();
}

function fmtTime(d: Date): string {
  return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
}

function toChineseSectionNumber(value: number): string {
  const digits = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  if (value <= 10) {
    return value === 10 ? '十' : digits[value];
  }
  if (value < 20) {
    return `十${digits[value % 10]}`;
  }
  const tens = Math.floor(value / 10);
  const ones = value % 10;
  return `${digits[tens] || tens}十${ones ? digits[ones] : ''}`;
}

function sectionLabel(index: number): string {
  return `第${toChineseSectionNumber(index + 1)}节`;
}

export default defineComponent({
  name: 'ClazzMatrixView',
  props: {
    events: { type: Array as PropType<NormalizedClazzEvent[]>, required: true },
    weekStart: { type: String as PropType<string>, required: true },
    weekEnd: { type: String as PropType<string>, required: true },
    landscape: { type: Boolean, default: false },
    hideLandscapeHeader: { type: Boolean, default: false },
  },
  emits: ['cell-click', 'event-click'],
  setup(props, { emit }) {
    const today = computed(() => new Date());

    const weekDays = computed<WeekDay[]>(() => {
      const days: WeekDay[] = [];
      const start = new Date(props.weekStart);
      for (let i = 0; i < 7; i++) {
        const d = new Date(start);
        d.setDate(d.getDate() + i);
        days.push({
          dateKey: formatDate(d, DateFormatter.Date),
          name: WEEKDAYS[d.getDay()],
          date: formatDate(d, 'MM-DD'),
          isToday: isSameDay(d, today.value),
        });
      }
      return days;
    });

    /** 按当前可见课程开始时间动态生成节次。 */
    const timeSlots = computed<TimeSlot[]>(() => {
      const visibleSlotKeys = new Set<string>();
      for (const ev of props.events) {
        if (ev.visible) {
          visibleSlotKeys.add(ev.timeSlotKey);
        }
      }

      return Array.from(visibleSlotKeys).sort().map((key, index) => ({
        key,
        label: sectionLabel(index),
        time: key,
      }));
    });

    const eventMap = computed(() => {
      const map: Record<string, Record<string, NormalizedClazzEvent[]>> = {};
      for (const ev of props.events) {
        if (!ev.visible) continue;
        if (!map[ev.dateKey]) map[ev.dateKey] = {};
        if (!map[ev.dateKey][ev.timeSlotKey]) map[ev.dateKey][ev.timeSlotKey] = [];
        map[ev.dateKey][ev.timeSlotKey].push(ev);
      }
      return map;
    });

    /** 每列宽度 = 按该列最多课块数量计算，课块横向排列时宽度自适应 */
    const columnWidths = computed(() => {
      const widths: Record<string, string> = {};
      for (const slot of timeSlots.value) {
        let maxN = 1;
        for (const day of weekDays.value) {
          const evts = eventMap.value[day.dateKey]?.[slot.key] || [];
          if (evts.length > maxN) maxN = evts.length;
        }
        // 每个课块至少 1.4rem，列宽 = 数量 × 1.4rem + 间距
        widths[slot.key] = `${Math.max(1.8, maxN * 1.4 + (maxN - 1) * 0.03)}rem`;
      }
      return widths;
    });

    function eventStyle(ev: NormalizedClazzEvent) {
      if (ev.color) {
        const { r, g, b } = hexToRgb(ev.color);
        return {
          backgroundColor: `rgba(${r}, ${g}, ${b}, 0.15)`,
          borderLeft: `3px solid ${ev.color}`,
        };
      }
      return {
        backgroundColor: 'rgba(55, 136, 216, 0.12)',
        borderLeft: '3px solid #3788d8',
      };
    }

    function onCellClick(dateKey: string, slotKey: string) {
      emit('cell-click', dateKey, slotKey);
    }

    function onEventClick(ev: NormalizedClazzEvent) {
      emit('event-click', ev);
    }

    return {
      timeSlots,
      weekDays,
      eventMap,
      columnWidths,
      fmtTime,
      eventStyle,
      onCellClick,
      onEventClick,
    };
  },
});
</script>

<style scoped lang="less">
@sidebar-width: 1.2rem;
@cell-width: 1.8rem;

.matrix-wrapper {
  width: 100%;
  height: 100%;
}

.matrix-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 0.28rem;
  color: #999;
}

.matrix-inner {
  position: relative;
  height: 100%;
}

/* ═══ 左侧固定栏（absolute 覆盖在滚动区上方） ═══ */
.matrix-sidebar {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 5;
  width: @sidebar-width;
  height: 100%;
  display: flex;
  flex-direction: column;
  pointer-events: none; /* allow click-through to cells underneath */

  .sidebar-corner {
    flex-shrink: 0;
    background: #f7f8fa;
    border-bottom: 1px solid #e8e8e8;
    border-right: 1px solid #e8e8e8;
    /* height matches sr-header via same padding+content */
    padding: 0.08rem 0.04rem;
  }

  .sidebar-row {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 0.04rem;
    background: #fafafa;
    border-bottom: 1px solid #f0f0f0;
    border-right: 1px solid #f0f0f0;
    min-height: 0;

    .day-name {
      font-weight: 600;
      font-size: 0.22rem;
      line-height: 1.4;
    }
    .day-date {
      font-size: 0.18rem;
      color: #888;
      line-height: 1.3;
    }

    &--today {
      background: #e6f7ff;
      .day-name { color: #1890ff; }
    }
  }
}

/* ═══ 右侧可滚动区域 ═══ */
.matrix-scroll {
  overflow-x: auto;
  overflow-y: auto;
  height: 100%;
}

.scroll-inner {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  min-width: fit-content;
}

/* ─── 行：共用 ─── */
.sr-header {
  display: flex;
  flex-shrink: 0;
}

.sr-row {
  display: flex;
  flex: 1;
  min-height: 0;
}

/* ─── Spacer（占位与 sidebar 同宽） ─── */
.sr-spacer {
  width: @sidebar-width;
  flex-shrink: 0;
}

/* ─── 单元格 ─── */
.sr-cell {
  width: @cell-width;
  flex-shrink: 0;
}

/* ─── Slot 头部 ─── */
.header-cell {
  background: #f7f8fa;
  text-align: center;
  padding: 0.08rem 0.04rem;
  border-bottom: 1px solid #e8e8e8;
  border-left: 1px solid #f0f0f0;

  .header-label {
    font-weight: 600;
    font-size: 0.22rem;
    line-height: 1.4;
  }
  .header-time {
    font-size: 0.18rem;
    color: #888;
    line-height: 1.3;
  }
}

/* ─── 课块容器（横向排列） ─── */
.event-cell {
  display: flex;
  flex-direction: row;
  gap: 0.03rem;
  align-items: stretch;
  padding: 0.03rem;
  border-bottom: 1px solid #f5f5f5;
  border-left: 1px solid #f5f5f5;
  overflow: hidden;
}

.event-block {
  flex: 1;
  min-width: 0;
  padding: 0.04rem 0.06rem;
  border-radius: 0.04rem;
  cursor: pointer;
  overflow: hidden;

  .ev-title {
    font-weight: 600;
    font-size: 0.2rem;
    line-height: 1.4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .ev-meta {
    font-size: 0.16rem;
    color: #888;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .ev-teacher {
    font-size: 0.16rem;
    color: #555;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .ev-students {
    font-size: 0.16rem;
    color: #777;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

.cell-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  min-height: 0.5rem;
  color: #ccc;
  font-size: 0.28rem;
  cursor: pointer;
  border-radius: 0.04rem;

  &:active {
    background: #f0f5ff;
    color: #3788d8;
  }
}

/* ═══ 横屏布局 ═══ */
.matrix-wrapper--landscape {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.ml-wrap {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.ml-header {
  display: flex;
  flex-shrink: 0;
  background: #f7f8fa;
  border-bottom: 1px solid #e8e8e8;
}

.ml-corner {
  width: @sidebar-width;
  flex-shrink: 0;
  text-align: center;
  padding: 0.08rem 0.04rem;
  font-size: 0.2rem;
  color: #888;
  border-right: 1px solid #e8e8e8;
}

.ml-day-header {
  flex: 1;
  min-width: 0;
  text-align: center;
  padding: 0.08rem 0.04rem;
  border-left: 1px solid #f0f0f0;

  .day-name { font-weight: 600; font-size: 0.22rem; line-height: 1.4; }
  .day-date { font-size: 0.18rem; color: #888; line-height: 1.3; }

  &--today {
    background: #e6f7ff;
    .day-name { color: #1890ff; }
  }
}

.ml-body {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding-bottom: 0.08rem;
}

.ml-row {
  display: flex;
  border-bottom: 1px solid #f0f0f0;
}

.ml-label {
  width: @sidebar-width;
  flex-shrink: 0;
  text-align: center;
  padding: 0.08rem 0.04rem;
  background: #fafafa;
  border-right: 1px solid #f0f0f0;

  .header-label { font-weight: 600; font-size: 0.2rem; line-height: 1.4; }
  .header-time { font-size: 0.16rem; color: #888; line-height: 1.3; }
}

.ml-cell {
  flex: 1;
  min-width: 0;
  min-height: 0.6rem;
  display: flex;
  flex-direction: row;
  gap: 0.02rem;
  align-items: stretch;
  padding: 0.03rem;
  border-left: 1px solid #f5f5f5;
  overflow: hidden;

  .event-block {
    flex: 1;
    min-width: 0;
    padding: 0.04rem 0.06rem;
    border-radius: 0.04rem;
    cursor: pointer;
    overflow: hidden;

    .ev-title {
      font-weight: 600;
      font-size: 0.2rem;
      line-height: 1.4;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .ev-meta {
      font-size: 0.16rem;
      color: #888;
      line-height: 1.3;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .ev-teacher {
      font-size: 0.16rem;
      color: #555;
      line-height: 1.3;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .ev-students {
      font-size: 0.16rem;
      color: #777;
      line-height: 1.3;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }

  .cell-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    min-height: 0.5rem;
    color: #ccc;
    font-size: 0.28rem;
    cursor: pointer;
    border-radius: 0.04rem;

    &:active {
      background: #f0f5ff;
      color: #3788d8;
    }
  }
}
</style>
