import * as ExcelJS from 'exceljs';

export interface OccupancyImportRow {
  roomNumber: string;
  building?: string;
  bedNumber?: string;
  lockerNumber?: string;
  name: string;
  gender?: string;
  ethnicity?: string;
  phone?: string;
  studentNo?: string;
  idNumber?: string;
  checkInDate: string;
  billingStartDate?: string;
  checkOutDate?: string;
  stayType?: string;
  emergencyContact?: string;
  emergencyPhone?: string;
  supervisor?: string;
  notes?: string;
}

export const OCCUPANCY_IMPORT_COLUMNS = [
  { header: '宿舍号', key: 'roomNumber', width: 12 },
  { header: '楼栋', key: 'building', width: 10 },
  { header: '床位号', key: 'bedNumber', width: 10 },
  { header: '柜子号', key: 'lockerNumber', width: 10 },
  { header: '姓名', key: 'name', width: 12 },
  { header: '性别', key: 'gender', width: 8 },
  { header: '民族', key: 'ethnicity', width: 10 },
  { header: '电话', key: 'phone', width: 15 },
  { header: '学号', key: 'studentNo', width: 15 },
  { header: '身份证号', key: 'idNumber', width: 22 },
  { header: '入住时间', key: 'checkInDate', width: 14 },
  { header: '计费起始日', key: 'billingStartDate', width: 14 },
  { header: '离宿时间', key: 'checkOutDate', width: 14 },
  { header: '入住类型', key: 'stayType', width: 10 },
  { header: '紧急联系人', key: 'emergencyContact', width: 15 },
  { header: '紧急联系人电话', key: 'emergencyPhone', width: 18 },
  { header: '负责人/班主任', key: 'supervisor', width: 15 },
  { header: '备注', key: 'notes', width: 20 },
] as const;

const HEADER_ALIASES: Record<keyof OccupancyImportRow, string[]> = {
  roomNumber: ['宿舍号', '房间号'],
  building: ['楼栋'],
  bedNumber: ['床位号'],
  lockerNumber: ['柜子号'],
  name: ['姓名', '学生姓名'],
  gender: ['性别'],
  ethnicity: ['民族'],
  phone: ['电话', '手机号'],
  studentNo: ['学号'],
  idNumber: ['身份证号', '身份证'],
  checkInDate: ['入住时间', '入住日期'],
  billingStartDate: ['计费起始日', '计费开始日'],
  checkOutDate: ['离宿时间', '退宿时间', '退宿日期'],
  stayType: ['入住类型', '住宿类型'],
  emergencyContact: ['紧急联系人'],
  emergencyPhone: ['紧急联系人电话', '紧急联系电话'],
  supervisor: ['负责人/班主任', '负责人', '班主任'],
  notes: ['备注'],
};

function cellText(cell: ExcelJS.Cell | undefined): string {
  if (!cell?.value) return '';
  if (typeof cell.value === 'object' && 'text' in cell.value) {
    return String(cell.value.text).trim();
  }
  return String(cell.value).trim();
}

