import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'

import { useToast } from '../../composables/useToast.js'
import { disableEmployee, fetchEmployeeMeta, fetchEmployees, updateEmployee } from '../../services/employees.js'

const DEFAULT_STATUS_TABS = ['全部员工', '在职', '试用中', '停用']
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: 'auditor',
    code: 'auditor',
    label: '审计观察员',
    desc: '可以查看变更记录和权限调整历史。'
  },
  {
    id: 'user',
    code: 'user',
    label: '使用者',
    desc: '可以发起报销、查看个人单据和使用 AI 助手。'
  }
]

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

function buildEmployeeForm(employee) {
  if (!employee) {
    return createEmployeeForm()
  }

  return {
    name: employee.name || '',
    employeeNo: employee.employeeNo || '',
    gender: employee.gender || '',
    birthDate: employee.birthDate || '',
    phone: employee.phone || '',
    email: employee.email || '',
    joinDate: employee.joinDate || '',
    location: employee.location || '',
    position: employee.position || '',
    grade: employee.grade || '',
    department: employee.department || '',
    manager: employee.manager || '',
    financeOwner: employee.financeOwner || '',
    costCenter: employee.costCenter || '',
    roleCodes: [...(employee.roleCodes || [])],
    password: ''
  }
}

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

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

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

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

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) : ''
}

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

  const haystack = [
    employee.name,
    employee.employeeNo,
    employee.department,
    employee.position,
    employee.email,
    employee.manager,
    employee.financeOwner,
    employee.syncState,
    ...(employee.roles || [])
  ]
    .filter(Boolean)
    .join(' ')
    .toLowerCase()

  return haystack.includes(keyword)
}

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

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: '该角色来自当前员工数据。'
    }))
  ]
}

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

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 default {
  name: 'EmployeeManagementView',
  emits: ['overview-change'],
  setup(_, { emit }) {
    const { toast } = useToast()
    const activeTab = ref(DEFAULT_STATUS_TABS[0])
    const selectedEmployee = ref(null)
    const employeeForm = ref(createEmployeeForm())
    const roleOptions = ref([...FALLBACK_ROLE_OPTIONS])
    const employees = ref([])
    const searchKeyword = ref('')
    const selectedDepartment = ref('')
    const selectedGrade = ref('')
    const selectedRole = ref('')
    const activeFilterPopover = ref('')
    const currentPage = ref(1)
    const pageSize = ref(10)
    const pageSizes = [10, 20, 50]
    const pageSizeOpen = ref(false)
    const actionState = ref('')
    const loading = ref(false)
    const errorMessage = ref('')

    const tabs = computed(() => buildStatusTabs(employees.value))
    const employeeSummary = computed(() => buildEmployeeSummary(employees.value))
    const detailAge = computed(() => calculateAgeFromDate(employeeForm.value.birthDate))
    const roleCount = computed(() => employeeForm.value.roleCodes.length)
    const selectedRoleLabels = computed(() =>
      roleOptions.value
        .filter((role) => employeeForm.value.roleCodes.includes(role.code))
        .map((role) => role.label)
    )
    const actionBusy = computed(() => actionState.value === 'save' || actionState.value === 'disable')
    const disableActionDisabled = computed(
      () =>
        actionBusy.value ||
        !selectedEmployee.value ||
        selectedEmployee.value.status === '停用'
    )

    const departmentOptions = computed(() =>
      uniqueSorted(employees.value.map((item) => item.department))
    )

    const gradeOptions = computed(() => uniqueSorted(employees.value.map((item) => item.grade)))

    const roleFilterOptions = computed(() =>
      uniqueSorted(
        roleOptions.value.map((item) => item.label).concat(
          employees.value.flatMap((item) => item.roles || [])
        )
      )
    )

    const filteredEmployees = computed(() => {
      const keyword = searchKeyword.value.trim().toLowerCase()

      return employees.value.filter((item) => {
        const matchesStatus =
          activeTab.value === '全部员工' ? true : item.status === activeTab.value
        const matchesDepartment = selectedDepartment.value
          ? item.department === selectedDepartment.value
          : true
        const matchesGrade = selectedGrade.value ? item.grade === selectedGrade.value : true
        const matchesRole = selectedRole.value
          ? (item.roles || []).includes(selectedRole.value)
          : true

        return (
          matchesStatus &&
          matchesDepartment &&
          matchesGrade &&
          matchesRole &&
          matchKeyword(item, keyword)
        )
      })
    })

    const totalCount = computed(() => filteredEmployees.value.length)
    const totalPages = computed(() => Math.max(1, Math.ceil(totalCount.value / pageSize.value)))

    const visibleEmployees = computed(() => {
      const start = (currentPage.value - 1) * pageSize.value
      return filteredEmployees.value.slice(start, start + pageSize.value)
    })

    const activeFilterTokens = computed(() => {
      const tokens = []

      if (selectedDepartment.value) {
        tokens.push(`部门：${selectedDepartment.value}`)
      }

      if (selectedGrade.value) {
        tokens.push(`职级：${selectedGrade.value}`)
      }

      if (selectedRole.value) {
        tokens.push(`角色：${selectedRole.value}`)
      }

      if (searchKeyword.value.trim()) {
        tokens.push(`搜索：${searchKeyword.value.trim()}`)
      }

      return tokens
    })

    const hasActiveFilters = computed(() => activeFilterTokens.value.length > 0)

    watch(
      employeeSummary,
      (summary) => {
        emit('overview-change', summary)
      },
      { immediate: true }
    )

    watch(
      selectedEmployee,
      (employee) => {
        employeeForm.value = buildEmployeeForm(employee)
      },
      { immediate: true }
    )

    watch(filteredEmployees, () => {
      currentPage.value = 1
      pageSizeOpen.value = false
    })

    function resetFilters() {
      searchKeyword.value = ''
      selectedDepartment.value = ''
      selectedGrade.value = ''
      selectedRole.value = ''
      activeTab.value = DEFAULT_STATUS_TABS[0]
      activeFilterPopover.value = ''
      pageSizeOpen.value = false
    }

    function changePageSize(size) {
      pageSize.value = size
      pageSizeOpen.value = false
      currentPage.value = 1
    }

    function togglePageSizeOpen() {
      pageSizeOpen.value = !pageSizeOpen.value
    }

    function toggleFilterPopover(name) {
      activeFilterPopover.value = activeFilterPopover.value === name ? '' : name
    }

    function closeFilterPopover() {
      activeFilterPopover.value = ''
    }

    function selectFilter(name, value) {
      if (name === 'department') {
        selectedDepartment.value = value
      }

      if (name === 'grade') {
        selectedGrade.value = value
      }

      if (name === 'role') {
        selectedRole.value = value
      }

      closeFilterPopover()
    }

    function handleDocumentClick(event) {
      const target = event.target

      if (!(target instanceof Element)) {
        closeFilterPopover()
        pageSizeOpen.value = false
        return
      }

      if (!target.closest('.picker-filter')) {
        closeFilterPopover()
      }

      if (!target.closest('.page-size-wrap')) {
        pageSizeOpen.value = false
      }

      if (target.closest('.picker-filter') || target.closest('.page-size-wrap')) {
        return
      }
    }

    function openEmployeeDetail(employee) {
      selectedEmployee.value = employee
    }

    function closeEmployeeDetail() {
      selectedEmployee.value = null
      employeeForm.value = createEmployeeForm()
      actionState.value = ''
    }

    function buildUpdatePayload() {
      const current = selectedEmployee.value
      const form = employeeForm.value
      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 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
      }

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

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

      return payload
    }

    async function saveEmployeeChanges() {
      if (!selectedEmployee.value || actionBusy.value) {
        return
      }

      if (!normalizeText(employeeForm.value.name)) {
        toast('员工姓名不能为空。')
        return
      }

      if (!normalizeText(employeeForm.value.email)) {
        toast('邮箱不能为空。')
        return
      }

      if (!normalizeText(employeeForm.value.position)) {
        toast('岗位不能为空。')
        return
      }

      if (!normalizeText(employeeForm.value.grade)) {
        toast('职级不能为空。')
        return
      }

      if (normalizeText(employeeForm.value.password) && normalizeText(employeeForm.value.password).length < 5) {
        toast('员工密码至少需要 5 位。')
        return
      }

      const payload = buildUpdatePayload()
      if (!Object.keys(payload).length) {
        toast('未检测到需要保存的变更。')
        return
      }

      actionState.value = 'save'

      try {
        const updated = await updateEmployee(selectedEmployee.value.id, payload)
        selectedEmployee.value = updated
        await loadEmployees()
        toast('员工信息已保存并生效。')
      } catch (error) {
        toast(error?.message || '员工信息保存失败，请稍后重试。')
      } finally {
        actionState.value = ''
      }
    }

    async function disableEmployeeAccount() {
      if (!selectedEmployee.value || disableActionDisabled.value) {
        return
      }

      if (!window.confirm(`确认停用 ${selectedEmployee.value.name} 的账号吗？`)) {
        return
      }

      actionState.value = 'disable'

      try {
        const updated = await disableEmployee(selectedEmployee.value.id)
        selectedEmployee.value = updated
        await loadEmployees()
        toast('员工账号已停用。')
      } catch (error) {
        toast(error?.message || '停用账号失败，请稍后重试。')
      } finally {
        actionState.value = ''
      }
    }

    async function loadEmployees() {
      loading.value = true
      errorMessage.value = ''

      const [employeesResult, metaResult] = await Promise.allSettled([
        fetchEmployees(),
        fetchEmployeeMeta()
      ])

      if (employeesResult.status !== 'fulfilled') {
        employees.value = []
        roleOptions.value = [...FALLBACK_ROLE_OPTIONS]
        selectedEmployee.value = null
        errorMessage.value =
          employeesResult.reason?.message || '员工数据加载失败，请稍后重试。'
        loading.value = false
        return
      }

      employees.value = Array.isArray(employeesResult.value) ? employeesResult.value : []

      if (metaResult.status === 'fulfilled') {
        roleOptions.value = resolveRoleOptions(metaResult.value?.roleOptions, employees.value)
      } else {
        roleOptions.value = resolveRoleOptions([], employees.value)
      }

      if (!DEFAULT_STATUS_TABS.includes(activeTab.value)) {
        activeTab.value = DEFAULT_STATUS_TABS[0]
      }

      if (selectedEmployee.value) {
        selectedEmployee.value =
          employees.value.find((item) => item.id === selectedEmployee.value.id) || null
      }

      loading.value = false
    }

    onMounted(() => {
      document.addEventListener('click', handleDocumentClick)
      loadEmployees().catch((error) => {
        employees.value = []
        roleOptions.value = [...FALLBACK_ROLE_OPTIONS]
        selectedEmployee.value = null
        errorMessage.value = error?.message || '员工数据加载失败，请稍后重试。'
        loading.value = false
      })
    })

    onBeforeUnmount(() => {
      document.removeEventListener('click', handleDocumentClick)
    })

    return {
      tabs,
      activeTab,
      employeeForm,
      detailAge,
      roleCount,
      selectedRoleLabels,
      actionState,
      actionBusy,
      disableActionDisabled,
      selectedEmployee,
      roleOptions,
      employees,
      visibleEmployees,
      searchKeyword,
      selectedDepartment,
      selectedGrade,
      selectedRole,
      activeFilterPopover,
      currentPage,
      pageSize,
      pageSizes,
      pageSizeOpen,
      departmentOptions,
      gradeOptions,
      roleFilterOptions,
      activeFilterTokens,
      hasActiveFilters,
      totalCount,
      totalPages,
      resetFilters,
      openEmployeeDetail,
      closeEmployeeDetail,
      saveEmployeeChanges,
      disableEmployeeAccount,
      changePageSize,
      togglePageSizeOpen,
      toggleFilterPopover,
      closeFilterPopover,
      selectFilter,
      loading,
      errorMessage,
      loadEmployees
    }
  }
}
