<script lang="ts" setup>
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
import { Button, Input, Select, 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];
}>();

const loading = ref(false);
const cols = ref(10);
const rows = ref(8);
const selectedCellType = ref<ClassroomApi.ClassroomLayoutCell['type']>('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 lastDrawnCell = ref<{ col: number; row: number } | null>(null);
const hasChangesInDrawing = ref(false); // 标记当前绘制操作是否有变化

// 初始化布局数据
const cells = ref<ClassroomApi.ClassroomLayoutCell[]>([]);

// 历史记录（用于撤销）
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));
  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',
      });
    }
  }
};

// 从现有布局加载
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));
    } else {
      initLayout();
    }
  } else {
    initLayout();
  }
};

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

// 在左侧添加列
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',
    });
  }
  cols.value += 1;
  message.success('已在左侧添加一列');
};

// 在右侧添加列
const addColumnRight = () => {
  saveHistory();
  // 添加新列（列号为当前最大列号+1）
  for (let row = 0; row < rows.value; row++) {
    cells.value.push({
      col: cols.value,
      row,
      type: 'empty',
    });
  }
  cols.value += 1;
  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',
    });
  }
  rows.value += 1;
  message.success('已在上方添加一行');
};

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

// 获取单元格
const getCell = (col: number, row: number) => {
  return cells.value.find((c) => c.col === col && c.row === row);
};

// 获取下一个座位编号
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) return;

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

  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') {
    cell.name = type === 'pillar' ? '柱子' : type === 'aisle' ? '过道' : '门';
  } else if (type === 'seat') {
    // 如果是座位类型
    if (autoNumbering.value) {
      // 自动编号：只有从非座位类型变为座位类型时才分配新编号
      if (!wasSeat || !cell.number) {
        cell.number = getNextSeatNumber();
        cell.status = 1;
      }
      // 如果已经是座位类型，保持原有编号不变
    } else if (!cell.number) {
      // 手动输入模式，如果没有编号，设置为空
      cell.status = 1;
    }
  }
};

// 处理单元格设置（用于点击和拖动）
const applyCellType = (col: number, row: number, skipSameType = false) => {
  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 (lastDrawnCell.value && lastDrawnCell.value.col === col && lastDrawnCell.value.row === row) {
    return;
  }

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

// 点击单元格
const handleCellClick = (col: number, row: number) => {
  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) => {
  event.preventDefault();
  isDrawing.value = true;
  hasChangesInDrawing.value = false; // 重置变化标记
  lastDrawnCell.value = null; // 重置最后绘制的单元格
  // 拖动操作开始前保存历史记录
  saveHistory();
  applyCellType(col, row, false);
};

// 鼠标移动绘制
const handleCellMouseEnter = (col: number, row: number) => {
  if (isDrawing.value) {
    applyCellType(col, row, false);
  }
};

// 鼠标释放停止绘制
const handleCellMouseUp = () => {
  if (isDrawing.value) {
    isDrawing.value = false;
    lastDrawnCell.value = null;
    // 如果拖动过程中没有实际变化，撤销刚才保存的历史记录
    if (!hasChangesInDrawing.value && history.value.length > 0) {
      history.value.pop();
    }
    hasChangesInDrawing.value = false;
  }
};

// 全局鼠标事件处理（确保即使鼠标移出单元格也能停止绘制）
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; // 默认可用
  }
  editingCell.value = null;
  seatNumber.value = '';
};

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

// 获取类型名称
const getTypeName = (type: ClassroomApi.ClassroomLayoutCell['type']) => {
  const typeMap: Record<string, string> = {
    empty: '空白',
    seat: '座位',
    pillar: '柱子',
    aisle: '过道',
    door: '门',
  };
  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';
  
  const classes = ['cell', `cell-${cell.type}`];
  if (editingCell.value && editingCell.value.col === col && editingCell.value.row === row) {
    classes.push('cell-editing');
  }
  return classes.join(' ');
};

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

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

  loading.value = true;
  try {
    const layout: ClassroomApi.ClassroomLayout = {
      cols: cols.value,
      rows: rows.value,
      cells: cells.value,
    };
    
    await saveClassroomLayoutApi({
      id: props.classroomId,
      layout,
    });
    
    message.success('座位布局保存成功');
    emit('saved', layout);
  } catch (error) {
    console.error('保存座位布局失败:', error);
    message.error('保存座位布局失败');
  } finally {
    loading.value = false;
  }
};

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

<template>
  <div class="seat-layout-editor" :class="{ drawing: isDrawing }">
    <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.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>单元格即可设置类型。<strong>按住鼠标左键拖动</strong>可以连续绘制多个单元格。
          {{ autoNumbering ? '座位将自动编号。' : '选择"座位"时需要手动输入座位号。' }}
          <span v-if="isDrawing" class="drawing-indicator">正在绘制中...</span>
        </p>
      </div>

      <div class="layout-container">
        <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">
          <div
            v-for="row in rows"
            :key="`row-${row}`"
            class="layout-row"
          >
            <div class="header-cell header-row">{{ row }}</div>
            <div
              v-for="col in cols"
              :key="`cell-${col}-${row}`"
              :class="getCellClass(col - 1, row - 1)"
              @click="handleCellClick(col - 1, row - 1)"
              @mousedown="(e) => handleCellMouseDown(col - 1, row - 1, e)"
              @mouseenter="handleCellMouseEnter(col - 1, row - 1)"
            >
              {{ getCellText(col - 1, row - 1) }}
            </div>
          </div>
        </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;
}

.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;
}

.drawing-indicator {
  display: inline-block;
  margin-left: 12px;
  padding: 2px 8px;
  background: #ff4d4f;
  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: flex;
  flex-direction: column;
  gap: 4px;
}

.layout-row {
  display: flex;
  gap: 4px;
}

.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 {
  width: 45px;
  min-width: 45px;
  min-height: 45px;
  height: 45px;
  flex-shrink: 0;
  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;
}

.cell:hover {
  border-color: #40a9ff;
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
  transform: scale(1.05);
  z-index: 1;
}

.seat-layout-editor.drawing .cell {
  cursor: crosshair;
}

.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);
}

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

.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-editing {
  border-color: #ff4d4f !important;
  box-shadow: 0 0 0 3px rgba(255, 77, 79, 0.2) !important;
  animation: pulse 1s infinite;
}

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

