import * as ExcelJS from 'exceljs';

export interface StudentImportRow {
  name: string;
  studentNo?: string;
  phone?: string;
  idNumber?: string;
  gender?: string;
  ethnicity?: string;
  emergencyContact?: string;
  emergencyPhone?: string;
  organization?: string;
  supervisor?: string;
  organizationId?: number;
  targetCollege?: string;
  targetMajor?: string;
  collegeSchool?: string;
  collegeMajor?: string;
  subjectDirection?: string;
  grade?: string;
  profileDate?: string;
  notes?: string;
  cultureFinalScore?: number;
  professionalFinalScore?: number;
  admissionStatus?: string;
  admittedCollege?: string;
  admittedMajor?: string;
}

export interface StudentEnrollmentImportRow {
  phone: string;
  name?: string;
  courseCategory: string;
  classType: string;
  className?: string;
  headTeacher?: string;
  subjectTeacher?: string;
  startDate?: string;
  endDate?: string;
  status?: string;
}

export interface ExamScoreImportRow {
  phone: string;
  name?: string;
  examType: string;
  examName?: string;
  subject: string;
  score?: number;
  classAvg?: number;
  rank?: number;
  examDate?: string;
  enrollmentName?: string;
}

export interface LearningRecordImportRow {
  phone: string;
  name?: string;
  recordDate: string;
  recordType: string;
  content: string;
  followUpMethod?: string;
  nextStep?: string;
}

export interface StudentWorkbookImport {
  students: StudentImportRow[];
  enrollments: StudentEnrollmentImportRow[];
  examScores: ExamScoreImportRow[];
  learningRecords: LearningRecordImportRow[];
}

type ColumnDef<T> = {
  header: string;
  key: keyof T;
  width: number;
  aliases?: string[];
  kind?: 'text' | 'date' | 'number' | 'integer';
};

export const STUDENT_IMPORT_COLUMNS: ColumnDef<StudentImportRow>[] = [
  { header: '手机号*', key: 'phone', width: 18, aliases: ['手机号', '电话'] },
  { header: '姓名*', key: 'name', width: 15, aliases: ['姓名'] },
  { header: '学号', key: 'studentNo', width: 15 },
  { header: '性别', key: 'gender', width: 8 },
  { header: '身份证号', key: 'idNumber', width: 22, aliases: ['身份证', '学号/身份证'] },
  { header: '民族', key: 'ethnicity', width: 10 },
  { header: '紧急联系人', key: 'emergencyContact', width: 15 },
  { header: '紧急联系人电话', key: 'emergencyPhone', width: 18 },
  { header: '所属机构', key: 'organization', width: 18, aliases: ['所属机构名称'] },
  { header: '负责人', key: 'supervisor', width: 15, aliases: ['负责人/班主任'] },
  { header: '目标院校', key: 'targetCollege', width: 18 },
  { header: '目标专业', key: 'targetMajor', width: 22 },
  { header: '大专院校', key: 'collegeSchool', width: 18 },
  { header: '大专专业', key: 'collegeMajor', width: 22 },
  { header: '选科方向', key: 'subjectDirection', width: 14 },
  { header: '年级', key: 'grade', width: 10 },
  { header: '建档日期', key: 'profileDate', width: 14, kind: 'date' },
  { header: '档案备注', key: 'notes', width: 28 },
  { header: '文化课最终分', key: 'cultureFinalScore', width: 14, kind: 'number' },
  { header: '专业课最终分', key: 'professionalFinalScore', width: 14, kind: 'number' },
  { header: '录取状态', key: 'admissionStatus', width: 14 },
  { header: '录取院校', key: 'admittedCollege', width: 18 },
  { header: '录取专业', key: 'admittedMajor', width: 22 },
];

export const STUDENT_EXPORT_COLUMNS = [
  ...STUDENT_IMPORT_COLUMNS,
];

const ENROLLMENT_IMPORT_COLUMNS: ColumnDef<StudentEnrollmentImportRow>[] = [
  { header: '手机号*', key: 'phone', width: 18, aliases: ['手机号', '电话'] },
  { header: '姓名', key: 'name', width: 15 },
  { header: '课程类别*', key: 'courseCategory', width: 14, aliases: ['课程类别'] },
  { header: '班型*', key: 'classType', width: 14, aliases: ['班型'] },
  { header: '班级名称', key: 'className', width: 20 },
  { header: '班主任', key: 'headTeacher', width: 15 },
  { header: '任课教师', key: 'subjectTeacher', width: 15 },
  { header: '开始日期', key: 'startDate', width: 14, kind: 'date' },
  { header: '结束日期', key: 'endDate', width: 14, kind: 'date' },
  { header: '状态', key: 'status', width: 12 },
];

