<script lang="ts" setup>
import { ref, computed, watch, onMounted, onUnmounted, shallowRef } from 'vue';
import { Button, Input, Space, message, Modal, Radio, Divider, Card } from 'ant-design-vue';
import type { ClassroomApi } from '#/api';
import { saveClassroomLayoutApi } from '#/api';

defineOptions({ name: 'SeatLayoutEditor' });

interface Props {
  classroomId: number;
  layout?: ClassroomApi.ClassroomLayout | null;
}

const props = withDefaults(defineProps<Props>(), {
  layout: null,
});

const emit = defineEmits<{
  saved: [layout: ClassroomApi.ClassroomLayout];
}>();

type CellSelectableType = ClassroomApi.ClassroomLayoutCell['type'] | 'merge';

const loading = ref(false);
const cols = ref(10);
const rows = ref(8);
const selectedCellType = ref<CellSelectableType>('seat');
const editingCell = ref<{ col: number; row: number } | null>(null);
const seatNumber = ref('');
const isDrawing = ref(false);
const autoNumbering = ref(true);
const seatNumberStart = ref(1);
const drawStartCell = ref<{ col: number; row: number } | null>(null); // 绘制起始单元格
const drawCurrentCell = ref<{ col: number; row: number } | null>(null); // 绘制当前单元格
const drawnCells = ref<Set<string>>(new Set()); // 记录本次绘制操作中已绘制的单元格（用于避免重复）
const hasChangesInDrawing = ref(false); // 标记当前绘制操作是否有变化
const mergeStartCell = ref<{ col: number; row: number } | null>(null); // 合并起始单元格
const mergeCurrentCell = ref<{ col: number; row: number } | null>(null); // 合并当前滑动到的单元格
const editingSeatStatus = ref<{ col: number; row: number } | null>(null); // 正在编辑座位状态的单元格

// 初始化布局数据 - 使用 shallowRef 优化性能
const cells = shallowRef<ClassroomApi.ClassroomLayoutCell[]>([]);

// 单元格查找缓存 Map: key = "col,row", value = cell
const cellMapCache = ref<Map<string, ClassroomApi.ClassroomLayoutCell>>(new Map());

// 合并单元格主单元格映射: key = "col,row" (被合并的单元格), value = "col,row" (主单元格)
const mergeMasterMapCache = ref<Map<string, string>>(new Map());

// 更新单元格缓存
const updateCellMapCache = () => {
  const map = new Map<string, ClassroomApi.ClassroomLayoutCell>();
  const mergeMap = new Map<string, string>();

  // 先建立单元格映射
  cells.value.forEach((cell) => {
    const key = `${cell.col},${cell.row}`;
    map.set(key, cell);
  });

  // 建立合并单元格映射
  cells.value.forEach((cell) => {
    if (cell.merged) return;
    const colspan = cell.colspan || 1;
    const rowspan = cell.rowspan || 1;

    if (colspan > 1 || rowspan > 1) {
      const masterKey = `${cell.col},${cell.row}`;
      for (let r = cell.row; r < cell.row + rowspan; r++) {
        for (let c = cell.col; c < cell.col + colspan; c++) {
          if (c === cell.col && r === cell.row) continue; // 跳过主单元格
          const key = `${c},${r}`;
          mergeMap.set(key, masterKey);
        }
      }
    }
  });

  cellMapCache.value = map;
  mergeMasterMapCache.value = mergeMap;
};

// 历史记录（用于撤销）
interface HistoryState {
  cols: number;
  rows: number;
  cells: ClassroomApi.ClassroomLayoutCell[];
}

const history = ref<HistoryState[]>([]);
const canUndo = computed(() => history.value.length > 0);

// 保存当前状态到历史记录
const saveHistory = () => {
  history.value.push({
    cols: cols.value,
    rows: rows.value,
    cells: JSON.parse(JSON.stringify(cells.value)),
  });
  // 限制历史记录数量，避免内存占用过大
  if (history.value.length > 50) {
    history.value.shift();
  }
};

// 撤销操作
const handleUndo = () => {
  if (history.value.length === 0) {
    message.warning('没有可撤销的操作');
    return;
  }

  const lastState = history.value.pop()!;
  cols.value = lastState.cols;
  rows.value = lastState.rows;
  cells.value = JSON.parse(JSON.stringify(lastState.cells));
  updateCellMapCache();
  message.success('已撤销');
};

// 初始化布局
const initLayout = () => {
  cells.value = [];
  for (let row = 0; row < rows.value; row++) {
    for (let col = 0; col < cols.value; col++) {
      cells.value.push({
        col,
        row,
        type: 'empty',
        colspan: 1,
        rowspan: 1,
        merged: false,
      });
    }
  }
  updateCellMapCache();
};

