<template>
  <div class="dashboard-panel-element px-0 pt-3">
    <b-row class="border-bottom m-0 mb-3 text-capitalize">
      <b-col cols="12" lg="6" class="border-right">
        <b-form-group :label="$t('Common.MemberID')" label-for="SponsorDownLine">
          <b-input-group id="SponsorDownLine">
            <eshop-autocomplete
              :wait="500"
              :min-len="3"
              variant="primary"
              class="flex-grow-1"
              template-name="member"
              :items="getMemberList"
              v-model="downlineListingFilter.searchMember"
              :get-label="item => (item ? item.name : '')"
              :placeholder="$t('Genealogy.SponsorNetworkTree.Search.SearchDownline')"
              @updateItems="loadMemberListItem"
              @item-selected="setMemberDetails"
            />
            <b-input-group-append>
              <div class="border border-left-0 d-flex align-items-center px-2">
                <b-spinner v-show="isLoading('memberListLoading')" small variant="primary" />
              </div>

              <b-button
                v-if="$helpers.isEmpty(downlineListingFilter.searchMember) === false"
                variant="link"
                @click="setMemberDetails()"
                class="border-light border-left rounded-0"
                data-qa="genealogy-evo-sponsor-downline-listing-member-search-clear-btn"
              >
                <icon name="clear-icon" />
              </b-button>
            </b-input-group-append>
          </b-input-group>
        </b-form-group>

        <b-row>
          <b-col cols="6">
            <b-form-group :label="$t('Genealogy.SponsorDownlineListing.MaxLevels')" label-for="MaxLevels">
              <b-form-select
                id="MaxLevels"
                :options="getMaxLevelOptions"
                v-model="downlineListingFilter.maxLevel"
                data-qa="genealogy-evo-sponsor-downline-listing-max-level-select"
              />
            </b-form-group>
          </b-col>

          <b-col cols="6">
            <b-form-group>
              <b-form-group :label="$t('Genealogy.SponsorDownlineListing.FilterExpiry')" label-for="MaxLevels">
                <b-form-select
                  id="MaxLevels"
                  :options="payCycleOptions"
                  v-model="downlineListingFilter.expiry"
                  data-qa="genealogy-evo-sponsor-downline-listing-expiry-select"
                />
              </b-form-group>
            </b-form-group>
          </b-col>
        </b-row>

        <b-form-group>
          <b-form-checkbox
            v-model="isFilterByMinPoint"
            data-qa="genealogy-evo-sponsor-downline-listing-filter-by-minimal-point-checkbox"
          >
            {{ $t('Genealogy.SponsorDownlineListing.FilterByMinimumPoints') }}
          </b-form-checkbox>
        </b-form-group>
      </b-col>

      <b-col cols="12" lg="6">
        <b-row>
          <b-col cols="6">
            <b-form-group :label="$t('Genealogy.SponsorDownlineListing.Breakaway')" label-for="Breakaway">
              <b-form-select
                id="Breakaway"
                :options="getBreakawayOptions"
                v-model="downlineListingFilter.breakaway"
                data-qa="genealogy-evo-sponsor-downline-listing-breakaway-select"
              />
            </b-form-group>
          </b-col>

          <b-col cols="6">
            <b-form-group>
              <b-form-group :label="$t('Eshop.SortBy.Title')" label-for="SortBy">
                <b-form-select
                  id="SortBy"
                  :options="getSortOptions"
                  v-model="downlineListingFilter.sortBy"
                  data-qa="genealogy-evo-sponsor-downline-listing-sort-bt-select"
                />
              </b-form-group>
            </b-form-group>
          </b-col>
        </b-row>

        <b-form-group
          v-if="councilRankOptions.length"
          :label="$t('Common.Terminology.CouncilRank')"
          label-for="CouncilRank"
        >
          <b-form-checkbox-group
            id="CouncilRank"
            :options="councilRankOptions"
            v-model="downlineListingFilter.councilRank"
            data-qa="genealogy-evo-sponsor-downline-listing-council-rank-checkbox-group"
          />
        </b-form-group>

        <div class="my-2 float-right">
          <b-button
            class="px-5"
            variant="primary"
            @click="loadDownlineListingRecords"
            :disabled="isLoading('loadingSponsorDownlineList')"
            data-qa="genealogy-evo-sponsor-downline-listing-list-btn"
          >
            <span>{{ $t('Genealogy.SponsorDownlineListing.List') }}</span>
            <b-spinner v-show="isLoading('loadingSponsorDownlineList')" small class="ml-2" />
          </b-button>
        </div>
      </b-col>
    </b-row>

    <b-row
      v-if="isFilterByMinPoint && !isLoading('loadingSponsorDownlineFilterList')"
      class="m-0 mb-3 animated fadeInDown"
    >
      <b-col v-for="(filter, idx) in getFilterByMinOptions" :key="idx" cols="6">
        <b-form-group :label="filter.text">
          <b-input
            @change="value => updateMinFilter(filter.key, value)"
            :data-qa="`genealogy-evo-sponsor-downline-listing-${filter.key}-input`"
          />
        </b-form-group>
      </b-col>
    </b-row>

    <b-row class="m-0">
      <b-col cols="12" class="mb-2">
        <b-button
          variant="green"
          class="px-3 float-right"
          @click="printSponsorDownlineList"
          :disabled="isLoading('requestingSponsorDownlineStatement')"
          data-qa="genealogy-evo-sponsor-downline-listing-print-btn"
        >
          <icon v-show="!isLoading('requestingSponsorDownlineStatement')" name="printer-icon" class="mr-2" />
          <span>{{ $t('Common.Print') }}</span>
          <b-spinner v-show="isLoading('requestingSponsorDownlineStatement')" small class="ml-2" />
        </b-button>
      </b-col>
      <b-col cols="12">
        <b-table
          hover
          bordered
          show-empty
          responsive=""
          stacked="xl"
          :thead-class="['text-capitalize']"
          :items="getSponsorDownLineRecords"
          :fields="getSponsorDownLineFields"
          :busy="isLoading('loadingSponsorDownlineList')"
        >
          <template v-slot:empty>
            <div class="text-center my-2">
              <h5 class="text-primary">{{ $t('Common.RecordNotFound') }}</h5>
            </div>
          </template>

          <template v-slot:table-busy>
            <div class="text-center text-primary my-2">
              <b-spinner class="mx-2" />
              <strong class="h4">{{ $t('Common.Loading') }}</strong>
            </div>
          </template>
        </b-table>
      </b-col>
    </b-row>

    <b-modal
      v-model="loadingModalMeta.show"
      lazy
      ok-only
      centered
      no-close-on-esc
      no-close-on-backdrop
      header-class="border-0"
      footer-class="border-0"
    >
      <div class="text-center">
        <div><b-spinner class="mb-2" variant="primary" /></div>
        <span>{{ loadingModalMeta.msg || $t('Genealogy.SponsorDownlineListing.GeneratingReport') }}</span>
      </div>
    </b-modal>
  </div>
