import {
  appendEmployeeBankUpdatePayload,
  createEmployeeBankFormFields,
  getEmployeeBankSearchFields,
  mapEmployeeBankFormFields
} from './employeeBankFields.js'

export const DEFAULT_STATUS_TABS = ['全部员工', '在职', '试用中', '停用']
export const FALLBACK_ROLE_OPTIONS = [
  {
    id: 'manager',
    code: 'manager',
    label: '管理员',
    desc: '可以维护员工档案、组织结构和角色权限。'
  },
  {
    id: 'finance',
    code: 'finance',
    label: '财务人员',
    desc: '可以处理复核、查看财务知识与风险校验结果。'
  },
  {
    id: 'approver',
    code: 'approver',
    label: '审批负责人',
    desc: '可以处理单据中心中的待审单据。'
  },
  {
    id: 'executive',
    code: 'executive',
    label: '高级财务人员',
    desc: '可以查看跨部门预算、经营看板与关键财务审批结果。'
  },
  {
    id: 'budget_monitor',
    code: 'budget_monitor',
    label: '预算监控员',
    desc: '可以查看本部门预算执行、预警和占用情况。'
  },
  {
    id: 'user',
    code: 'user',
    label: '使用者',
    desc: '可以发起费用申请、报销、查看个人单据和使用 AI 助手。'
  }
]

export function createEmployeeForm() {
  return {
    name: '',
    employeeNo: '',
    gender: '',
    age: '',
    birthDate: '',
    phone: '',
    email: '',
    joinDate: '',
    location: '',
    position: '',
    grade: '',
    department: '',
    organizationUnitCode: '',
    manager: '',
    managerEmployeeNo: '',
    financeOwner: '',
    costCenter: '',
    ...createEmployeeBankFormFields(),
    roleCodes: [],
    password: ''
  }
}

export function isPlaceholderManagerName(name) {
  const normalized = normalizeText(name)
  return !normalized || normalized === 'CEO' || normalized === '无'
}

export function resolveManagerEmployeeNo(employee, roster = []) {
  const fromApi = normalizeText(employee?.managerEmployeeNo)
  if (fromApi) {
    return fromApi
  }

  const managerName = normalizeText(employee?.manager)
  if (isPlaceholderManagerName(managerName)) {
    return ''
  }

  const matches = roster.filter((item) => normalizeText(item.name) === managerName)
  if (matches.length === 1) {
    return matches[0].employeeNo
  }

  return ''
}

export function enrichEmployeeRecord(employee, roster = []) {
  if (!employee) {
    return employee
  }

  const managerEmployeeNo = resolveManagerEmployeeNo(employee, roster)
  if (!managerEmployeeNo || managerEmployeeNo === employee.managerEmployeeNo) {
    return employee
  }

  return {
    ...employee,
    managerEmployeeNo
  }
}

export function mergeEmployeeRecords(listItem, detailItem, roster = []) {
  if (!listItem && !detailItem) {
    return null
  }

  if (!listItem) {
    return enrichEmployeeRecord(detailItem, roster)
  }

  if (!detailItem) {
    return enrichEmployeeRecord(listItem, roster)
  }

  const managerEmployeeNo =
    normalizeText(detailItem.managerEmployeeNo) ||
    normalizeText(listItem.managerEmployeeNo) ||
    resolveManagerEmployeeNo(detailItem, roster) ||
    resolveManagerEmployeeNo(listItem, roster)

  const history =
    Array.isArray(detailItem.history) && detailItem.history.length
      ? detailItem.history
      : listItem.history || []

  const permissions =
    Array.isArray(detailItem.permissions) && detailItem.permissions.length
      ? detailItem.permissions
      : listItem.permissions || []

  return enrichEmployeeRecord(
    {
      ...listItem,
      ...detailItem,
      manager: detailItem.manager || listItem.manager,
      managerEmployeeNo: managerEmployeeNo || null,
      history,
      permissions,
      roleCodes: detailItem.roleCodes?.length ? detailItem.roleCodes : listItem.roleCodes,
      roles: detailItem.roles?.length ? detailItem.roles : listItem.roles,
      organization: detailItem.organization || listItem.organization,
      department: detailItem.department || listItem.department
    },
    roster
  )
}