// 从现有布局加载
const loadLayout = () => {
  if (props.layout) {
    cols.value = props.layout.cols || 10;
    rows.value = props.layout.rows || 8;
    if (props.layout.cells && props.layout.cells.length > 0) {
      cells.value = JSON.parse(JSON.stringify(props.layout.cells));
      // 确保所有单元格都有默认的合并属性，并修复类型字段
      cells.value.forEach((cell) => {
        if (cell.colspan === undefined) cell.colspan = 1;
        if (cell.rowspan === undefined) cell.rowspan = 1;
        if (cell.merged === undefined) cell.merged = false;
        // 将 monitor 类型转换为 projector（兼容后端数据）
        if ((cell.type as any) === 'monitor') {
          cell.type = 'projector';
        }
      });

      // 确保所有位置都有单元格数据（补充缺失的空白单元格）
      const cellMap = new Map<string, ClassroomApi.ClassroomLayoutCell>();
      cells.value.forEach((cell) => {
        const key = `${cell.col},${cell.row}`;
        cellMap.set(key, cell);
      });

      // 检查并补充缺失的单元格
      for (let row = 0; row < rows.value; row++) {
        for (let col = 0; col < cols.value; col++) {
          const key = `${col},${row}`;
          if (!cellMap.has(key)) {
            cells.value.push({
              col,
              row,
              type: 'empty',
              colspan: 1,
              rowspan: 1,
              merged: false,
            });
          }
        }
      }
    } else {
      initLayout();
    }
  } else {
    initLayout();
  }
  updateCellMapCache();
};

// 监听布局变化
watch(
  () => props.layout,
  () => {
    loadLayout();
  },
  { immediate: true },
);

// 切换类型时，如果离开合并模式，重置合并选区与绘制状态
watch(
  () => selectedCellType.value,
  (val) => {
    if (val !== 'merge') {
      mergeStartCell.value = null;
      mergeCurrentCell.value = null;
      isDrawing.value = false;
    }
  },
);

// 在左侧添加列
const addColumnLeft = () => {
  saveHistory();
  // 所有现有单元格的列号加1
  cells.value.forEach((cell) => {
    cell.col += 1;
  });
  // 添加新列（列号为0）
  for (let row = 0; row < rows.value; row++) {
    cells.value.push({
      col: 0,
      row,
      type: 'empty',
      colspan: 1,
      rowspan: 1,
      merged: false,
    });
  }
  cols.value += 1;
  updateCellMapCache();
  message.success('已在左侧添加一列');
};

// 在右侧添加列
const addColumnRight = () => {
  saveHistory();
  // 添加新列（列号为当前最大列号+1）
  for (let row = 0; row < rows.value; row++) {
    cells.value.push({
      col: cols.value,
      row,
      type: 'empty',
      colspan: 1,
      rowspan: 1,
      merged: false,
    });
  }
  cols.value += 1;
  updateCellMapCache();
  message.success('已在右侧添加一列');
};

// 在上方添加行
const addRowTop = () => {
  saveHistory();
  // 所有现有单元格的行号加1
  cells.value.forEach((cell) => {
    cell.row += 1;
  });
  // 添加新行（行号为0）
  for (let col = 0; col < cols.value; col++) {
    cells.value.push({
      col,
      row: 0,
      type: 'empty',
      colspan: 1,
      rowspan: 1,
      merged: false,
    });
  }
  rows.value += 1;
  updateCellMapCache();
  message.success('已在上方添加一行');
};

// 在下方添加行
const addRowBottom = () => {
  saveHistory();
  // 添加新行（行号为当前最大行号+1）
  for (let col = 0; col < cols.value; col++) {
    cells.value.push({
      col,
      row: rows.value,
      type: 'empty',
      colspan: 1,
      rowspan: 1,
      merged: false,
    });
  }
  rows.value += 1;
  updateCellMapCache();
  message.success('已在下方添加一行');
};

// 获取单元格 - 使用缓存优化性能
const getCell = (col: number, row: number) => {
  const key = `${col},${row}`;
  return cellMapCache.value.get(key);
};

// 获取下一个座位编号
const getNextSeatNumber = () => {
  const seats = cells.value.filter((c) => c.type === 'seat' && c.number);
  if (seats.length === 0) {
    return String(seatNumberStart.value);
  }
  // 找到最大的座位编号
  const maxNumber = Math.max(
    ...seats.map((c) => {
      const num = parseInt(c.number || '0', 10);
      return isNaN(num) ? 0 : num;
    }),
  );
  return String(maxNumber + 1);
};

// 设置单元格类型
const setCellType = (col: number, row: number, type: ClassroomApi.ClassroomLayoutCell['type']) => {
  const cell = getCell(col, row);
  if (!cell || cell.merged) return; // 被合并的单元格不能直接设置类型

  const wasSeat = cell.type === 'seat';

  cell.type = type;

  if (type !== 'seat') {
    delete cell.number;
    delete cell.status;
  }

  if (type === 'empty') {
    delete cell.name;
  } else if (type === 'pillar' || type === 'aisle' || type === 'door' || type === 'projector') {
    const nameMap: Record<ClassroomApi.ClassroomLayoutCell['type'], string> = {
      pillar: '柱子',
      aisle: '过道',
      door: '门',
      projector: '投影仪',
      seat: '座位',
      empty: '',
    };
    cell.name = nameMap[type];
  } else if (type === 'seat') {
    // 如果是座位类型
    if (autoNumbering.value) {
      // 自动编号：只有从非座位类型变为座位类型时才分配新编号
      if (!wasSeat || !cell.number) {
        cell.number = getNextSeatNumber();
        cell.status = 1; // 默认可用
      }
      // 如果已经是座位类型，保持原有编号和状态不变
    } else if (!cell.number) {
      // 手动输入模式，如果没有编号，设置为空
      cell.status = 1; // 默认可用
    }
  }
  // 更新缓存（单元格对象引用未变，但内容变了，需要更新 Map）
  const key = `${col},${row}`;
  cellMapCache.value.set(key, cell);
};