</template>

<script>
import { mapActions, mapGetters } from 'vuex'
import EshopAutocomplete from '@/app/_global/components/elements/EshopAutocomplete'

export default {
  name: 'EvoSponsorDownlineListing',
  components: { EshopAutocomplete },
  data() {
    return {
      payCycleOptions: [],
      councilRankOptions: [],
      isFilterByMinPoint: false,
      sponsorDownlineFilters: [],
      sponsorDownLineRecords: [],
      connectedWebSocketList: [],
      loadingModalMeta: { show: false, msg: '' },
      payCycleFilter: { filter_type: 'current', sort: 'id', order: 'desc', limit: 2 },
      downlineListingFilter: {
        maxLevel: 1,
        expiry: null,
        sortBy: null,
        minFilters: {},
        councilRank: [],
        searchMember: '',
        breakaway: false,
        selectedDownlineId: '',
      },
    }
  },
  watch: {
    'downlineListingFilter.expiry'(val) {
      this.loadSponsorDownlineFilters(val)
      this.downlineListingFilter = {
        ...this.downlineListingFilter,
        minFilters: {},
        sortBy: null,
      }
    },
    isFilterByMinPoint(toggle) {
      if (!toggle) {
        this.downlineListingFilter.minFilters = {}
      }
    },
  },
  computed: {
    ...mapGetters(['getMemberList', 'isLoading']),
    getMaxLevelOptions() {
      return Array.from({ length: 99 }, (k, i) => i + 1)
    },
    getBreakawayOptions() {
      return [
        { text: this.$t('Common.Yes'), value: true },
        { text: this.$t('Common.No'), value: false },
      ]
    },
    getBaseSponsorDownLineFilters() {
      return [
        { key: 'level', label: this.$t('Genealogy.Level', { level: '' }) },
        {
          key: 'old_member_id',
          label: this.$t('Common.MemberID'),
          formatter: (data, key, item) => `${data} ${(!item.has_order && '*') || ''}`,
          tdClass: ['no-wrap'],
        },
        { key: 'effective_rank_code', label: this.$t('Common.Rank') },
        { key: 'council_rank_code', label: this.$t('Common.Terminology.CouncilRank') },
        { key: 'name', label: this.$t('Common.IboName') },
        { key: 'expiry', label: this.$t('Genealogy.SponsorDownlineListing.TableHeader.Expiry') },
        {
          key: 'has_payout_info',
          label: this.$t('Genealogy.SponsorDownlineListing.TableHeader.PayoutMethod'),
          formatter: data => this.$t(data ? 'Common.Yes' : 'Common.No'),
        },
      ]
    },
    getSponsorDownLineFields() {
      let fields = this.getBaseSponsorDownLineFilters

      let dynamicField = this.$helpers
        .getValue(this.getSponsorDownLineRecords, '[0].bonuses', [])
        .map(bonus => ({ key: bonus.key, label: bonus.name, class: ['text-lg-right'] }))

      return [...fields.slice(0, 5), ...dynamicField, ...fields.slice(5, 7)]
    },
    getFilterByMinOptions() {
      return (this.sponsorDownlineFilters || []).map(data => ({
        key: data.key,
        value: data.key,
        text: data.name,
      }))
    },
    getSortOptions() {
      return [
        ...this.getBaseSponsorDownLineFilters.map(filter => ({ value: filter.key, text: filter.label })),
        ...this.getFilterByMinOptions,
      ]
    },
    getSponsorDownLineRecords() {
      return this.sponsorDownLineRecords || []
    },
  },
  mounted() {
    this.loadMemberListItem()
    this.loadSponsorDownlineFilters()
    this.loadCwScheduleList(this.payCycleFilter).then(cycles => {
      this.payCycleOptions = (cycles || []).map(cycle => ({ text: cycle.cw_name, value: cycle.id }))
    })
    this.loadCouncilRankList().then(ranks => {
      this.councilRankOptions = (ranks || []).map(rank => ({ text: rank.code, value: rank.id }))
    })
  },
  methods: {
    ...mapActions([
      'loadMemberList',
      'loadCwScheduleList',
      'loadCouncilRankList',
      'loadSponsorDownlineList',
      'loadSponsorDownlineFilterList',
      'requestSponsorDownlineStatement',
    ]),
    setMemberDetails(val = {}) {
      this.downlineListingFilter = {
        ...this.downlineListingFilter,
        searchMember: '',
        selectedDownlineId: val.user_id || '',
      }
    },
    updateMinFilter(key, value) {
      if (value !== '') {
        this.downlineListingFilter.minFilters[key] = value
      } else {
        delete this.downlineListingFilter.minFilters[key]
      }
    },
    loadMemberListItem(val = '') {
      this.loadMemberList({ searchText: val, minimal: true })
    },
    loadSponsorDownlineFilters(cwId = null) {
      this.loadSponsorDownlineFilterList(cwId).then(filters => {
        this.sponsorDownlineFilters = filters || []
      })
    },
    loadDownlineListingRecords() {
      let payload = this.sponsorDownlinePayloadFactory()

      this.loadSponsorDownlineList(payload).then(result => {
        this.sponsorDownLineRecords = this.sponsorDownlineRecordDataNormalizer(result || [])
      })
    },
    printSponsorDownlineList() {
      let payload = this.sponsorDownlinePayloadFactory()

      this.requestSponsorDownlineStatement(payload).then(result => {
        if (result && result.job_event_name) {
          this.loadingModalMeta = { show: true, msg: result.message }
          this.enableReportSocketEventListener(result.job_event_name)
        } else {
          this.$swal({
            type: 'error',
            title: this.$t('Common.Table.NoRecords.Msg'),
          })
        }
      })
    },
    sponsorDownlineRecordDataNormalizer(records = []) {
      return records.map(record => {
        let mappedBonuses = {}

        Object.assign([], record.bonuses).forEach(bonus => {
          mappedBonuses[bonus.key] = bonus.value
        })

        return { ...record, ...mappedBonuses }
      })
    },
    sponsorDownlinePayloadFactory() {
      let {
        expiry,
        sortBy,
        maxLevel,
        breakaway,
        minFilters,
        councilRank,
        selectedDownlineId,
      } = this.downlineListingFilter

      return {
        sortBy,
        breakaway,
        depth: maxLevel,
        activeUntilCwId: expiry,
        councilRankIds: [...councilRank],
        downlineUserId: selectedDownlineId,
        dynamicFilters: Object.entries(minFilters).map(data => ({ key: data[0], value: data[1] })),
      }
    },
    enableReportSocketEventListener(connectionString) {
      if (this.$echo && !this.connectedWebSocketList.includes(connectionString)) {
        let [channel, eventName] = connectionString.split(':')

        this.connectedWebSocketList.push(connectionString) // push con string will easy connection remove without hard coding
        this.$echo.private(channel).listen(`.${eventName}`, data => {
          if (data.status) {
            this.loadingModalMeta = { show: false, msg: '' }
          }

          data.links.forEach(link => {
            window.open(link, '_blank')
          })
        })
      }
    },
  },
  destroyed() {
    if (this.$echo) {
      this.connectedWebSocketList.forEach(socket => {
        this.$echo.leave(socket.split(':')[0])
      })
      this.connectedWebSocketList = []
    }
  },
}
</script>