export function buildEmployeeForm(employee, roster = []) {
  if (!employee) {
    return createEmployeeForm()
  }

  const birthDate = employee.birthDate || ''
  const managerName = employee.manager || ''
  const managerEmployeeNo = resolveManagerEmployeeNo(employee, roster)

  return {
    name: employee.name || '',
    employeeNo: employee.employeeNo || '',
    gender: employee.gender || '',
    age:
      employee.age !== null && employee.age !== undefined && employee.age !== ''
        ? String(employee.age)
        : calculateAgeFromDate(birthDate),
    birthDate,
    phone: employee.phone || '',
    email: employee.email || '',
    joinDate: employee.joinDate || '',
    location: employee.location || '',
    position: employee.position || '',
    grade: employee.grade || '',
    department: resolveOrganizationUnitName(employee),
    organizationUnitCode: resolveOrganizationUnitCode(employee),
    manager: managerName,
    managerEmployeeNo,
    financeOwner: employee.financeOwner || '',
    costCenter: employee.costCenter || '',
    ...mapEmployeeBankFormFields(employee),
    roleCodes: [...(employee.roleCodes || [])],
    password: ''
  }
}

export function normalizeText(value) {
  return String(value || '').trim()
}

export function normalizeNullableText(value) {
  const text = normalizeText(value)
  return text || null
}

export function isValidEmail(value) {
  const normalized = normalizeText(value)
  if (!normalized) {
    return false
  }

  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/u.test(normalized)
}

export function isValidIsoDate(value) {
  const normalized = normalizeText(value)
  if (!normalized) {
    return false
  }

  if (!/^\d{4}-\d{2}-\d{2}$/u.test(normalized)) {
    return false
  }

  const [yearText, monthText, dayText] = normalized.split('-')
  const year = Number.parseInt(yearText, 10)
  const month = Number.parseInt(monthText, 10)
  const day = Number.parseInt(dayText, 10)

  if ([year, month, day].some((item) => Number.isNaN(item))) {
    return false
  }

  const parsed = new Date(year, month - 1, day)
  if (Number.isNaN(parsed.getTime())) {
    return false
  }

  return (
    parsed.getFullYear() === year &&
    parsed.getMonth() === month - 1 &&
    parsed.getDate() === day
  )
}

export function sameValues(left, right) {
  if (left.length !== right.length) {
    return false
  }

  return left.every((value, index) => value === right[index])
}

export function formatEmployeeHistoryTime(value) {
  const raw = normalizeText(value)
  if (!raw) {
    return ''
  }

  const chineseMatched = raw.match(
    /^(\d{4})年(\d{1,2})月(\d{1,2})日(\d{1,2})时(\d{1,2})分(?:\d{1,2}秒)?$/
  )
  if (chineseMatched) {
    const [, year, month, day, hour, minute] = chineseMatched
    return `${year}-${padDatePart(month)}-${padDatePart(day)} ${padDatePart(hour)}:${padDatePart(minute)}`
  }

  const isoMatched = raw.match(/^(\d{4})-(\d{1,2})-(\d{1,2})(?:[ T](\d{1,2}):(\d{1,2}))?/)
  if (isoMatched) {
    const [, year, month, day, hour = '0', minute = '0'] = isoMatched
    return `${year}-${padDatePart(month)}-${padDatePart(day)} ${padDatePart(hour)}:${padDatePart(minute)}`
  }

  return raw.replace(/(\d{1,2}分)\d{1,2}秒$/, '$1')
}

export function resolveOrganizationUnitCode(employee) {
  return normalizeText(employee?.organization?.code)
}

export function resolveOrganizationUnitName(employee) {
  return normalizeText(employee?.department) || normalizeText(employee?.organization?.name)
}

export function captureEmployeeDetailSnapshot(form) {
  return {
    roleCodes: [...(form.roleCodes || [])].sort(),
    organizationUnitCode: normalizeText(form.organizationUnitCode) || ''
  }
}

export function resolveOrganizationOptions(metaOrganizations) {
  if (!Array.isArray(metaOrganizations) || !metaOrganizations.length) {
    return []
  }

  return metaOrganizations
    .map((item) => ({
      id: item.id,
      code: item.code,
      name: item.name,
      unitType: item.unitType,
      label: `${item.name}（${item.code}）`
    }))
    .sort((a, b) => a.name.localeCompare(b.name, 'zh-CN'))
}

export function calculateAgeFromDate(dateString) {
  if (!dateString) {
    return ''
  }

  const birthDate = new Date(`${dateString}T00:00:00`)
  if (Number.isNaN(birthDate.getTime())) {
    return ''
  }

  const today = new Date()
  let age = today.getFullYear() - birthDate.getFullYear()
  const hasBirthdayPassed =
    today.getMonth() > birthDate.getMonth() ||
    (today.getMonth() === birthDate.getMonth() && today.getDate() >= birthDate.getDate())

  if (!hasBirthdayPassed) {
    age -= 1
  }

  return age >= 0 ? String(age) : ''
}