// 处理单元格设置（用于点击和拖动）
const applyCellType = (col: number, row: number, skipSameType = false) => {
  // 合并模式下不做类型绘制，交给合并逻辑处理
  if (selectedCellType.value === 'merge') {
    return;
  }

  const cell = getCell(col, row);
  if (!cell) return;

  const oldType = cell.type;

  // 如果跳过相同类型，且当前类型已经是目标类型，则不处理
  if (skipSameType && cell.type === selectedCellType.value) {
    // 如果是座位类型但没有编号，需要输入
    if (selectedCellType.value === 'seat' && !autoNumbering.value && !cell.number) {
      editingCell.value = { col, row };
      seatNumber.value = '';
    }
    return;
  }

  // 在绘制模式下，检查是否已经绘制过（避免重复）
  if (isDrawing.value) {
    const cellKey = `${col},${row}`;
    if (drawnCells.value.has(cellKey)) {
      return;
    }
    drawnCells.value.add(cellKey);
  }

  if (selectedCellType.value === 'seat' && !autoNumbering.value && !isDrawing.value) {
    // 如果是座位且不自动编号，且不是拖动模式，需要输入座位号
    editingCell.value = { col, row };
    seatNumber.value = cell?.number || '';
  } else {
    // 其他情况直接设置
    setCellType(col, row, selectedCellType.value);
    // 标记有变化
    if (oldType !== selectedCellType.value) {
      hasChangesInDrawing.value = true;
    }
  }
};

// 填充从起点到终点之间的所有单元格
const fillCellsBetween = (startCol: number, startRow: number, endCol: number, endRow: number) => {
  const minCol = Math.min(startCol, endCol);
  const maxCol = Math.max(startCol, endCol);
  const minRow = Math.min(startRow, endRow);
  const maxRow = Math.max(startRow, endRow);

  // 合并模式下不填充
  if (selectedCellType.value === 'merge') {
    return;
  }

  // 按顺序填充所有单元格
  for (let row = minRow; row <= maxRow; row++) {
    for (let col = minCol; col <= maxCol; col++) {
      const cellKey = `${col},${row}`;
      if (!drawnCells.value.has(cellKey)) {
        drawnCells.value.add(cellKey);
        const cell = getCell(col, row);
        if (cell) {
          const oldType = cell.type;
          setCellType(col, row, selectedCellType.value as ClassroomApi.ClassroomLayoutCell['type']);
          if (oldType !== selectedCellType.value) {
            hasChangesInDrawing.value = true;
          }
        }
      }
    }
  }
};

// 点击单元格
const handleCellClick = (col: number, row: number) => {
  // 合并模式下，点击交给拖拽流程处理，这里不做处理
  if (selectedCellType.value === 'merge') return;

  if (!isDrawing.value) {
    // 点击操作前保存历史记录
    const cell = getCell(col, row);
    if (cell && cell.type !== selectedCellType.value) {
      saveHistory();
    }
    applyCellType(col, row, true);
  }
};

// 鼠标按下开始绘制/合并
const handleCellMouseDown = (col: number, row: number, event: MouseEvent) => {
  // 右键点击不触发绘制
  if (event.button === 2) {
    return;
  }

  event.preventDefault();
  isDrawing.value = true;
  hasChangesInDrawing.value = false; // 重置变化标记
  drawnCells.value.clear(); // 清空已绘制单元格记录

  if (selectedCellType.value === 'merge') {
    mergeStartCell.value = { col, row };
    mergeCurrentCell.value = { col, row };
    return;
  }

  // 记录绘制起始位置
  drawStartCell.value = { col, row };
  drawCurrentCell.value = { col, row };

  // 拖动操作开始前保存历史记录
  saveHistory();
  applyCellType(col, row, false);
};

// 鼠标移动绘制（使用 requestAnimationFrame 优化性能）
let rafId: number | null = null;
const handleCellMouseEnter = (col: number, row: number) => {
  if (!isDrawing.value) return;

  if (selectedCellType.value === 'merge') {
    mergeCurrentCell.value = { col, row };
    return;
  }

  // 更新当前绘制位置
  if (drawStartCell.value) {
    drawCurrentCell.value = { col, row };

    // 使用 requestAnimationFrame 优化性能，避免过于频繁的更新
    if (rafId !== null) {
      cancelAnimationFrame(rafId);
    }

    rafId = requestAnimationFrame(() => {
      // 填充从起点到当前点的所有单元格
      if (drawStartCell.value && drawCurrentCell.value) {
        fillCellsBetween(
          drawStartCell.value.col,
          drawStartCell.value.row,
          drawCurrentCell.value.col,
          drawCurrentCell.value.row
        );
      }
      rafId = null;
    });
  } else {
    // 如果没有起始点，直接应用（兼容旧逻辑）
    applyCellType(col, row, false);
  }
};

