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

import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
import DocumentDropdownFilter from '../../components/shared/DocumentDropdownFilter.vue'
import EnterprisePagination from '../../components/shared/EnterprisePagination.vue'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
import { useToast } from '../../composables/useToast.js'
import {
  disableEmployee,
  downloadEmployeeImportTemplate,
  enableEmployee,
  exportEmployees,
  fetchEmployeeDetail,
  fetchEmployeeMeta,
  fetchEmployees,
  importEmployees,
  updateEmployee
} from '../../services/employees.js'
import {
  DEFAULT_STATUS_TABS,
  FALLBACK_ROLE_OPTIONS,
  buildEmployeeForm,
  buildEmployeeStatusActionCopy,
  buildEmployeeUpdatePayload,
  calculateAgeFromDate,
  calculateBirthDateFromAge,
  captureEmployeeDetailSnapshot,
  createEmployeeForm,
  enrichEmployeeRecord,
  formatEmployeeHistoryTime,
  isValidEmail,
  isValidIsoDate,
  mergeEmployeeRecords,
  normalizeNullableText,
  normalizeText,
  resolveOrganizationOptions,
  resolveRoleOptions
} from './employeeManagementModel.js'
import { useEmployeeManagementFilters } from './useEmployeeManagementFilters.js'
import { useEmployeeManagementPickers } from './useEmployeeManagementPickers.js'

