<template>
  <div class="adb-filter-operation">
    <div v-if="item.type === 'checkbox'" class="adb-filter-operation__checkbox">
      <el-input
        v-if="item.options.length > 5"
        v-model="filterSearch"
        class="adb-filter-operation__search"
        :placeholder="`${$tc('adb-filter.searchBy')} ${item.label}`"
        clearable
      />

      <div class="adb-filter-operation__select-all">
        <el-checkbox v-model="isSelectAll" @change="onChangeAll">
          {{ $tc('adb-filter.SelectAll') }}
        </el-checkbox>
      </div>

      <el-checkbox-group
        v-model="model"
        class="content-wrapper"
        @change="(val) => onChangeItem(val, { key: item.key })"
      >
        <el-checkbox
          v-for="op in listOptions"
          class="adb-filter-operation__checkbox__item"
          :key="op.value"
          :label="op.value"
        >
          <slot v-if="item.slot" name="optionItem" :option="op"></slot>
          <span v-else> {{ op.label }}</span>
        </el-checkbox>
      </el-checkbox-group>
    </div>
    <div
      v-else-if="item.type === 'amount-range' || item.type === 'number-range'"
      class="adb-filter-operation__amount-range"
    >
      <div class="adb-filter-operation__amount-range__content">
        <div class="min-amount-wrapper">
          <span v-if="item.type === 'amount-range'" class="min-amount__icon"
            >$</span
          >
          <el-input-number
            v-model="model[0]"
            class="amount-input"
            :controls="false"
            :min="oneMinForTypeAmountRanage"
            :max="oneMaxForTypeAmountRange"
            :precision="precisionForTypeRange"
            :placeholder="placeholderForTypeRange[0]"
            :disabled="item.disabled || false"
            @change="(val) => onChangeItem(val, { key: item.key, index: 0 })"
            @blur="(val) => onChangeItem(val, { key: item.key, index: 0 })"
          />
        </div>
        <span class="center">-</span>
        <div class="min-amount-wrapper">
          <span v-if="item.type === 'amount-range'" class="min-amount__icon"
            >$</span
          >
          <el-input-number
            v-model="model[1]"
            class="amount-input"
            :controls="false"
            :min="twoMinForTypeAmountRanage"
            :max="twoMaxForTypeAmountRange"
            :placeholder="placeholderForTypeRange[1]"
            :precision="precisionForTypeRange"
            :disabled="item.disabled || false"
            @change="(val) => onChangeItem(val, { key: item.key, index: 1 })"
            @blur="(val) => onChangeItem(val, { key: item.key, index: 1 })"
          />
        </div>
      </div>
    </div>
    <div
      v-else-if="item.type === 'date-picker'"
      class="adb-filter-operation__date"
    >
      <div class="adb-filter-operation__date__content">
        <el-date-picker
          ref="picker"
          v-model="model"
          :type="item.date_options ? item.date_options.type : 'date'"
          align="right"
          format="MM/dd/yyyy"
          unlink-panels
          range-separator="-"
          :start-placeholder="$tc('adb-filter.startDate')"
          :end-placeholder="$tc('adb-filter.endDate')"
          :picker-options="
            $_.chain(item.date_options ? item.date_options.pickerOptions : {})
              .defaults(pickerOptions)
              .value()
          "
        />
      </div>
    </div>

    <div
      v-else-if="item.type === 'select'"
      class="adb-filter-operation__select"
    >
      <div class="adb-filter-operation__select__content">
        <el-select
          :ref="item.key"
          v-model="model"
          :placeholder="$tc('adb-filter.pleaseSelect')"
          @change="(val) => onChangeItem(val, { key: item.key })"
        >
          <el-option
            v-for="item in item.options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </div>
    </div>

    <div v-else class="adb-filter-operation__radio">
      <el-input
        v-if="item.options.length > 5"
        v-model="filterSearch"
        class="adb-filter-operation__search"
        :placeholder="`${$tc('adb-filter.searchBy')} ${item.label}`"
        clearable
      />

      <el-radio-group
        v-model="model"
        class="content-wrapper"
        @change="(val) => onChangeItem(val, { key: item.key })"
      >
        <el-radio
          v-for="op in listOptions"
          class="adb-filter-operation__radio__item"
          :key="op.value"
          :label="op.value"
        >
          <slot v-if="item.slot" name="optionItem" :option="op"></slot>
          <span v-else> {{ op.label }}</span>
        </el-radio>
      </el-radio-group>
    </div>
  </div>