// 鼠标释放停止绘制/合并
const handleCellMouseUp = () => {
  if (!isDrawing.value) return;

  // 清除 requestAnimationFrame
  if (rafId !== null) {
    cancelAnimationFrame(rafId);
    rafId = null;
  }

  if (selectedCellType.value === 'merge') {
    const start = mergeStartCell.value;
    const end = mergeCurrentCell.value;
    if (start && end) {
      const colspan = Math.abs(end.col - start.col) + 1;
      const rowspan = Math.abs(end.row - start.row) + 1;
      if (colspan === 1 && rowspan === 1) {
        message.warning('请选择至少两个单元格进行合并');
      } else {
        saveHistory();
        mergeCells(start.col, start.row, end.col, end.row);
      }
    }
    mergeStartCell.value = null;
    mergeCurrentCell.value = null;
    isDrawing.value = false;
    return;
  }

  // 确保填充到最终位置
  if (drawStartCell.value && drawCurrentCell.value) {
    fillCellsBetween(
      drawStartCell.value.col,
      drawStartCell.value.row,
      drawCurrentCell.value.col,
      drawCurrentCell.value.row
    );
  }

  isDrawing.value = false;
  drawStartCell.value = null;
  drawCurrentCell.value = null;
  drawnCells.value.clear();

  // 如果拖动过程中没有实际变化，撤销刚才保存的历史记录
  if (!hasChangesInDrawing.value && history.value.length > 0) {
    history.value.pop();
  }
  hasChangesInDrawing.value = false;
  updateCellMapCache();
};

// 全局鼠标事件处理（确保即使鼠标移出单元格也能停止绘制）
const handleGlobalMouseUp = () => {
  handleCellMouseUp();
};

// 组件挂载时添加全局事件监听
onMounted(() => {
  document.addEventListener('mouseup', handleGlobalMouseUp);
  document.addEventListener('mouseleave', handleGlobalMouseUp);
});

onUnmounted(() => {
  document.removeEventListener('mouseup', handleGlobalMouseUp);
  document.removeEventListener('mouseleave', handleGlobalMouseUp);
});

// 确认座位号
const confirmSeatNumber = () => {
  if (!editingCell.value) return;
  const cell = getCell(editingCell.value.col, editingCell.value.row);
  if (cell) {
    // 如果类型或编号发生变化，保存历史记录
    if (cell.type !== 'seat' || cell.number !== seatNumber.value) {
      saveHistory();
    }
    cell.type = 'seat';
    cell.number = seatNumber.value;
    cell.status = 1; // 默认可用
    // 更新缓存
    const key = `${editingCell.value.col},${editingCell.value.row}`;
    cellMapCache.value.set(key, cell);
  }
  editingCell.value = null;
  seatNumber.value = '';
};

// 批量填充
const handleFillAll = () => {
  if (selectedCellType.value === 'merge') {
    message.warning('合并模式下无法批量填充');
    return;
  }
  if (selectedCellType.value === 'empty') {
    message.warning('不能批量填充为空白类型');
    return;
  }

  Modal.confirm({
    title: '确认批量填充',
    content: `确定要将所有空白单元格填充为"${getTypeName(selectedCellType.value)}"吗？`,
    onOk: () => {
      saveHistory();
      // 如果是座位类型且自动编号，先获取当前最大编号
      const emptyCells = cells.value.filter((cell) => cell.type === 'empty' && !cell.merged);
      const cellType = selectedCellType.value as ClassroomApi.ClassroomLayoutCell['type'];
      emptyCells.forEach((cell) => {
        setCellType(cell.col, cell.row, cellType);
      });
      updateCellMapCache();
      message.success(`批量填充完成，共填充 ${emptyCells.length} 个单元格`);
    },
  });
};

// 获取类型名称
const getTypeName = (type: CellSelectableType) => {
  const typeMap: Record<string, string> = {
    empty: '空白',
    seat: '座位',
    pillar: '柱子',
    aisle: '过道',
    door: '门',
    projector: '投影仪',
    merge: '合并',
  };
  return typeMap[type] || type;
};

// 统计座位数量
const seatCount = computed(() => {
  return cells.value.filter((c) => c.type === 'seat').length;
});

// 取消编辑
const cancelEdit = () => {
  editingCell.value = null;
  seatNumber.value = '';
};

// 获取单元格样式 - 优化性能，使用缓存
const getCellClass = (col: number, row: number) => {
  const cell = getCell(col, row);
  if (!cell) return 'cell-empty';

  // 如果是被合并的单元格，不显示
  if (cell.merged) {
    return 'cell cell-merged';
  }

  // 使用缓存检查是否被其他合并单元格覆盖
  const key = `${col},${row}`;
  if (mergeMasterMapCache.value.has(key)) {
    return 'cell cell-merged';
  }

  const classes = ['cell', `cell-${cell.type}`];

  // 如果是座位且禁坐，添加禁坐样式
  if (cell.type === 'seat' && cell.status === 0) {
    classes.push('cell-disabled');
  }

  if (editingCell.value && editingCell.value.col === col && editingCell.value.row === row) {
    classes.push('cell-editing');
  }

  // 合并拖动预览：当前选择合并类型，且在选择矩形范围内
  if (selectedCellType.value === 'merge' && mergeStartCell.value && mergeCurrentCell.value) {
    const minCol = Math.min(mergeStartCell.value.col, mergeCurrentCell.value.col);
    const maxCol = Math.max(mergeStartCell.value.col, mergeCurrentCell.value.col);
    const minRow = Math.min(mergeStartCell.value.row, mergeCurrentCell.value.row);
    const maxRow = Math.max(mergeStartCell.value.row, mergeCurrentCell.value.row);
    if (col >= minCol && col <= maxCol && row >= minRow && row <= maxRow) {
      classes.push('cell-merge-selected');
    }
  }

  return classes.join(' ');
};