export function calculateBirthDateFromAge(ageValue, existingBirthDate = '') {
  const age = Number.parseInt(String(ageValue ?? '').trim(), 10)
  if (Number.isNaN(age) || age < 0 || age > 120) {
    return existingBirthDate || ''
  }

  const today = new Date()
  let month = '01'
  let day = '01'

  if (existingBirthDate && isValidIsoDate(existingBirthDate)) {
    const [, monthText, dayText] = existingBirthDate.split('-')
    month = monthText
    day = dayText
  }

  let birthYear = today.getFullYear() - age
  let candidate = `${birthYear}-${month}-${day}`

  if (Number(calculateAgeFromDate(candidate)) > age) {
    birthYear -= 1
    candidate = `${birthYear}-${month}-${day}`
  }

  return candidate
}

export function matchKeyword(employee, keyword) {
  if (!keyword) {
    return true
  }

  const fields = [
    employee.name,
    employee.employeeNo,
    employee.department,
    employee.position,
    employee.email,
    employee.manager,
    employee.financeOwner,
    ...getEmployeeBankSearchFields(employee),
    employee.syncState
  ]

  const roles = Array.isArray(employee.roles) ? employee.roles : []
  const haystack = [...fields, ...roles]
    .map((val) => String(val || '').trim())
    .filter(Boolean)
    .join(' ')
    .toLowerCase()

  return haystack.includes(keyword)
}

export function uniqueSorted(values) {
  return [...new Set(values.filter(Boolean))].sort((left, right) => {
    return String(left).localeCompare(String(right), 'zh-CN')
  })
}

export function resolveRoleOptions(metaRoles, employees) {
  const options = Array.isArray(metaRoles) && metaRoles.length ? metaRoles : FALLBACK_ROLE_OPTIONS
  const existingLabels = new Set(options.map((item) => item.label))
  const unknownRoles = uniqueSorted(employees.flatMap((item) => item.roles || [])).filter(
    (label) => !existingLabels.has(label)
  )

  return [
    ...options,
    ...unknownRoles.map((label) => ({
      id: label,
      code: label,
      label,
      desc: '该角色来自当前员工数据。'
    }))
  ]
}

export function buildStatusTabs(employees) {
  return DEFAULT_STATUS_TABS.map((label) => ({
    label,
    count:
      label === '全部员工'
        ? employees.length
        : employees.filter((item) => item.status === label).length
  }))
}

export function buildEmployeeSummary(employees) {
  return {
    total: employees.length,
    active: employees.filter((item) => item.status === '在职').length,
    onboarding: employees.filter((item) => item.status === '试用中').length,
    disabled: employees.filter((item) => item.status === '停用').length,
    followUp: employees.filter((item) => item.syncState !== '已同步').length,
    departments: uniqueSorted(employees.map((item) => item.department)).length
  }
}

export function mapSimpleFilterOptions(values, allLabel) {
  return [
    { label: allLabel, value: '' },
    ...values.map((value) => ({ label: value, value }))
  ]
}

export function buildEmployeeStatusActionCopy(options = {}) {
  const employeeName = options.selectedEmployee?.name || '该员工'
  if (options.selectedEmployeeDisabled) {
    return {
      buttonLabel: options.actionState === 'disable' ? '启用中...' : '启用账号',
      buttonIcon: 'mdi mdi-account-check-outline',
      badge: '启用账号',
      badgeTone: 'info',
      title: `确认启用 ${employeeName} 的账号吗？`,
      description: '启用后该员工将恢复登录能力，并重新获得个人业务入口访问权限。',
      confirmText: '确认启用',
      busyText: '启用中...',
      confirmTone: 'primary',
      confirmIcon: 'mdi mdi-account-check-outline',
      successMessage: '员工账号已启用。',
      failureMessage: '启用账号失败，请稍后重试。'
    }
  }

  return {
    buttonLabel: options.actionState === 'disable' ? '停用中...' : '停用账号',
    buttonIcon: 'mdi mdi-account-cancel-outline',
    badge: '停用账号',
    badgeTone: 'warning',
    title: `确认停用 ${employeeName} 的账号吗？`,
    description: '停用后该员工将无法继续登录系统，相关个人操作入口也会立即失效。',
    confirmText: '确认停用',
    busyText: '停用中...',
    confirmTone: 'danger',
    confirmIcon: 'mdi mdi-account-cancel-outline',
    successMessage: '员工账号已停用。',
    failureMessage: '停用账号失败，请稍后重试。'
  }
}

