import { EntityManager } from 'typeorm';
import { Organization } from '../entities/organization.entity';
import { Room } from '../entities/room.entity';
import { Student } from '../entities/student.entity';
import { Bed } from '../entities/bed.entity';
import { RoomsService } from '../rooms/rooms.service';
import type { AiReviewSection } from './entities/ai-review.entity';
import { MAX_CAPACITY, normalizePhone } from './ai-review.shared';
import { resolveOrganizationId } from './ai-review.enrich';

export async function importStudents(
  section: AiReviewSection | undefined,
  manager: EntityManager,
): Promise<{ created: number; skipped: number; issues: string[] }> {
  let created = 0;
  let skipped = 0;
  const issues: string[] = [];
  if (!section || section.rows.length === 0) return { created, skipped, issues };
  const studentRepo = manager.getRepository(Student);
  const organizations = await manager.getRepository(Organization).find({
    where: { status: 'active' },
  });
  const seen = new Set<string>();

  for (const row of section.rows) {
    const name = row.name === undefined || row.name === null ? '' : String(row.name).trim();
    if (!name) {
      skipped += 1;
      issues.push('存在姓名为空的学生行');
      continue;
    }
    const phone = normalizePhone(row.phone);
    const studentNo =
      row.studentNo === undefined || row.studentNo === null
        ? ''
        : String(row.studentNo).trim();
    let organizationId = resolveOrganizationId(row.organization, organizations);
    if (organizationId === null) {
      const hostOrganization = organizations.find((org) => org.isHost)?.id ?? null;
      if (hostOrganization === null) {
        skipped += 1;
        issues.push(`学生「${name}」的所属机构无法识别且未配置本机构`);
        continue;
      }
      issues.push(
        `学生「${name}」的机构「${String(row.organization ?? '').trim()}」无法识别，已按本机构导入`,
      );
      organizationId = hostOrganization;
    }
    const phoneKey = phone ? `phone:${phone}` : '';
    const noKey = studentNo ? `no:${studentNo}` : '';
    if ((phoneKey && seen.has(phoneKey)) || (noKey && seen.has(noKey))) {
      skipped += 1;
      issues.push(`学生「${name}」与同一批次中的其他学生手机号/学号重复`);
      continue;
    }
    const existing =
      (phone
        ? await studentRepo.findOne({ where: { phone } })
        : null) ||
      (studentNo
        ? await studentRepo.findOne({ where: { studentNo } })
        : null);
    if (existing) {
      skipped += 1;
      issues.push(`学生「${name}」已存在（按手机号/学号匹配），未重复创建`);
      continue;
    }
    if (phoneKey) seen.add(phoneKey);
    if (noKey) seen.add(noKey);
    await studentRepo.save(
      studentRepo.create({
        name,
        phone: phone ?? undefined,
        studentNo: studentNo || undefined,
        gender: row.gender === undefined || row.gender === null ? undefined : String(row.gender).trim().slice(0, 10),
        organizationId,
        status: 'active',
      }),
    );
    created += 1;
  }
  return { created, skipped, issues };
}

export async function importRooms(
  section: AiReviewSection | undefined,
  manager: EntityManager,
): Promise<{ created: number; skipped: number; issues: string[] }> {
  let created = 0;
  let skipped = 0;
  const issues: string[] = [];
  if (!section || section.rows.length === 0) return { created, skipped, issues };
  const roomRepo = manager.getRepository(Room);
  const bedRepo = manager.getRepository(Bed);
  const seen = new Set<string>();

  for (const row of section.rows) {
    const roomNumber =
      row.roomNumber === undefined || row.roomNumber === null
        ? ''
        : String(row.roomNumber).trim();
    if (!roomNumber) {
      skipped += 1;
      issues.push('存在房间号为空的行');
      continue;
    }
    const parsed = RoomsService.parseRoomNumber(roomNumber);
    const capacity = normalizeCapacity(row.capacity, parsed.capacity ?? 4);
    if (capacity === null) {
      skipped += 1;
      issues.push(`宿舍「${roomNumber}」的容量无效`);
      continue;
    }
    if (seen.has(roomNumber)) {
      skipped += 1;
      issues.push(`宿舍「${roomNumber}」在同一批次中重复`);
      continue;
    }
    const existing = await roomRepo.findOne({ where: { roomNumber } });
    if (existing) {
      skipped += 1;
      issues.push(`宿舍「${roomNumber}」已存在，未重复创建`);
      continue;
    }
    seen.add(roomNumber);
    const room = await roomRepo.save(
      roomRepo.create({
        roomNumber,
        building:
          row.building === undefined || row.building === null
            ? parsed.building
            : String(row.building).trim().slice(0, 50),
        floor:
          row.floor === undefined || row.floor === null
            ? parsed.floor
            : (normalizeFloor(row.floor) ?? undefined),
        roomType:
          row.roomType === undefined || row.roomType === null
            ? parsed.roomType
            : String(row.roomType).trim().slice(0, 20),
        capacity,
        status: 'available',
      }),
    );
    const beds = Array.from({ length: capacity }, (_, index) =>
      bedRepo.create({ roomId: room.id, bedNumber: `${index + 1}号床` }),
    );
    if (beds.length > 0) await bedRepo.save(beds);
    created += 1;
  }
  return { created, skipped, issues };
}

export function normalizeCapacity(raw: unknown, fallback: number): number | null {
  let value: number;
  if (typeof raw === 'number') {
    value = raw;
  } else if (typeof raw === 'string' && /^\d+$/.test(raw.trim())) {
    value = Number(raw.trim());
  } else {
    return fallback > 0 ? fallback : null;
  }
  if (!Number.isFinite(value) || value < 1 || value > MAX_CAPACITY) return null;
  return Math.floor(value);
}

export function normalizeFloor(raw: unknown): number | null {
  if (typeof raw === 'number' && Number.isFinite(raw)) return Math.floor(raw);
  if (typeof raw === 'string' && /^\d+$/.test(raw.trim())) return Number(raw.trim());
  return null;
}

export function nextDay(date: string): string {
  const parsed = new Date(`${date}T00:00:00+08:00`);
  parsed.setDate(parsed.getDate() + 1);
  const year = parsed.getFullYear();
  const month = String(parsed.getMonth() + 1).padStart(2, '0');
  const day = String(parsed.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}