// 获取单元格显示文本
const getCellText = (col: number, row: number) => {
  const cell = getCell(col, row);
  if (!cell || cell.merged) return '';

  if (cell.type === 'seat' && cell.number) {
    return cell.number;
  }
  if (cell.name) {
    return cell.name;
  }
  return '';
};

// 获取单元格的 Grid 样式属性（用于合并单元格）
const getCellGridStyle = (col: number, row: number) => {
  const cell = getCell(col, row);

  // 使用 CSS Grid 的 grid-column 和 grid-row 来实现合并
  // grid 布局中，列从1开始（第1列是行号），行从1开始
  // 传入的 col 和 row 是数组索引（从0开始），需要转换为Grid位置（从1开始）
  const gridColumn = col + 2; // +2 因为第1列是行号，数据列从第2列开始
  const gridRow = row + 1; // row 是数组索引（0开始），Grid行号从1开始，所以+1

  const style: Record<string, string> = {};

  // 如果单元格不存在或被合并，仍然需要设置基本位置（用于空白单元格显示）
  if (!cell || cell.merged) {
    // 被合并的单元格不设置 grid 位置，由主单元格占据
    // 但如果单元格不存在（空白），需要设置位置以便显示
    if (!cell) {
      style.gridColumn = `${gridColumn} / span 1`;
      style.gridRow = `${gridRow} / span 1`;
    }
    return style;
  }

  const colspan = cell.colspan || 1;
  const rowspan = cell.rowspan || 1;

  if (colspan > 1 || rowspan > 1) {
    // 合并单元格：使用 span 语法
    style.gridColumn = `${gridColumn} / span ${colspan}`;
    style.gridRow = `${gridRow} / span ${rowspan}`;
  } else {
    // 普通单元格：只设置位置（也可以显式设置span 1）
    style.gridColumn = `${gridColumn} / span 1`;
    style.gridRow = `${gridRow} / span 1`;
  }

  return style;
};

// 检查单元格是否应该渲染（用于合并单元格，Grid布局中只渲染主单元格）- 优化性能
const shouldRenderCell = (col: number, row: number) => {
  // 首先检查是否在有效范围内
  if (col < 0 || col >= cols.value || row < 0 || row >= rows.value) {
    return false;
  }

  const cell = getCell(col, row);

  // 如果单元格不存在，应该渲染（作为空白单元格）
  if (!cell) {
    return true;
  }

  // 被合并的单元格不渲染
  if (cell.merged) {
    return false;
  }

  // 使用缓存检查是否被其他合并单元格覆盖
  const key = `${col},${row}`;
  if (mergeMasterMapCache.value.has(key)) {
    return false;
  }

  return true;
};

// 保存布局
const handleSave = async () => {
  if (!props.classroomId) {
    message.error('教室ID不能为空');
    return;
  }

  loading.value = true;
  try {
    // 保存前将 projector 转换为 monitor（兼容后端）
    const cellsToSave = cells.value.map((cell) => {
      const cellCopy = { ...cell };
      if (cellCopy.type === 'projector') {
        (cellCopy as any).type = 'monitor';
      }
      return cellCopy;
    });

    const layout: ClassroomApi.ClassroomLayout = {
      cols: cols.value,
      rows: rows.value,
      cells: cellsToSave as any,
    };

    await saveClassroomLayoutApi({
      id: props.classroomId,
      layout,
    });

    message.success('座位布局保存成功');
    // 发送保存后的布局（使用前端类型）
    emit('saved', {
      cols: cols.value,
      rows: rows.value,
      cells: cells.value,
    });
  } catch (error) {
    console.error('保存座位布局失败:', error);
    message.error('保存座位布局失败');
  } finally {
    loading.value = false;
  }
};

// 清空布局
const handleClear = () => {
  Modal.confirm({
    title: '确认清空',
    content: '确定要清空所有座位布局吗？',
    onOk: () => {
      saveHistory(); // 保存清空前的状态，可以撤销
      initLayout();
      message.success('已清空布局');
    },
  });
};

// 检查单元格是否是合并的主单元格
const isMergeMaster = (col: number, row: number) => {
  const cell = getCell(col, row);
  return cell && (cell.colspan && cell.colspan > 1 || cell.rowspan && cell.rowspan > 1);
};

// 获取合并的主单元格
const getMergeMaster = (col: number, row: number) => {
  // 遍历所有单元格，找到包含该单元格的合并主单元格
  for (const cell of cells.value) {
    if (cell.merged) continue;
    const colspan = cell.colspan || 1;
    const rowspan = cell.rowspan || 1;
    if (
      col >= cell.col &&
      col < cell.col + colspan &&
      row >= cell.row &&
      row < cell.row + rowspan
    ) {
      return cell;
    }
  }
  return null;
};