const EXAM_SCORE_IMPORT_COLUMNS: ColumnDef<ExamScoreImportRow>[] = [
  { header: '手机号*', key: 'phone', width: 18, aliases: ['手机号', '电话'] },
  { header: '姓名', key: 'name', width: 15 },
  { header: '考试类型*', key: 'examType', width: 14, aliases: ['考试类型'] },
  { header: '考试名称', key: 'examName', width: 20 },
  { header: '科目*', key: 'subject', width: 14, aliases: ['科目'] },
  { header: '成绩*', key: 'score', width: 12, aliases: ['成绩'], kind: 'number' },
  { header: '班级均分', key: 'classAvg', width: 12, kind: 'number' },
  { header: '排名', key: 'rank', width: 10, kind: 'integer' },
  { header: '考试日期', key: 'examDate', width: 14, kind: 'date' },
  { header: '关联报读（班级名）', key: 'enrollmentName', width: 22, aliases: ['关联报读(班级名)'] },
];

const LEARNING_RECORD_IMPORT_COLUMNS: ColumnDef<LearningRecordImportRow>[] = [
  { header: '手机号*', key: 'phone', width: 18, aliases: ['手机号', '电话'] },
  { header: '姓名', key: 'name', width: 15 },
  { header: '记录日期*', key: 'recordDate', width: 14, aliases: ['记录日期'], kind: 'date' },
  { header: '记录类型*', key: 'recordType', width: 14, aliases: ['记录类型'] },
  { header: '内容*', key: 'content', width: 36, aliases: ['内容'] },
  { header: '跟进方式', key: 'followUpMethod', width: 14 },
  { header: '下一步计划', key: 'nextStep', width: 28 },
];

function normalizeHeader(header: string): string {
  return header.trim().replace(/\*+$/u, '').trim();
}

function getCellPrimitiveValue(cell: ExcelJS.Cell): unknown {
  const value = cell.value;
  if (value === null || value === undefined) return undefined;
  if (value instanceof Date) return value;
  if (typeof value === 'object') {
    if ('result' in value) return value.result;
    if ('text' in value) return value.text;
    if ('richText' in value && Array.isArray(value.richText)) {
      return value.richText.map((part) => part.text).join('');
    }
  }
  return value;
}

function cellToText(cell: ExcelJS.Cell): string {
  const value = getCellPrimitiveValue(cell);
  if (value === null || value === undefined) return '';
  if (value instanceof Date) return formatDate(value);
  return String(value).trim();
}

function formatDate(date: Date): string {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

function excelSerialToDate(serial: number): string | undefined {
  if (!Number.isFinite(serial) || serial < 1) return undefined;
  const epoch = Date.UTC(1899, 11, 30);
  return formatDate(new Date(epoch + serial * 24 * 60 * 60 * 1000));
}

function parseDateText(cell: ExcelJS.Cell): string | undefined {
  const value = getCellPrimitiveValue(cell);
  if (value instanceof Date) return formatDate(value);
  if (typeof value === 'number') return excelSerialToDate(value);
  const text = value === null || value === undefined ? '' : String(value).trim();
  if (!text) return undefined;
  const normalized = text.replace(/[/.]/g, '-');
  const match = normalized.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/u);
  if (!match) return text;
  return `${match[1]}-${match[2].padStart(2, '0')}-${match[3].padStart(2, '0')}`;
}

function parseNumber(cell: ExcelJS.Cell): number | undefined {
  const text = cellToText(cell).replace(/,/g, '');
  if (!text) return undefined;
  const value = Number(text);
  return Number.isFinite(value) ? value : undefined;
}

function buildHeaderMap<T extends object>(ws: ExcelJS.Worksheet, columns: ColumnDef<T>[]) {
  const columnByHeader = new Map<string, ColumnDef<T>>();
  for (const column of columns) {
    columnByHeader.set(normalizeHeader(column.header), column);
    for (const alias of column.aliases || []) {
      columnByHeader.set(normalizeHeader(alias), column);
    }
  }

  const headerIndex = new Map<number, ColumnDef<T>>();
  ws.getRow(1).eachCell((cell, colNumber) => {
    const column = columnByHeader.get(normalizeHeader(cellToText(cell)));
    if (column) headerIndex.set(colNumber, column);
  });
  return headerIndex;
}

