<template>
  <el-select
    v-loading.fullscreen="companyChangeLoading"
    :element-loading-text="'正在切换至 ' + getUserCompany().name + ' ......'"
    element-loading-background="rgba(0, 0, 0, 0.8)"
    element-loading-spinner="el-icon-loading"
    :value="!global ? value : currentCompany"
    :remote-method="handleRemoteSearch"
    :placeholder="placeholder"
    style="width:380px"
    :disabled="disabled"
    reserve-keyword
    :size="size"
    filterable
    remote
    @change="setCurrentCompany"
  >
    <!-- 当selectAll为true 且为超管账号允许选择所有公司 -->
    <el-option v-if="selectAll && isSupertube" :label="allCompanyLabel" value="" />

    <el-options
      v-for="(company, index) in companylist"
      :key="index"
      class="custom-company"
      :label="genCompanyLabel(company)"
      :value="company.code"
    />

    <p v-if="state.loading" class="company-loading">
      <i class="el-icon-loading" />
      加载中...
    </p>

    <p v-if="state.noMore" class="company-more">没有更多数据了...</p>
  </el-select>
</template>

<script>
import requset  from '@/apis/user'
import { isBusinessCompany, isOnlyBusinessCompanyPath } from './utils'
import { accountLevels } from '@/assets/js/statusList'
import { userStoreActions } from '@/store/modules/user'
import { getUserCompany } from '@/utils/auth'
import { convertCompanylist } from '@/utils'
import { mapGetters, mapState } from 'vuex'