// 取消合并单元格
const unmergeCell = (col: number, row: number) => {
  const cell = getCell(col, row);
  if (!cell) return;

  const colspan = cell.colspan || 1;
  const rowspan = cell.rowspan || 1;

  // 清除被合并的单元格标记
  for (let r = cell.row; r < cell.row + rowspan; r++) {
    for (let c = cell.col; c < cell.col + colspan; c++) {
      if (c === col && r === row) continue; // 跳过主单元格
      const mergedCell = getCell(c, r);
      if (mergedCell) {
        mergedCell.merged = false;
        // 恢复为空白类型
        if (mergedCell.type === 'empty') {
          mergedCell.colspan = 1;
          mergedCell.rowspan = 1;
        }
      }
    }
  }

  // 重置主单元格的合并属性
  cell.colspan = 1;
  cell.rowspan = 1;
  updateCellMapCache();
};

// 合并单元格
const mergeCells = (startCol: number, startRow: number, endCol: number, endRow: number) => {
  // 确保起始位置在左上角
  const minCol = Math.min(startCol, endCol);
  const maxCol = Math.max(startCol, endCol);
  const minRow = Math.min(startRow, endRow);
  const maxRow = Math.max(startRow, endRow);

  const colspan = maxCol - minCol + 1;
  const rowspan = maxRow - minRow + 1;

  // 如果只选择一个单元格，不进行合并
  if (colspan === 1 && rowspan === 1) {
    message.warning('请选择至少两个单元格进行合并');
    return;
  }

  // 检查范围内是否有已合并的单元格
  for (let r = minRow; r <= maxRow; r++) {
    for (let c = minCol; c <= maxCol; c++) {
      const cell = getCell(c, r);
      if (!cell) continue;

      // 如果单元格是合并的主单元格，先取消合并
      if (isMergeMaster(c, r)) {
        unmergeCell(c, r);
      }

      // 如果单元格是被合并的单元格，需要找到主单元格并取消合并
      if (cell.merged) {
        const master = getMergeMaster(c, r);
        if (master) {
          unmergeCell(master.col, master.row);
        }
      }
    }
  }

  // 获取主单元格（左上角的单元格）
  const masterCell = getCell(minCol, minRow);
  if (!masterCell) return;

  // 设置主单元格的合并属性
  masterCell.colspan = colspan;
  masterCell.rowspan = rowspan;

  // 标记其他单元格为被合并
  for (let r = minRow; r <= maxRow; r++) {
    for (let c = minCol; c <= maxCol; c++) {
      if (c === minCol && r === minRow) continue; // 跳过主单元格
      const cell = getCell(c, r);
      if (cell) {
        cell.merged = true;
        // 保持单元格的类型和属性，但标记为被合并
      }
    }
  }

  updateCellMapCache();
  message.success(`已合并 ${colspan}×${rowspan} 的单元格`);
};

// 设置座位禁坐状态
const setSeatDisabled = (col: number, row: number) => {
  const cell = getCell(col, row);
  if (!cell || cell.type !== 'seat') {
    message.warning('只能对座位设置禁坐状态');
    return;
  }

  saveHistory();
  cell.status = cell.status === 0 ? 1 : 0; // 切换状态
  // 更新缓存
  const key = `${col},${row}`;
  cellMapCache.value.set(key, cell);
  message.success(cell.status === 0 ? '座位已设置为禁坐' : '座位已设置为可用');
};

// 右键菜单处理（用于设置座位禁坐）
const handleCellContextMenu = (col: number, row: number, event: MouseEvent) => {
  event.preventDefault();
  const cell = getCell(col, row);
  if (cell && cell.type === 'seat') {
    editingSeatStatus.value = { col, row };
    Modal.confirm({
      title: '设置座位状态',
      content: `当前状态：${cell.status === 0 ? '禁坐' : '可用'}`,
      okText: cell.status === 0 ? '设为可用' : '设为禁坐',
      cancelText: '取消',
      onOk: () => {
        setSeatDisabled(col, row);
        editingSeatStatus.value = null;
      },
      onCancel: () => {
        editingSeatStatus.value = null;
      },
    });
  }
};
</script>