</template>
<script>
import { resetItem } from '@adber/shipber-ui/utils/filters';
import commonMessage from '@adber/shipber-ui/packages/locale';

export default {
  name: 'adb-filter-operation',
  i18n: {
    sharedMessages: commonMessage,
  },
  props: {
    item: {
      type: Object,
      default: () => ({}),
      required: false,
    },
    value: {
      default: undefined,
      required: true,
    },
  },
  data() {
    return {
      filterSearch: '',
      model: this.$_.cloneDeep(this.value),
      pickerOptions: {
        shortcuts: [
          {
            text: this.$tc('adb-filter.lastWeek'),
            onClick: (picker) => this.getLastDateOfNum(picker, 7),
          },
          {
            text: this.$tc('adb-filter.lastMonth'),
            onClick: (picker) => this.getLastDateOfNum(picker, 30),
          },
          {
            text: this.$tc('adb-filter.last3Month'),
            onClick: (picker) => this.getLastDateOfNum(picker, 90),
          },
        ],
        onPick: (date_range) => {
          if (date_range.maxDate) {
            this.onChangeItem(
              [date_range.minDate, date_range.maxDate],
              this.item.key
            );
          }
        },
      },
    };
  },
  watch: {
    model: {
      handler(newVal) {
        if (newVal === null && this.item.type === 'date-picker') {
          newVal = resetItem(this.item.type);
        }
        if (this.$_.isEqual(newVal, this.value)) return;
        this.$emit('input', newVal);
      },
      deep: true,
    },
    value: {
      handler(newVal) {
        if (this.$_.isEqual(newVal, this.model)) return;
        this.model = this.$_.cloneDeep(newVal);
      },
      deep: true,
    },
  },
  computed: {
    isSelectAll: {
      get() {
        if (!this.listOptions.length) return false;
        return this.listOptions.every(
          (_opt) => this.model.indexOf(_opt.value) !== -1
        );
      },
      set(bool) {
        if (this.listOptions.length) {
          this.model = [];
          return;
        }
        this.model = bool ? this.listOptions.map((d) => d.value) : [];
      },
    },
    oneMinForTypeAmountRanage() {
      if (this.item.date_options) {
        return this.item.date_options.min != undefined
          ? this.item.date_options.min
          : -Infinity;
      }
      return -Infinity;
    },

    oneMaxForTypeAmountRange() {
      if (this.$_.isNil(this.model[1])) {
        return this.item.date_options && this.item.date_options.max != undefined
          ? this.item.date_options.max
          : Infinity;
      }
      return +this.model[1];
    },

    twoMinForTypeAmountRanage() {
      if (this.$_.isNil(this.model[0])) {
        return this.item.date_options && this.item.date_options.min != undefined
          ? this.item.date_options.min
          : -Infinity;
      }
      return +this.model[0];
    },

    twoMaxForTypeAmountRange() {
      if (this.item.date_options) {
        return this.item.date_options.max != undefined
          ? this.item.date_options.max
          : Infinity;
      }
      return Infinity;
    },

    placeholderForTypeRange() {
      let arrText = [];
      switch (this.item.type) {
        case 'amount-range':
          arrText = [
            this.$tc('adb-filter.minimumAmount'),
            this.$tc('adb-filter.maximumAmount'),
          ];
          break;
        case 'number-range':
          arrText = [
            this.$tc('adb-filter.minimumNumber'),
            this.$tc('adb-filter.maximumNumber'),
          ];
          break;
        default:
          break;
      }
      return arrText;
    },

    precisionForTypeRange() {
      let num = 0;
      switch (this.item.type) {
        case 'amount-range':
          num = 2;
          break;
        default:
          num = 0;
          break;
      }
      return num;
    },
    listOptions() {
      if (['checkbox', 'radio', 'select'].indexOf(this.item.type) === -1)
        return [];
      if (!this.filterSearch.length) return this.item.options;
      return this.item.options.filter(
        (d) => d.label.indexOf(this.filterSearch) !== -1
      );
    },
  },
  methods: {
    getLastDateOfNum(picker, num) {
      const today = this.$adbDayjs
        .dayjs(this.$adbDayjs.getDate(new Date()))
        .toISOString();
      const end = this.$adbDayjs.getEndingTimeOfDay(today);
      const start = this.$adbDayjs
        .dayjs(today)
        .subtract(num, 'd')
        .toISOString();
      picker.$emit('pick', [start, end]);
    },
    handleChangeAmount(val, option) {
      this.fnChange(option.key, { value: val, index: option.index });
    },
    handleChangeDate(date_range) {
      const start_date = date_range[0];
      // 结束日期设置为当天最后一秒
      const end_date = this.$adbDayjs.getEndingTimeOfDay(date_range[1]);
      return [start_date, end_date];
    },
    onChangeAll(value) {
      this.model = value ? this.listOptions.map((d) => d.value) : [];
    },
    onChangeItem(value, option) {
      const item = this.item;
      let data = value;
      switch (item.type) {
        case 'radio':
          data = value;
          break;
        case 'checkbox':
          data = value;
          break;
        case 'amount-range':
          data = { value, index: option.index };
          if (option.index === 1) {
            this.$emit('input', this.model);
          }
          break;
        case 'number-range':
          data = { value, index: option.index };
          if (option.index === 1) {
            this.$emit('input', this.model);
          }
          break;
        case 'date-picker':
          data = this.handleChangeDate(data);
          this.$nextTick(() => {
            this.model = data;
          });
          break;
        case 'select':
          data = value;
          break;
        default:
          break;
      }
      // reset bind key
      if (item.bind) {
        const keys = item.bind;
        // 兼容string and array
        const arrKeys = typeof keys === 'string' ? keys.split(',') : keys;
        arrKeys.forEach((key) => {
          this.$emit('bind', key);
        });
      }

      this.fnChange(option.key, data);
    },
    fnChange(key, value) {
      this.item.change && this.item.change(this.model, value);
    },
  },
};
</script>
<style lang="scss" scoped>
@import '~@adber/shipber-ui/packages/theme/scss/basic.scss';