export function buildEmployeeEmptyState(options = {}) {
  const hasEmployeeFilters = Boolean(options.hasEmployeeFilters)
  const activeTab = options.activeTab || DEFAULT_STATUS_TABS[0]
  if (!options.employeeCount) {
    return {
      eyebrow: '员工台账',
      title: '员工目录暂时还是空的',
      desc: '当前环境还没有同步任何员工档案。完成目录接入后，这里会展示员工基础信息、角色和状态。',
      icon: 'mdi mdi-account-group-outline',
      actionLabel: '重新加载',
      actionIcon: 'mdi mdi-refresh',
      tone: 'sky',
      artLabel: 'PEOPLE',
      tips: ['支持按部门、职级和角色统一维护', '点击列表行即可进入档案和权限详情']
    }
  }

  return {
    eyebrow: hasEmployeeFilters ? '筛选结果为空' : '员工状态为空',
    title: hasEmployeeFilters ? '当前条件下没有匹配员工' : `“${activeTab}”里暂时没有员工`,
    desc: hasEmployeeFilters
      ? '可以切回“全部员工”，或者清空关键词、部门、职级和角色条件后再试。'
      : '这个状态标签下目前还没有记录，您可以切换到其他状态继续查看。',
    icon: hasEmployeeFilters ? 'mdi mdi-account-search-outline' : 'mdi mdi-badge-account-horizontal-outline',
    actionLabel: hasEmployeeFilters ? '清空筛选' : '查看全部员工',
    actionIcon: hasEmployeeFilters ? 'mdi mdi-filter-remove-outline' : 'mdi mdi-format-list-bulleted',
    tone: hasEmployeeFilters ? 'primary' : 'slate',
    artLabel: hasEmployeeFilters ? 'FILTER' : 'STATUS',
    tips: hasEmployeeFilters
      ? ['关键词、部门、职级和角色条件会叠加生效', '也可以直接搜索姓名、工号或岗位']
      : ['员工状态统计会按真实目录数据自动更新', '停用员工仍会保留在台账中便于追溯']
  }
}

export function buildEmployeeUpdatePayload(options = {}) {
  const current = options.selectedEmployee
  const form = options.form || {}
  const payload = {}

  if (!current) {
    return payload
  }

  const nextName = normalizeText(form.name)
  if (nextName && nextName !== current.name) payload.name = nextName

  const nextGender = normalizeNullableText(form.gender)
  if (nextGender !== (current.gender || null)) payload.gender = nextGender

  const nextBirthDate = normalizeNullableText(form.birthDate)
  if (nextBirthDate !== (current.birthDate || null)) payload.birth_date = nextBirthDate

  const nextPhone = normalizeNullableText(form.phone)
  if (nextPhone !== (current.phone || null)) payload.phone = nextPhone

  const nextEmail = normalizeText(form.email)
  if (nextEmail && nextEmail !== current.email) payload.email = nextEmail

  const nextJoinDate = normalizeNullableText(form.joinDate)
  if (nextJoinDate !== (current.joinDate || null)) payload.join_date = nextJoinDate

  const nextLocation = normalizeNullableText(form.location)
  if (nextLocation !== (current.location || null)) payload.location = nextLocation

  const nextPosition = normalizeText(form.position)
  if (nextPosition && nextPosition !== current.position) payload.position = nextPosition

  const nextGrade = normalizeText(form.grade)
  if (nextGrade && nextGrade !== current.grade) payload.grade = nextGrade

  const nextOrganizationCode = normalizeText(form.organizationUnitCode)
  const currentOrganizationCode =
    normalizeText(options.employeeDetailSnapshot?.organizationUnitCode) ||
    resolveOrganizationUnitCode(current) ||
    ''
  if (nextOrganizationCode !== currentOrganizationCode) {
    payload.organization_unit_code = nextOrganizationCode
  }

  const nextFinanceOwner = normalizeNullableText(form.financeOwner)
  if (nextFinanceOwner !== (current.financeOwner || null)) {
    payload.finance_owner_name = nextFinanceOwner
  }

  const nextCostCenter = normalizeNullableText(form.costCenter)
  if (nextCostCenter !== (current.costCenter || null)) {
    payload.cost_center = nextCostCenter
  }

  appendEmployeeBankUpdatePayload(payload, form, current, normalizeNullableText)

  const nextManagerEmployeeNo = normalizeNullableText(form.managerEmployeeNo)
  const currentManagerEmployeeNo =
    normalizeNullableText(current.managerEmployeeNo) ||
    resolveManagerEmployeeNo(current, options.employees || []) ||
    null
  if (nextManagerEmployeeNo !== currentManagerEmployeeNo) {
    payload.manager_employee_no = nextManagerEmployeeNo || ''
  }

  const nextRoleCodes = [...(form.roleCodes || [])].sort()
  const currentRoleCodes = [
    ...(options.employeeDetailSnapshot?.roleCodes || current.roleCodes || [])
  ].sort()
  if (!sameValues(nextRoleCodes, currentRoleCodes)) {
    payload.role_codes = [...(form.roleCodes || [])]
  }

  const nextPassword = normalizeText(form.password)
  if (nextPassword) payload.password = nextPassword

  return payload
}

function padDatePart(value) {
  return String(Number(value)).padStart(2, '0')
}