function parseWorksheetRows<T extends object>(
  ws: ExcelJS.Worksheet | undefined,
  columns: ColumnDef<T>[],
): T[] {
  if (!ws) return [];
  const headerIndex = buildHeaderMap(ws, columns);
  const rows: T[] = [];

  ws.eachRow((row, idx) => {
    if (idx === 1) return;
    const parsed: Partial<Record<keyof T, string | number>> = {};
    headerIndex.forEach((column, colNumber) => {
      const cell = row.getCell(colNumber);
      const value =
        column.kind === 'date'
          ? parseDateText(cell)
          : column.kind === 'number' || column.kind === 'integer'
            ? parseNumber(cell)
            : cellToText(cell);
      if (value !== undefined && value !== '') {
        parsed[column.key] = column.kind === 'integer' && typeof value === 'number'
          ? Math.trunc(value)
          : value;
      }
    });

    if (Object.keys(parsed).length > 0) rows.push(parsed as T);
  });

  return rows;
}

function findWorksheet(workbook: ExcelJS.Workbook, names: string[], fallbackIndex?: number) {
  for (const name of names) {
    const sheet = workbook.getWorksheet(name);
    if (sheet) return sheet;
  }
  return fallbackIndex === undefined ? undefined : workbook.worksheets[fallbackIndex];
}

export function parseStudentImportWorkbook(workbook: ExcelJS.Workbook): StudentWorkbookImport {
  return {
    students: parseWorksheetRows(
      findWorksheet(workbook, ['学生基础+档案+录取', '学生导入模板', '学生名单'], 0),
      STUDENT_IMPORT_COLUMNS,
    ).map((row) => ({ ...row, name: row.name || '', phone: row.phone || '' })),
    enrollments: parseWorksheetRows(
      findWorksheet(workbook, ['报读班型']),
      ENROLLMENT_IMPORT_COLUMNS,
    ),
    examScores: parseWorksheetRows(
      findWorksheet(workbook, ['考试成绩']),
      EXAM_SCORE_IMPORT_COLUMNS,
    ),
    learningRecords: parseWorksheetRows(
      findWorksheet(workbook, ['课堂回访']),
      LEARNING_RECORD_IMPORT_COLUMNS,
    ),
  };
}

function applyHeaderStyle(ws: ExcelJS.Worksheet) {
  ws.getRow(1).font = { bold: true };
  ws.getRow(1).fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFE0E0E0' } };
}

function setupWorksheet<T>(workbook: ExcelJS.Workbook, name: string, columns: ColumnDef<T>[]) {
  const ws = workbook.addWorksheet(name);
  ws.columns = columns.map(({ header, key, width }) => ({ header, key: String(key), width }));
  applyHeaderStyle(ws);
  return ws;
}

export function createStudentImportTemplateWorkbook(): ExcelJS.Workbook {
  const workbook = new ExcelJS.Workbook();
  setupWorksheet(workbook, '学生基础+档案+录取', STUDENT_IMPORT_COLUMNS).addRow({
    phone: '13800138000',
    name: '张三',
    studentNo: '2024001',
    gender: '男',
    idNumber: '11010120060101001X',
    ethnicity: '汉族',
    emergencyContact: '张父',
    emergencyPhone: '13900139000',
    organization: '北京校区',
    supervisor: '李老师',
    targetCollege: '北京大学',
    targetMajor: '计算机科学与技术',
    collegeSchool: '北京职业技术学院',
    collegeMajor: '软件技术',
    subjectDirection: '物化生',
    grade: '高三',
    profileDate: '2024-09-01',
    notes: '学习态度积极，目标明确',
    cultureFinalScore: 620,
    professionalFinalScore: 580,
    admissionStatus: 'pending',
    admittedCollege: '',
    admittedMajor: '',
  });
  setupWorksheet(workbook, '报读班型', ENROLLMENT_IMPORT_COLUMNS);
  setupWorksheet(workbook, '考试成绩', EXAM_SCORE_IMPORT_COLUMNS);
  setupWorksheet(workbook, '课堂回访', LEARNING_RECORD_IMPORT_COLUMNS);
  return workbook;
}