<template>
  <div class="seat-layout-editor">
    <Card>
      <div class="editor-toolbar">
        <div class="toolbar-section">
          <div class="toolbar-item">
            <label class="toolbar-label">当前列数：</label>
            <span class="toolbar-value">{{ cols }}</span>
            <Button size="small" @click="addColumnLeft">左侧添加</Button>
            <Button size="small" @click="addColumnRight">右侧添加</Button>
          </div>
          <Divider type="vertical" />
          <div class="toolbar-item">
            <label class="toolbar-label">当前行数：</label>
            <span class="toolbar-value">{{ rows }}</span>
            <Button size="small" @click="addRowTop">上方添加</Button>
            <Button size="small" @click="addRowBottom">下方添加</Button>
          </div>
          <Divider type="vertical" />
          <div class="toolbar-item">
            <label class="toolbar-label">选择类型：</label>
            <Radio.Group v-model:value="selectedCellType" button-style="solid" size="large">
              <Radio.Button value="empty">
                <span class="type-icon type-empty"></span>
                空白
              </Radio.Button>
              <Radio.Button value="seat">
                <span class="type-icon type-seat"></span>
                座位
              </Radio.Button>
              <Radio.Button value="pillar">
                <span class="type-icon type-pillar"></span>
                柱子
              </Radio.Button>
              <Radio.Button value="aisle">
                <span class="type-icon type-aisle"></span>
                过道
              </Radio.Button>
              <Radio.Button value="door">
                <span class="type-icon type-door"></span>
                门
              </Radio.Button>
              <Radio.Button value="projector">
                <span class="type-icon type-projector"></span>
                投影仪
              </Radio.Button>
              <Radio.Button value="merge">
                <span class="type-icon type-merge"></span>
                合并
              </Radio.Button>
            </Radio.Group>
          </div>
        </div>
        <Divider />
        <div class="toolbar-section">
          <div class="toolbar-item">
            <label class="toolbar-label">座位编号：</label>
            <Radio.Group v-model:value="autoNumbering">
              <Radio :value="true">自动编号</Radio>
              <Radio :value="false">手动输入</Radio>
            </Radio.Group>
            <Input
              v-if="autoNumbering"
              :value="String(seatNumberStart)"
              type="number"
              :min="1"
              :style="{ width: '100px', marginLeft: '8px' }"
              placeholder="起始编号"
              @change="(e: any) => { const val = parseInt(e.target.value); if (!isNaN(val) && val > 0) seatNumberStart = val; }"
            />
          </div>
          <Divider type="vertical" />
          <Space>
            <Button :disabled="!canUndo" @click="handleUndo">
              <template #icon>
                <span>↶</span>
              </template>
              撤销
            </Button>
            <Button @click="handleFillAll">批量填充空白</Button>
            <Button danger @click="handleClear">清空布局</Button>
            <Button type="primary" size="large" :loading="loading" @click="handleSave">
              保存布局
            </Button>
          </Space>
        </div>
        <div class="toolbar-stats">
          <span>座位总数：<strong>{{ seatCount }}</strong></span>
        </div>
      </div>
    </Card>

    <Card class="layout-card">
      <div class="editor-hint">
        <p>
          <strong>操作提示：</strong>
          <strong>按住鼠标左键拖动</strong>可以连续绘制多个单元格。
          {{ autoNumbering ? '座位将自动编号。' : '选择"座位"时需要手动输入座位号。' }}
          <strong>右键点击座位</strong>可以设置禁坐状态。
        </p>
      </div>

      <div class="layout-container" :style="{ '--cols': cols, '--rows': rows }">
        <div class="layout-header">
          <div class="header-cell"></div>
          <div
            v-for="col in cols"
            :key="`header-col-${col}`"
            class="header-cell header-col"
          >
            {{ col }}
          </div>
        </div>
        <div class="layout-body">
          <template v-for="row in rows" :key="`row-${row}`">
            <div class="header-cell header-row" :style="{ gridColumn: '1', gridRow: String(row) }">{{ row }}</div>
            <template v-for="col in cols" :key="`cell-${row}-${col}`">
              <div
                v-if="shouldRenderCell(col - 1, row - 1)"
                :class="getCellClass(col - 1, row - 1)"
                :style="getCellGridStyle(col - 1, row - 1)"
                @click="handleCellClick(col - 1, row - 1)"
                @mousedown="(e) => handleCellMouseDown(col - 1, row - 1, e)"
                @mouseenter="handleCellMouseEnter(col - 1, row - 1)"
                @contextmenu="(e) => handleCellContextMenu(col - 1, row - 1, e)"
              >
                {{ getCellText(col - 1, row - 1) }}
                <span v-if="getCell(col - 1, row - 1)?.type === 'seat' && getCell(col - 1, row - 1)?.status === 0" class="disabled-icon">🚫</span>
              </div>
            </template>
          </template>
        </div>
      </div>
    </Card>

    <Modal
      :open="!!editingCell"
      title="输入座位号"
      @ok="confirmSeatNumber"
      @cancel="cancelEdit"
    >
      <Input
        v-model:value="seatNumber"
        placeholder="请输入座位号"
        @press-enter="confirmSeatNumber"
      />
    </Modal>
  </div>
</template>

<style scoped>
.seat-layout-editor {
  padding: 0;
}

.editor-toolbar {
  padding: 0;
}

.toolbar-section {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 12px;
}

.toolbar-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.toolbar-label {
  font-size: 15px;
  font-weight: 600;
  color: var(--ant-color-text);
  white-space: nowrap;
}

.toolbar-value {
  display: inline-block;
  min-width: 30px;
  padding: 0 8px;
  font-size: 15px;
  font-weight: 700;
  color: var(--ant-color-primary);
  text-align: center;
}

.toolbar-item :deep(.ant-radio-wrapper),
.toolbar-item :deep(.ant-radio-button-wrapper) {
  color: var(--ant-color-text);
  font-weight: 500;
}

.toolbar-item :deep(.ant-radio-button-wrapper-checked) {
  color: var(--ant-color-text-inverse);
}

.toolbar-stats {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--ant-color-border-secondary);
  font-size: 15px;
  color: var(--ant-color-text-secondary);
  font-weight: 500;
}

.toolbar-stats strong {
  color: var(--ant-color-primary);
  font-size: 18px;
  font-weight: 700;
}

.type-icon {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 2px;
  margin-right: 4px;
  vertical-align: middle;
}

.type-empty {
  background: #fff;
  border: 1px solid #d9d9d9;
}

.type-seat {
  background: #52c41a;
}

.type-pillar {
  background: #8c8c8c;
}

.type-aisle {
  background: #faad14;
}

.type-door {
  background: #1890ff;
}

.type-projector {
  background: #13c2c2;
}

.type-merge {
  background: #722ed1;
}

.layout-card {
  margin-top: 16px;
}