function parseDate(cell: ExcelJS.Cell | undefined): string {
  const value = cell?.value;
  if (!value) return '';
  if (value instanceof Date) {
    const year = value.getFullYear();
    const month = String(value.getMonth() + 1).padStart(2, '0');
    const day = String(value.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
  }
  const text = cellText(cell);
  const matched = text.match(/(\d{4})[\/\-.](\d{1,2})[\/\-.](\d{1,2})/);
  if (!matched) return text;
  return `${matched[1]}-${matched[2].padStart(2, '0')}-${matched[3].padStart(2, '0')}`;
}

function normalizeStayType(value: string): string | undefined {
  if (!value) return undefined;
  if (value === '长租' || value.toLowerCase() === 'long') return 'long';
  if (value === '短租' || value.toLowerCase() === 'short') return 'short';
  return value;
}

export function parseOccupancyImportWorksheet(ws: ExcelJS.Worksheet): OccupancyImportRow[] {
  const headerIndexes = new Map<string, number>();
  ws.getRow(1).eachCell((cell, columnNumber) => {
    const header = cellText(cell).replace(/\s+/g, '');
    if (header) headerIndexes.set(header, columnNumber);
  });

  const columnFor = (key: keyof OccupancyImportRow): number | undefined => {
    for (const alias of HEADER_ALIASES[key]) {
      const index = headerIndexes.get(alias.replace(/\s+/g, ''));
      if (index) return index;
    }
    return undefined;
  };
  const getCell = (row: ExcelJS.Row, key: keyof OccupancyImportRow) => {
    const index = columnFor(key);
    return index ? row.getCell(index) : undefined;
  };

  const rows: OccupancyImportRow[] = [];
  let lastRoomNumber = '';
  ws.eachRow((row, rowNumber) => {
    if (rowNumber === 1) return;
    const roomNumber = cellText(getCell(row, 'roomNumber'));
    if (roomNumber) lastRoomNumber = roomNumber;
    const name = cellText(getCell(row, 'name'));
    if (!name) return;

    rows.push({
      roomNumber: lastRoomNumber,
      building: cellText(getCell(row, 'building')) || undefined,
      bedNumber: cellText(getCell(row, 'bedNumber')) || undefined,
      lockerNumber: cellText(getCell(row, 'lockerNumber')) || undefined,
      name,
      gender: cellText(getCell(row, 'gender')) || undefined,
      ethnicity: cellText(getCell(row, 'ethnicity')) || undefined,
      phone: cellText(getCell(row, 'phone')) || undefined,
      studentNo: cellText(getCell(row, 'studentNo')) || undefined,
      idNumber: cellText(getCell(row, 'idNumber')) || undefined,
      checkInDate: parseDate(getCell(row, 'checkInDate')),
      billingStartDate: parseDate(getCell(row, 'billingStartDate')) || undefined,
      checkOutDate: parseDate(getCell(row, 'checkOutDate')) || undefined,
      stayType: normalizeStayType(cellText(getCell(row, 'stayType'))),
      emergencyContact: cellText(getCell(row, 'emergencyContact')) || undefined,
      emergencyPhone: cellText(getCell(row, 'emergencyPhone')) || undefined,
      supervisor: cellText(getCell(row, 'supervisor')) || undefined,
      notes: cellText(getCell(row, 'notes')) || undefined,
    });
  });
  return rows;
}

export function createOccupancyImportTemplateWorkbook(): ExcelJS.Workbook {
  const workbook = new ExcelJS.Workbook();
  const ws = workbook.addWorksheet('入住名单导入模板');
  ws.columns = [...OCCUPANCY_IMPORT_COLUMNS];
  ws.getRow(1).font = { bold: true };
  ws.getRow(1).fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFE0E0E0' } };
  ws.views = [{ state: 'frozen', ySplit: 1 }];
  ws.autoFilter = {
    from: 'A1',
    to: `${ws.getColumn(OCCUPANCY_IMPORT_COLUMNS.length).letter}1`,
  };

  ws.addRow({
    roomNumber: '4-102',
    building: '4号楼',
    bedNumber: '1号床',
    lockerNumber: 'A01',
    name: '张三',
    gender: '男',
    ethnicity: '汉族',
    phone: '13800138000',
    studentNo: '2024001',
    idNumber: '11010120060101001X',
    checkInDate: '2026-04-21',
    billingStartDate: '2026-04-21',
    checkOutDate: '',
    stayType: '短租',
    emergencyContact: '张父',
    emergencyPhone: '13900000000',
    supervisor: '',
    notes: '',
  });
  ws.addRow({
    roomNumber: '4-102',
    building: '4号楼',
    bedNumber: '2号床',
    lockerNumber: 'A02',
    name: '李四',
    gender: '男',
    ethnicity: '汉族',
    phone: '13800138001',
    studentNo: '2024002',
    idNumber: '11010120060202002X',
    checkInDate: '2026-04-21',
    billingStartDate: '2026-04-22',
    checkOutDate: '',
    stayType: '长租',
    emergencyContact: '',
    emergencyPhone: '',
    supervisor: '王老师',
    notes: '示例数据，导入前请删除',
  });

  const stayTypeColumnNumber = ws.getColumn('stayType').number;
  for (let row = 2; row <= 1000; row++) {
    ws.getCell(row, stayTypeColumnNumber).dataValidation = {
      type: 'list',
      allowBlank: true,
      formulae: ['"短租,长租"'],
    };
  }

  const helpWs = workbook.addWorksheet('使用说明');
  helpWs.getColumn(1).width = 90;
  const instructions = [
    '【入住名单导入说明】',
    '1. 宿舍号、姓名、手机号、入住时间为必填项；床位号建议填写，柜子号可选。',
    '2. 填写床位号或柜子号后，系统会在对应宿舍中匹配；不存在时自动创建，已被占用时该行导入失败。',
    '3. 宿舍不存在时会自动创建；宿舍号可智能解析楼栋、楼层和房间类型，楼栋列可用于补充楼栋名称。',
    '4. 同一宿舍号的连续多行可以合并或留空，系统会继承上一行宿舍号。',
    '5. 入住类型可填“短租”或“长租”；计费起始日不填时默认等于入住时间。',
    '6. 学号和身份证号为两个独立字段，请分别填写。',
    '7. 系统按手机号关联已有学生，入住记录的所属机构自动取学生档案；未找到时会新建学生。',
    '8. 已有在住记录的学生会自动跳过，不会重复入住。',
    '9. 填写离宿时间的记录会作为历史入住导入，床位和柜子不会被标记为占用。',
    '10. 押金不在表格中逐行填写；请在上传前使用页面上的“导入时自动收押金”和金额设置，历史入住不会自动收取，已有已缴押金不会重复创建。',
    '11. 模板中的两行示例数据仅用于说明，正式导入前请删除或替换。',
  ];
  instructions.forEach((instruction) => helpWs.addRow([instruction]));
  helpWs.getRow(1).font = { bold: true, size: 14 };
  return workbook;
}