export default {
  /**
   * @param placeholder
   * @param size 选择器尺寸
   * @param disabled 是否禁用
   * @param selectAll 超管账号是否可以选择所有公司
   * @param global 是否设置全局选中公司(全局使用/组件独立使用)
   */
  props: {
    selectAll: {
      type: Boolean,
      default: false
    },
    size: {
      type: String,
      default: 'small'
    },
    placeholder: {
      type: String,
      default: ''
    },
    disabled: {
      type: Boolean,
      default: false
    },
    global: {
      type: Boolean,
      default: false
    },
    value: {
      type: String,
      default: ''
    },
    isSupplier: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    allCompanyLabel() { return this.currentLevel === accountLevels.supplier ? '所有供应商' : '所有业务公司' },
    ...mapGetters(['currentLevel']),
    ...mapState({
      currentCompany: state => state.user.currentCompany,
      companylist: state => state.user.companylist,
      isSupertube: state => state.user.isSupertube
    })
  },
  data() {
    return {
      ScrollWrapper: null,
      initialization: true,
      companyChangeLoading: false,
      key: 1,
      state: {
        loading: false,
        noMore: false
      },
      params: {
        name: '',
        page: 2,
        size: 10
      }
    }
  },
  watch: {
    currentLevel: {
      handler() {
        if (!this.isSupertube) return
        this.params = {
          name: '',
          page: 1,
          size: 10
        }
        this.state = {
          loading: false,
          noMore: false
        }
        this.initalData()
      }
    }
  },
  async mounted() {
    await this.initalData()
    this.ScrollWrapper = await this.getScrollWrapper()
    this.ScrollWrapper && this.bindEvent(this.ScrollWrapper)
  },
  beforeDestroy() {
    this.ScrollWrapper && this.removeEvent(this.ScrollWrapper)
  },
  methods: {
    getUserCompany,
    genCompanyLabel(company) {
      const { name, code, type } = company
      return `${code}/${name}${type === '1' ? '(已升级为业务公司)' : ''}`
    },
    async initalData(reset = false) {
      // 区分是否超管用户请求不同接口
      this.state.loading = true
      const api = this.isSupertube || this.isSupplier ? requset.requsetSupertubeCompany : requset.requsetUserBindingCompany
      const isSupplier = this.currentLevel === accountLevels.supplier
      const { page, size, name } = this.params

      const params = {
        ...(this.isSupertube ? { type: isSupplier ? '3' : '1' } : {}),
        [this.isSupertube ? 'name' : 'companyName']: name,
        page,
        size
      }

      const { code, data } = await api(params)

      if (code === 0) {
        if (data.list.length < 10) this.state.noMore = true
        this.state.loading = false
        this.params.page++
        const _list = this.isSupertube ? data.list : convertCompanylist(data.list)
        this.$store.commit('user/setCompanylist', reset ? [...this.companylist, ..._list] : _list)
        return this.isSupertube ? data.list : convertCompanylist(data.list)
      }
    },

    setCurrentCompany(currentCompany) {
      this.$emit('update:value', currentCompany)
      this.$emit('change', currentCompany)
      // 作为通用组件使用不设置全局选中公司
      if (!this.global) return null
      // 只能选择业务公司的页面
      const { path } = this.$route
      if (isOnlyBusinessCompanyPath(path) && !isBusinessCompany(currentCompany)) {
        this.$message.warning('该页面只能选择业务公司')
        return
      }
      this.$store.commit(userStoreActions.setCurrentCompany, currentCompany)
      if (this.isSupertube) return null // 超管用户不刷新路由
      this.changeRouterWithCompany()
    },

    async changeRouterWithCompany() {
      const { path, query } = this.$route
      query.redirect = path
      const keys = Object.keys(query).filter(key => key && key !== 'error')

      // 1.保存透传参数
      // 1.2 是否详情页
      const isDetailPath = path.indexOf('Detail') >= 0
      let queryString = ''
      const chunk = (qs, key, index) => {
        const next = `${key}=${query[key]}${index === keys.length ? '' : '&'}`
        return qs + next
      }

      // 2.重新获取用户信息和菜单
      this.companyChangeLoading = true
      const result = await this.$store.dispatch(userStoreActions.reloadMenu)
      this.companyChangeLoading = false
      switch (result) {
        // 登出
        case 'noToken':
          await this.$store.dispatch('user/logout')
          await this.$router.push(`/login`)
          break

          // 角色异常或该公司禁用清空菜单返回首页
        case 'disabled':
          await this.$store.dispatch('user/disabledCompany')
          break

          // 切换路由
        default:
          queryString = isDetailPath ? this.parsePathDetail2List(path) : keys.reduce(chunk, '?')
          await this.$router.replace('/reload' + queryString)
          break
      }
    },

    parsePathDetail2List(path) {
      const chunks = path.split('Detail')
      return `?redirect=${chunks[0]}`
    },

    getScrollWrapper() {
      return new Promise(resolve => {
        setTimeout(() => {
          let optionEl = document.querySelector('.custom-company')
          if (optionEl && (optionEl = optionEl.parentElement)) {
            resolve(optionEl.parentElement)
            return
          }
          resolve(null)
        }, 500)
      })
    },

    async handleScroll() {
      const ScrollWrapper = this.ScrollWrapper
      const height = ScrollWrapper.clientHeight
      const scrollTop = ScrollWrapper.scrollTop
      const scrollHeight = ScrollWrapper.scrollHeight
      const { loading, noMore } = this.state

      // 是否允许下拉加载
      const isAllowLoad = !loading && !noMore
      if (height + scrollTop >= scrollHeight && isAllowLoad) {
        const list = await this.loadMore()
        const _list = this.isSupertube ? list : convertCompanylist(list)
        // 保存到全局
        this.$store.commit(userStoreActions.setCompanyList, [...this.companylist, ..._list])
      }
    },

    async loadMore() {
      // 区分超管用户和普通用户
      const api = this.isSupertube ? requset.requsetSupertubeCompany : requset.requsetUserBindingCompany
      const isSupplier = this.currentLevel === accountLevels.supplier
      this.state.loading = true
      const { page, size, name } = this.params
      const nameProp = this.isSupertube ? 'name' : 'companyName'

      const params = {
        [nameProp]: name,
        page,
        size
      }

      const { data } = await api({
        ...params,
        ...(this.isSupertube ? { type: isSupplier ? '3' : '1' } : {})
      })
      this.state.loading = false
      const isTransborder = this.companylist.length >= Number(data.count) // 是否越界

      if (isTransborder) {
        this.state.noMore = true
        this.state.loading = false
        return []
      }
      this.params.page++
      return data.list
    },

    async handleRemoteSearch(name) {
      // 清空全局业务公司列表
      this.$store.commit(userStoreActions.setCompanyList, [])
      this.params.name = name
      this.params.page = 1
      this.state.noMore = false
      this.state.loading = false
      // 获取列表数据
      const result = await this.initalData()
      if (result) this.$store.commit(userStoreActions.setCompanyList, result)
    },

    bindEvent(ScrollWrapper) {
      ScrollWrapper.addEventListener('scroll', this.handleScroll)
    },

    removeEvent(ScrollWrapper) {
      ScrollWrapper.removeEventListener('scroll', this.handleScroll)
    },

    selectAllCompany() {
      this.value = ''
      this.$nextTick(() => (this.key = this.key + 1))
      this.global && this.$store.commit(userStoreActions.setCurrentCompany, '')
    }
  }
}
</script>

<style lang="scss" scoped>
.company-more {
  text-align: center;
  color: #999;
  font-size: 14px;
  line-height: 38px;
}

.company-loading {
  display: flex;
  font-size: 14px;
  justify-content: center;
  align-items: center;
  color: #999;
  gap: 10px;
  line-height: 38px;
}
</style>
