import * as XLSX from 'xlsx'

import type { ChildProfile, ClassProfile } from '@renderer/types/app'

export const CHILD_PROFILES_STORAGE_KEY = 'growth-report:student-profiles'
const LEGACY_CHILD_PROFILES_STORAGE_KEY = 'growth-report:child-profiles'

type SpreadsheetRow = Record<string, unknown>

function asText(value: unknown): string {
  if (value === null || value === undefined) {
    return ''
  }

  if (value instanceof Date) {
    return value.toISOString().slice(0, 10)
  }

  return String(value).trim()
}

function splitList(value: unknown): string[] {
  return asText(value)
    .split(/[、,，]/)
    .map((item) => item.trim())
    .filter(Boolean)
}

function createChildId(profile: Omit<ChildProfile, 'id'>, index: number): string {
  return [profile.classId, profile.name, profile.englishName, profile.birthday, index]
    .filter(Boolean)
    .join('-')
}

function mapRowToChild(
  row: SpreadsheetRow,
  index: number,
  importedAt: string,
  selectedClass: ClassProfile
): ChildProfile | null {
  const profile = {
    classId: selectedClass.id,
    className: selectedClass.name,
    name: asText(row['姓名']),
    englishName: asText(row['英文名']),
    gender: asText(row['性别']),
    birthday: asText(row['生日']),
    zodiac: asText(row['属相']),
    friends: splitList(row['我的好朋友']),
    hobbies: splitList(row['我的爱好']),
    favoriteGames: splitList(row['喜欢的游戏']),
    favoriteFoods: splitList(row['喜欢吃的食物']),
    traits: asText(row['表现特征']),
    comment: '',
    commentGeneratedAt: '',
    importedAt
  }

  if (!profile.name && !profile.englishName) {
    return null
  }

  return {
    ...profile,
    id: createChildId(profile, index)
  }
}

export function loadProfiles(): ChildProfile[] {
  const rawProfiles =
    window.localStorage.getItem(CHILD_PROFILES_STORAGE_KEY) ??
    window.localStorage.getItem(LEGACY_CHILD_PROFILES_STORAGE_KEY)

  if (!rawProfiles) {
    return []
  }

  try {
    const profiles = JSON.parse(rawProfiles)
    return Array.isArray(profiles)
      ? profiles
          .map(normalizeProfile)
          .filter((profile): profile is ChildProfile => profile !== null)
      : []
  } catch {
    return []
  }
}

function normalizeProfile(profile: Partial<ChildProfile>): ChildProfile | null {
  if (!profile.id) {
    return null
  }

  return {
    id: profile.id,
    classId: profile.classId ?? '',
    className: profile.className ?? '',
    name: profile.name ?? '',
    englishName: profile.englishName ?? '',
    gender: profile.gender ?? '',
    birthday: profile.birthday ?? '',
    zodiac: profile.zodiac ?? '',
    friends: Array.isArray(profile.friends) ? profile.friends : [],
    hobbies: Array.isArray(profile.hobbies) ? profile.hobbies : [],
    favoriteGames: Array.isArray(profile.favoriteGames) ? profile.favoriteGames : [],
    favoriteFoods: Array.isArray(profile.favoriteFoods) ? profile.favoriteFoods : [],
    traits: profile.traits ?? '',
    comment: profile.comment ?? '',
    commentGeneratedAt: profile.commentGeneratedAt ?? '',
    importedAt: profile.importedAt ?? ''
  }
}

export function loadLocalProfilesForMigration(): ChildProfile[] {
  return loadProfiles()
}

export function clearLocalProfilesForMigration(): void {
  window.localStorage.removeItem(CHILD_PROFILES_STORAGE_KEY)
  window.localStorage.removeItem(LEGACY_CHILD_PROFILES_STORAGE_KEY)
}

export function saveProfiles(profiles: ChildProfile[]): void {
  window.localStorage.setItem(CHILD_PROFILES_STORAGE_KEY, JSON.stringify(profiles))
}

export async function readChildProfilesFromSpreadsheet(
  file: File,
  selectedClass: ClassProfile
): Promise<ChildProfile[]> {
  const buffer = await file.arrayBuffer()
  const workbook = XLSX.read(buffer, { cellDates: false })
  const worksheet = workbook.Sheets[workbook.SheetNames[0]]
  const importedAt = new Date().toLocaleString('zh-CN', { hour12: false })
  const rows = XLSX.utils.sheet_to_json<SpreadsheetRow>(worksheet, { defval: '' })

  return rows
    .map((row, index) => mapRowToChild(row, index, importedAt, selectedClass))
    .filter((profile): profile is ChildProfile => profile !== null)
}

export function replaceProfilesForClass(
  profiles: ChildProfile[],
  selectedClass: ClassProfile,
  nextProfiles: ChildProfile[]
): ChildProfile[] {
  const otherClassProfiles = profiles.filter((profile) => profile.classId !== selectedClass.id)
  return [...otherClassProfiles, ...nextProfiles]
}

export function deleteProfilesForClass(profiles: ChildProfile[], classId: string): ChildProfile[] {
  return profiles.filter((profile) => profile.classId !== classId)
}