.editor-hint {
  margin-bottom: 16px;
  padding: 12px 16px;
  background: var(--ant-color-info-bg, #e6f7ff);
  border: 1px solid var(--ant-color-info-border, #91d5ff);
  border-radius: 4px;
}

.editor-hint p {
  margin: 0;
  font-size: 14px;
  color: var(--ant-color-info, #1890ff);
  line-height: 1.6;
}

.merge-indicator {
  display: inline-block;
  margin-left: 12px;
  padding: 2px 8px;
  background: #1890ff;
  color: #fff;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
  animation: blink 1s infinite;
}

@keyframes blink {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.6;
  }
}

.layout-container {
  overflow-x: auto;
  padding: 10px;
  background: var(--ant-color-fill-tertiary, #fafafa);
  border-radius: 4px;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

.layout-header {
  display: flex;
  margin-bottom: 4px;
  gap: 4px;
}

.layout-body {
  display: grid;
  grid-template-columns: 45px repeat(var(--cols, 10), 45px);
  grid-template-rows: repeat(var(--rows, 8), 45px);
  gap: 4px;
  grid-auto-flow: row;
  align-items: stretch;
  justify-items: stretch;
}

.layout-row {
  display: contents; /* 让行容器不参与布局，直接使用 grid */
}

.header-cell {
  width: 45px;
  min-width: 45px;
  height: 45px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 600;
  color: var(--ant-color-text-secondary, #595959);
  background: var(--ant-color-fill-secondary, #f5f5f5);
  border: 2px solid var(--ant-color-border-secondary, #e8e8e8);
  border-radius: 2px;
  user-select: none;
  box-sizing: border-box;
}

.header-col {
  background: var(--ant-color-primary-bg, #e6f7ff);
  color: var(--ant-color-primary, #1890ff);
  font-weight: 700;
}

.header-row {
  background: var(--ant-color-success-bg, #f6ffed);
  color: var(--ant-color-success, #52c41a);
  font-weight: 700;
}

.cell {
  /* Grid布局中，宽度和高度由grid自动控制，不设置固定值 */
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: 2px solid #d9d9d9;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 600;
  transition: all 0.15s;
  user-select: none;
  position: relative;
  line-height: 1;
  box-sizing: border-box;
  min-width: 0; /* 允许grid控制宽度 */
  min-height: 0; /* 允许grid控制高度 */
}

.cell:hover {
  border-color: #40a9ff;
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
  z-index: 1;
  /* 移除 transform: scale，避免影响合并单元格的布局 */
}


.cell-empty {
  background: var(--ant-color-bg-container, #ffffff);
  color: var(--ant-color-text-disabled, #bfbfbf);
  border-color: var(--ant-color-border, #d9d9d9);
}

.cell-seat {
  background: #52c41a;
  color: #ffffff;
  border-color: #389e0d;
  font-weight: 700;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  position: relative;
}

.cell-seat:hover {
  background: #73d13d;
  border-color: #52c41a;
  box-shadow: 0 0 0 3px rgba(82, 196, 26, 0.2);
}

.cell-seat.cell-disabled {
  background: #ff7875;
  border-color: #ff4d4f;
  opacity: 0.7;
  position: relative;
}

.cell-seat.cell-disabled:hover {
  background: #ff9c9a;
  border-color: #ff7875;
  box-shadow: 0 0 0 3px rgba(255, 77, 79, 0.2);
}

.cell-seat.cell-disabled::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: repeating-linear-gradient(
    45deg,
    transparent,
    transparent 5px,
    rgba(0, 0, 0, 0.1) 5px,
    rgba(0, 0, 0, 0.1) 10px
  );
  pointer-events: none;
}

.disabled-icon {
  position: absolute;
  top: 2px;
  right: 2px;
  font-size: 10px;
  line-height: 1;
}

.cell-pillar {
  background: #595959;
  color: #ffffff;
  border-color: #434343;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.cell-pillar:hover {
  background: #8c8c8c;
  box-shadow: 0 0 0 3px rgba(89, 89, 89, 0.2);
}

.cell-aisle {
  background: #fa8c16;
  color: #ffffff;
  border-color: #d46b08;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

.cell-aisle:hover {
  background: #ffa940;
  box-shadow: 0 0 0 3px rgba(250, 140, 22, 0.2);
}

.cell-door {
  background: #1890ff;
  color: #ffffff;
  border-color: #096dd9;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

.cell-door:hover {
  background: #40a9ff;
  box-shadow: 0 0 0 3px rgba(24, 144, 255, 0.2);
}

.cell-projector {
  background: #13c2c2;
  color: #ffffff;
  border-color: #08979c;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

.cell-projector:hover {
  background: #36cfc9;
  border-color: #13c2c2;
  box-shadow: 0 0 0 3px rgba(19, 194, 194, 0.2);
}

.cell-editing {
  border-color: #ff4d4f !important;
  box-shadow: 0 0 0 3px rgba(255, 77, 79, 0.2) !important;
  animation: pulse 1s infinite;
}

.cell-merged {
  display: none !important; /* Grid 布局中，被合并的单元格完全隐藏，由主单元格占据空间 */
}

.cell-merge-selected {
  border-color: #1890ff !important;
  box-shadow: 0 0 0 3px rgba(24, 144, 255, 0.3) !important;
  animation: pulse 1s infinite;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.8;
  }
}
</style>