.adb-filter-operation {
  &__select-all {
    margin-top: 20px;
    padding: 0 0 $shipber-num-L 0;
    border-bottom: 1px solid $shipber-border-color-2;
  }

  &__checkbox,
  &__radio {
    & > *:first-child {
      margin-top: 0;
    }
    .content-wrapper {
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: flex-start;
      max-height: 300px;
      overflow: auto;
      & > * {
        margin-top: $shipber-num-L;
      }
    }
  }
  &__amount-range,
  &__number-range {
    &__content {
      display: flex;
      justify-content: space-around;
      align-items: center;
      background: #ffffff;

      /deep/ .el-input {
        input {
          border: 0;
          padding: 0;
        }
      }

      > * {
        flex: 1 1 auto;
      }

      .min-amount-wrapper {
        display: flex;
        align-items: center;
        border-radius: 5px;
        border: 1px solid #c6cdd5;

        .amount-input {
          flex: 1 1 auto;
          width: 100%;
        }

        .min-amount__icon {
          margin-left: 12px;
          margin-right: 10px;
          color: #32363b;
        }
      }

      .center {
        margin: 0 8px;
        flex: 0 0 auto;
        color: #32363b;
      }
    }
  }

  &__date {
    &__content {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      & > * {
        width: 100%;
      }
    }
  }
  &__select {
    &__content {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      & > * {
        width: 100%;
      }
    }
  }
}
</style>