export default {
  name: 'EmployeeManagementView',
  components: {
    ConfirmDialog,
    DocumentDropdownFilter,
    EnterprisePagination,
    EnterpriseSelect,
    TableLoadingState,
    TableEmptyState
  },
  emits: ['overview-change'],
  setup(_, { emit }) {
    const { toast } = useToast()
    const selectedEmployee = ref(null)
    const employeeForm = ref(createEmployeeForm())
    const roleOptions = ref([...FALLBACK_ROLE_OPTIONS])
    const employees = ref([])
    const actionState = ref('')
    const loading = ref(false)
    const errorMessage = ref('')
    const disableDialogOpen = ref(false)
    const importFileInput = ref(null)
    const pendingImportFile = ref(null)
    const importConfirmDialogOpen = ref(false)
    const importErrorDialogOpen = ref(false)
    const importErrors = ref([])
    const importResultMessage = ref('')
    const organizationUnitOptions = ref([])
    const employeeDetailSnapshot = ref(null)

    const employeeFilters = useEmployeeManagementFilters({
      employees,
      roleOptions,
      emit,
      loadEmployees: () => loadEmployees()
    })
    const {
      activeTab,
      searchKeyword,
      selectedDepartment,
      selectedGrade,
      selectedRole,
      activeFilterPopover,
      currentPage,
      pageSize,
      pageSizes,
      pageSizeOptions,
      tabs,
      departmentOptions,
      gradeOptions,
      roleFilterOptions,
      departmentFilterOptions,
      gradeFilterOptions,
      roleDropdownOptions,
      departmentFilterLabel,
      gradeFilterLabel,
      roleFilterLabel,
      totalCount,
      totalPages,
      pageSummary,
      visibleEmployees,
      activeFilterTokens,
      hasActiveFilters,
      hasEmployeeFilters,
      employeeEmptyState,
      resetFilters,
      handleEmployeeEmptyAction,
      changePageSize,
      toggleFilterPopover,
      closeFilterPopover,
      selectFilter
    } = employeeFilters

    const employeePickers = useEmployeeManagementPickers({
      selectedEmployee,
      employees,
      employeeForm,
      organizationUnitOptions,
      closeFilterPopover
    })
    const {
      managerPickerOpen,
      managerSearchKeyword,
      managerDisplayLabel,
      hasManagerAssignment,
      departmentPickerOpen,
      departmentSearchKeyword,
      departmentDisplayLabel,
      filteredDepartmentOptions,
      filteredManagerOptions,
      handleDocumentClick,
      toggleDepartmentPicker,
      closeDepartmentPicker,
      selectDepartment,
      resolveDepartmentSelectionFromKeyword,
      toggleManagerPicker,
      closeManagerPicker,
      selectManager,
      resolveManagerSelectionFromKeyword
    } = employeePickers

    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' ||
        actionState.value === 'import' ||
        actionState.value === 'export'
    )
    const importExportBusy = computed(
      () => actionState.value === 'import' || actionState.value === 'export'
    )
    const disableActionDisabled = computed(() => actionBusy.value || !selectedEmployee.value)
    const selectedEmployeeDisabled = computed(() => selectedEmployee.value?.status === '停用')
    const statusActionCopy = computed(() => buildEmployeeStatusActionCopy({
      selectedEmployee: selectedEmployee.value,
      selectedEmployeeDisabled: selectedEmployeeDisabled.value,
      actionState: actionState.value
    }))

    function syncFormFromEmployee(employee) {
      if (!employee) {
        employeeForm.value = createEmployeeForm()
        employeeDetailSnapshot.value = null
        return
      }

      const preservedPassword = employeeForm.value.password
      employeeForm.value = buildEmployeeForm(employee, employees.value)
      employeeForm.value.password = preservedPassword
      employeeDetailSnapshot.value = captureEmployeeDetailSnapshot(employeeForm.value)
    }

    watch(
      () => selectedEmployee.value?.id ?? null,
      (employeeId, previousId) => {
        if (!employeeId) {
          syncFormFromEmployee(null)
          return
        }

        if (employeeId === previousId) {
          return
        }

        syncFormFromEmployee(selectedEmployee.value)
      },
      { immediate: true }
    )

    watch(employees, () => {
      if (!selectedEmployee.value?.id) {
        return
      }

      const preserved = selectedEmployee.value
      const fromList = employees.value.find((item) => item.id === preserved.id)
      if (!fromList) {
        return
      }

      selectedEmployee.value = mergeEmployeeRecords(fromList, preserved, employees.value)
    })

    const recentEmployeeHistory = computed(() => {
      const history = selectedEmployee.value?.history
      if (!Array.isArray(history)) {
        return []
      }

      return history.slice(0, 5)
    })

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

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

    function syncAgeFromBirthDate() {
      employeeForm.value.age = calculateAgeFromDate(employeeForm.value.birthDate)
    }

    function syncBirthDateFromAge() {
      const ageText = normalizeText(employeeForm.value.age)
      if (!ageText) {
        return
      }

      employeeForm.value.birthDate = calculateBirthDateFromAge(
        ageText,
        employeeForm.value.birthDate
      )
    }

    function buildUpdatePayload() {
      return buildEmployeeUpdatePayload({
        selectedEmployee: selectedEmployee.value,
        form: employeeForm.value,
        employeeDetailSnapshot: employeeDetailSnapshot.value,
        employees: employees.value
      })
    }

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

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

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

      if (!isValidEmail(employeeForm.value.email)) {
        toast('请输入有效的邮箱地址。')
        return
      }

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

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

      const ageText = normalizeText(employeeForm.value.age)
      if (ageText) {
        const age = Number.parseInt(ageText, 10)
        if (Number.isNaN(age) || age < 0 || age > 120) {
          toast('年龄请输入 0 到 120 之间的整数。')
          return
        }
        syncBirthDateFromAge()
      }

      const birthDate = normalizeNullableText(employeeForm.value.birthDate)
      if (birthDate && !isValidIsoDate(birthDate)) {
        toast('出生日期格式不正确，请使用 YYYY-MM-DD。')
        return
      }

      const joinDate = normalizeNullableText(employeeForm.value.joinDate)
      if (joinDate && !isValidIsoDate(joinDate)) {
        toast('入职日期格式不正确，请使用 YYYY-MM-DD。')
        return
      }

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

      resolveManagerSelectionFromKeyword()
      resolveDepartmentSelectionFromKeyword()

      if (!normalizeText(employeeForm.value.organizationUnitCode)) {
        toast('请选择所属部门。')
        return
      }

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

      if (normalizeText(employeeForm.value.managerEmployeeNo) === selectedEmployee.value.employeeNo) {
        toast('直属上级不能设置为员工本人。')
        return
      }

      actionState.value = 'save'

      try {
        const employeeId = selectedEmployee.value.id
        const updated = await updateEmployee(employeeId, payload)
        selectedEmployee.value = updated
        await loadEmployees()

        let refreshed = updated
        try {
          refreshed = await fetchEmployeeDetail(employeeId)
        } catch {
          refreshed = updated
        }

        const fromList = employees.value.find((item) => item.id === employeeId)
        const merged = mergeEmployeeRecords(fromList, refreshed, employees.value)
        selectedEmployee.value = merged

        const listIndex = employees.value.findIndex((item) => item.id === employeeId)
        if (listIndex >= 0) {
          employees.value[listIndex] = {
            ...employees.value[listIndex],
            ...merged
          }
        }

        closeManagerPicker()
        closeDepartmentPicker()
        syncFormFromEmployee(selectedEmployee.value)
        employeeDetailSnapshot.value = captureEmployeeDetailSnapshot(employeeForm.value)
        toast('员工信息已保存并生效。')
      } catch (error) {
        toast(error?.message || '员工信息保存失败，请稍后重试。')
      } finally {
        actionState.value = ''
      }
    }

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

      disableDialogOpen.value = true
    }

    function closeDisableDialog() {
      if (actionState.value === 'disable') {
        return
      }

      disableDialogOpen.value = false
    }

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

      const shouldEnable = selectedEmployeeDisabled.value
      const actionCopy = shouldEnable
        ? {
            successMessage: '员工账号已启用。',
            failureMessage: '启用账号失败，请稍后重试。'
          }
        : {
            successMessage: '员工账号已停用。',
            failureMessage: '停用账号失败，请稍后重试。'
          }

      actionState.value = 'disable'

      try {
        const updated = shouldEnable
          ? await enableEmployee(selectedEmployee.value.id)
          : await disableEmployee(selectedEmployee.value.id)
        disableDialogOpen.value = false
        selectedEmployee.value = updated
        await loadEmployees()
        toast(actionCopy.successMessage)
      } catch (error) {
        toast(error?.message || actionCopy.failureMessage)
      } finally {
        actionState.value = ''
      }
    }

    function openImportFilePicker() {
      importFileInput.value?.click()
    }

    function handleImportFileChange(event) {
      const file = event.target.files?.[0]
      event.target.value = ''

      if (!file) {
        return
      }

      pendingImportFile.value = file
      importConfirmDialogOpen.value = true
    }

    function closeImportConfirmDialog() {
      if (actionState.value === 'import') {
        return
      }

      importConfirmDialogOpen.value = false
      pendingImportFile.value = null
    }

    function closeImportErrorDialog() {
      importErrorDialogOpen.value = false
      importErrors.value = []
      importResultMessage.value = ''
    }

    async function handleDownloadTemplate() {
      try {
        await downloadEmployeeImportTemplate()
        toast('员工导入模板已开始下载。')
      } catch (error) {
        toast(error?.message || '模板下载失败，请稍后重试。')
      }
    }

    async function handleExportEmployees() {
      actionState.value = 'export'

      try {
        await exportEmployees({
          status: activeTab.value,
          keyword: searchKeyword.value.trim()
        })
        toast('员工目录已开始导出。')
      } catch (error) {
        toast(error?.message || '员工导出失败，请稍后重试。')
      } finally {
        actionState.value = ''
      }
    }

    async function confirmImportEmployees() {
      const file = pendingImportFile.value
      if (!file) {
        closeImportConfirmDialog()
        return
      }

      actionState.value = 'import'

      try {
        const result = await importEmployees(file)

        if (!result?.success) {
          importErrors.value = Array.isArray(result?.errors) ? result.errors : []
          importResultMessage.value =
            result?.message || '导入未执行，请根据下方错误提示修正 Excel 后重试。'
          importConfirmDialogOpen.value = false
          importErrorDialogOpen.value = true
          pendingImportFile.value = null
          return
        }

        importConfirmDialogOpen.value = false
        pendingImportFile.value = null
        await loadEmployees()
        toast(result.message || '员工导入成功。')
      } 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]
        organizationUnitOptions.value = []
        selectedEmployee.value = null
        errorMessage.value =
          employeesResult.reason?.message || '员工数据加载失败，请稍后重试。'
        loading.value = false
        return
      }

      const roster = Array.isArray(employeesResult.value) ? employeesResult.value : []
      employees.value = roster.map((item) => enrichEmployeeRecord(item, roster))

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

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

      if (selectedEmployee.value) {
        const preserved = selectedEmployee.value
        const fromList = employees.value.find((item) => item.id === preserved.id) || null
        selectedEmployee.value = mergeEmployeeRecords(fromList, preserved, employees.value)
      }

      loading.value = false
    }

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

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

    return {
      tabs,
      activeTab,
      employeeForm,
      roleCount,
      syncAgeFromBirthDate,
      syncBirthDateFromAge,
      selectedRoleLabels,
      selectedEmployeeDisabled,
      statusActionCopy,
      actionState,
      actionBusy,
      importExportBusy,
      importFileInput,
      importConfirmDialogOpen,
      importErrorDialogOpen,
      importErrors,
      importResultMessage,
      openImportFilePicker,
      handleImportFileChange,
      closeImportConfirmDialog,
      closeImportErrorDialog,
      handleDownloadTemplate,
      handleExportEmployees,
      confirmImportEmployees,
      disableActionDisabled,
      selectedEmployee,
      roleOptions,
      employees,
      visibleEmployees,
      employeeEmptyState,
      searchKeyword,
      selectedDepartment,
      selectedGrade,
      selectedRole,
      departmentFilterLabel,
      departmentFilterOptions,
      gradeFilterLabel,
      gradeFilterOptions,
      roleDropdownOptions,
      roleFilterLabel,
      activeFilterPopover,
      currentPage,
      pageSize,
      pageSizes,
      pageSizeOptions,
      departmentOptions,
      gradeOptions,
      roleFilterOptions,
      managerPickerOpen,
      managerSearchKeyword,
      managerDisplayLabel,
      hasManagerAssignment,
      departmentPickerOpen,
      departmentSearchKeyword,
      departmentDisplayLabel,
      filteredDepartmentOptions,
      toggleDepartmentPicker,
      closeDepartmentPicker,
      selectDepartment,
      resolveDepartmentSelectionFromKeyword,
      recentEmployeeHistory,
      formatEmployeeHistoryTime,
      filteredManagerOptions,
      toggleManagerPicker,
      closeManagerPicker,
      selectManager,
      resolveManagerSelectionFromKeyword,
      activeFilterTokens,
      hasActiveFilters,
      hasEmployeeFilters,
      totalCount,
      totalPages,
      pageSummary,
      resetFilters,
      handleEmployeeEmptyAction,
      openEmployeeDetail,
      closeEmployeeDetail,
      closeDisableDialog,
      confirmDisableEmployeeAccount,
      saveEmployeeChanges,
      disableDialogOpen,
      disableEmployeeAccount,
      changePageSize,
      toggleFilterPopover,
      closeFilterPopover,
      selectFilter,
      loading,
      errorMessage,
      loadEmployees
    }
  }
}
