<template>
  <wrapper
    class="c-profile"
    fill
    margin
    background
  >
    <div class="l-flex__none l-flex--col center c-profile__header has-padding">
      <div
        class="o-avatar u-pointer"
        @click="onAvatarClick"
      >
        <i
          class="o-avatar__img"
          :style="avatarStyle"
        />
        <i class="o-avatar__upload el-icon-camera" />
        <input
          ref="upload"
          type="file"
          accept="image/*"
          style="display: none;"
          @change="onUpload"
        >
      </div>
      <div class="c-profile__name has-top-padding">{{ name }}</div>
      <div class="u-relative has-top-padding">
        <i class="el-icon-user" />
        {{ role }}
      </div>
    </div>
    <div
      v-loading="loading"
      class="l-flex__fill l-flex--col center"
    >
      <warning
        v-if="error"
        @click="getUserInfo"
      />
      <div
        v-else
        class="has-padding l-flex--col"
      >
        <div class="l-flex--row">
          <UserInfoItem
            v-if="user"
            key="phone"
            v-model="phone"
            type="phone"
            :initial="user.attributes.phone[0]"
            @update="changeAttribute('phone', phone, '更新手机号')"
          />
        </div>
        <div class="l-flex--row has-padding--v">
          <UserInfoItem
            v-if="user"
            key="email"
            v-model="email"
            type="email"
            :initial="user.email"
            @update="updateUser({email}, '更新邮箱')"
          />
        </div>
        <div class="l-flex--row center has-top-padding">
          <div class="o-app">
            <i class="o-icon wechat has-bg" />
            <template v-if="wechat">
              <div class="l-flex--row">
                <div class="c-sibling-item u-color--info light">已绑定</div>
                <div
                  class="c-sibling-item u-pointer"
                  @click="onClickWechat"
                >
                  解绑
                </div>
              </div>
            </template>
            <div
              v-else
              class="u-pointer"
              @click="onClickWechat"
            >
              绑定微信
            </div>
          </div>
          <div class="o-app">
            <i class="o-icon applet has-bg" />
            <template v-if="applet">
              <div class="l-flex--row">
                <div class="c-sibling-item u-color--info light">已绑定</div>
                <div
                  class="c-sibling-item u-pointer"
                  @click="onClickApplet"
                >
                  解绑
                </div>
              </div>
            </template>
            <div
              v-else
              class="u-pointer"
              @click="onClickApplet"
            >
              绑定小程序
            </div>
          </div>
        </div>
      </div>
    </div>
    <el-dialog
      :visible.sync="showQr"
      custom-class="c-preview"
      width="0"
      @close="onCloseQr"
    >
      <div class="c-wechat has-padding">
        <div class="l-flex--row center has-bottom-padding">
          <i class="c-sibling-item o-icon medium wechat has-bg" />
          <span class="c-sibling-item u-color--black u-bold">请使用微信扫一扫</span>
        </div>
        <div
          v-loading="qrOptions.loading"
          class="c-wechat__wrapper"
          :class="{ retry: qrOptions.retry }"
          @click="getQr"
        >
          <img
            class="c-wechat__qr"
            :src="qrOptions.qr"
          >
        </div>
      </div>
    </el-dialog>
  </wrapper>
</template>

<script>
import { mapGetters } from 'vuex'
import UserInfoItem from './components/UserInfoItem'
import {
  userinfo,
  updateUser,
  getTicket,
  getQrcode
} from '@/api/user'
import {
  validPhone,
  validEmail
} from '@/utils/validate'

export default {
  name: 'Profile',
  components: {
    UserInfoItem
  },
  data () {
    return {
      loading: true,
      error: false,
      user: {
        email: '',
        attributes: {
          phone: ['']
        }
      },
      avatar: '',
      phone: '',
      email: '',
      wechat: '',
      applet: '',
      showQr: false,
      qrType: 'wechatOptions',
      wechatOptions: {
        loading: false,
        retry: false,
        qr: null
      },
      appletOptions: {
        loading: false,
        retry: false,
        qr: null
      }
    }
  },
  computed: {
    ...mapGetters([
      'name',
      'isSuperAdmin',
      'isTenantAdmin',
      'isGroupAdmin'
    ]),
    avatarStyle () {
      const avatar = this.avatar
      return avatar ? { backgroundImage: `url("${avatar}")` } : null
    },
    qrOptions () {
      return this[this.qrType]
    },
    role () {
      if (this.isSuperAdmin) {
        return '超级管理员'
      }
      if (this.isTenantAdmin) {
        return '管理员'
      }
      if (this.isGroupAdmin) {
        return '主管'
      }
      return '员工'
    }
  },
  created () {
    this.$timer = null
    this.$checkTimer = null
    this.getUserInfo()
  },
  beforeDestroy () {
    clearTimeout(this.$timer)
    clearInterval(this.$checkTimer)
  },
  methods: {
    onAvatarClick () {
      this.$refs.upload.click()
    },
    onUpload (e) {
      const file = e.target.files[0]
      e.target.value = null
      if (file.size >= 1024 * 1024) {
        this.$message({
          type: 'warning',
          message: '请选择1M以下的图片'
        })
        return
      }
      const reader = new FileReader()
      reader.onload = () => {
        this.avatar = reader.result
      }
      reader.readAsDataURL(file)
    },
    getUserInfo () {
      this.loading = true
      this.error = false
      userinfo().then(
        this.setUserInfo,
        () => {
          this.error = true
        }
      ).finally(() => {
        this.loading = false
      })
    },
    setUserInfo (data) {
      if (!data.attributes) {
        data.attributes = {}
      }
      this.avatar = this.getOrCreateAttribute(data, 'avatar', '')
      this.phone = this.getOrCreateAttribute(data, 'phone', '')
      this.email = data.email ?? ''
      this.wechat = this.getOrCreateAttribute(data, 'wechat', '')
      this.user = data
      this.applet = this.getOrCreateAttribute(data, 'wechat-applet-openid', '')
    },
    getOrCreateAttribute (user, key, defaults = '') {
      if (!user.attributes[key]) {
        user.attributes[key] = [defaults]
      }
      return user.attributes[key][0]
    },
    updateUser (data, meesage) {
      return updateUser(this.user.id, data, meesage).then(() => {
        this.user = { ...this.user, ...data }
      })
    },
    changeAttribute (key, value, meesage) {
      if (this.user.attributes[key][0] !== value) {
        this.updateUser({
          attributes: {
            ...this.user.attributes,
            [key]: [value]
          }
        }, meesage).then(
          () => {
            this.user.attributes[key][0] = value
          },
          () => {
            this.resetAttribute(key)
          }
        )
      }
    },
    resetAttribute (key) {
      this[key] = this.user.attributes[key][0]
    },
    resetProp (key) {
      this[key] = this.user[key] ?? ''
    },
    onPhoneChange () {
      if (!this.phone) {
        this.$message({
          type: 'warning',
          message: '手机号不能为空'
        })
        this.resetAttribute('phone')
        return
      }
      if (!validPhone(this.phone)) {
        this.$message({
          type: 'warning',
          message: '手机号格式错误'
        })
        this.resetAttribute('phone')
        return
      }
      this.changeAttribute('phone', this.phone, '更新手机号')
    },
    onEmailChange () {
      if (!this.email) {
        this.$message({
          type: 'warning',
          message: '邮箱不能为空'
        })
        this.resetProp('email')
        return
      }
      if (!validEmail(this.email)) {
        this.$message({
          type: 'warning',
          message: '邮箱格式错误'
        })
        this.resetProp('email')
        return
      }
      this.updateUser({ email: this.email }, '更新邮箱').then(
        () => {
          this.user.email = this.email
        },
        () => {
          this.resetProp('email')
        }
      )
    },
    onClickWechat () {
      if (this.wechat) {
        this.$confirm(
          '解除绑定后将无法再收到消息推送',
          '解绑微信',
          { type: 'warning' }
        ).then(() => {
          this.changeAttribute('wechat', this.wechat = '', '解绑公众号')
        })
      } else {
        this.qrType = 'wechatOptions'
        this.showQr = true
        this.getQr()
      }
    },
    onClickApplet () {
      if (this.applet) {
        this.$confirm(
          '解除绑定后将无法使用小程序的功能',
          '解绑小程序',
          { type: 'warning' }
        ).then(
          () => {
            this.changeAttribute('wechat-applet-openid', this.applet = '', '解绑小程序')
          }
        )
      } else {
        this.qrType = 'appletOptions'
        this.showQr = true
        this.getQr()
      }
    },
    onCloseQr () {
      this.showQr = false
    },
    getQr () {
      const options = this.qrOptions
      if (options.loading || options.qr && !options.retry) {
        return
      }
      switch (this.qrType) {
        case 'wechatOptions':
          this.getWechatQr()
          break
        case 'appletOptions':
          this.getAppletQr()
          break
        default:
          break
      }
    },
    getWechatQr () {
      const options = this.wechatOptions
      if (!this.showQr || this.qrType !== 'wechatOptions') {
        options.qr = null
        return
      }
      options.loading = true
      options.retry = false
      clearTimeout(this.$timer)
      getTicket(this.user.id).then(
        ({ data }) => {
          if (!this.wechat) {
            try {
              const { expire_seconds, ticket } = JSON.parse(data)
              options.checking = true
              options.qr = `https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=${ticket}`
              // 提前10秒重新获取
              this.$timer = setTimeout(this.getWechatQr, (expire_seconds > 10 ? expire_seconds - 10 : expire_seconds) * 1000)
              this.checkBind()
            } catch (e) {
              console.warn(e)
              options.retry = true
            }
          }
        },
        () => {
          if (!this.wechat) {
            options.retry = true
          }
        }
      ).finally(() => {
        options.loading = false
      })
    },
    getAppletQr () {
      const options = this.appletOptions
      options.loading = true
      options.retry = false
      getQrcode({ page: 'pages/otp/otp' }).then(
        ({ data }) => {
          options.checking = true
          options.qr = `data:image/png;base64,${data}`
          this.checkBind()
        },
        () => {
          options.retry = true
        }
      ).finally(() => {
        options.loading = false
      })
    },
    checkBind () {
      if (!this.$checkTimer) {
        this.$checkTimer = setInterval(this.check, 2000)
      }
    },
    check () {
      userinfo(true).then(data => {
        let bound = false
        let needCheck = false
        if (this.wechatOptions.checking) {
          const wechat = data.attributes.wechat?.[0]
          if (wechat) {
            bound = true
            this.wechatOptions.checking = false
            this.$message({
              type: 'success',
              message: '绑定公众号成功'
            })
            clearTimeout(this.$timer)
            this.wechatOptions.qr = null
            if (this.qrType === 'wechatOptions') {
              this.onCloseQr()
            }
          } else {
            needCheck = true
          }
        }
        if (this.appletOptions.checking) {
          const applet = data.attributes['wechat-applet-openid']?.[0]
          if (applet) {
            bound = true
            this.appletOptions.checking = false
            this.$message({
              type: 'success',
              message: '绑定小程序成功'
            })
            this.appletOptions.qr = null
            if (this.qrType === 'appletOptions') {
              this.onCloseQr()
            }
          } else {
            needCheck = true
          }
        }
        if (bound) {
          this.setUserInfo(data)
        }
        if (!needCheck) {
          clearInterval(this.$checkTimer)
          this.$checkTimer = null
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.c-profile {
  overflow: hidden;

  &__header {
    color: #fff;
    line-height: 1;
    background-color: $blue;
  }

  &__name {
    font-size: 20px;
  }
}

.o-avatar {
  display: inline-block;
  position: relative;
  width: 80px;
  height: 80px;
  padding: 2px;
  border-radius: 50%;
  background-color: #fff;

  &__img {
    display: inline-block;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background: url("~@/assets/icon_avatar.png") 0 0 / 100% 100% no-repeat;
  }

  &__upload {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    right: 0;
    bottom: 0;
    width: 26px;
    height: 26px;
    color: $blue;
    border-radius: 50%;
    background-color: #fff;
  }
}

.el-icon-user {
  position: absolute;
  left: -32px;
}

.o-app {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 128px;
  color: $blue;
  font-size: 16px;

  .o-icon {
    margin-bottom: $spacing;
  }
}

.o-icon {
  &.wechat {
    background-image: url("~@/assets/icon_wechat.png");
  }

  &.applet {
    background-image: url("~@/assets/icon_applet.png");
  }
}

.c-wechat {
  border-radius: $radius;
  background-color: #fff;

  &__wrapper {
    position: relative;
    width: 240px;
    height: 240px;

    &.retry::after {
      content: "点击重试";
      display: inline-flex;
      justify-content: center;
      align-items: center;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      color: $black;
      font-weight: bold;
      background-color: rgba(#fff, 0.8);
      cursor: pointer;
    }
  }

  &__qr {
    display: inline-block;
    width: 100%;
    height: 100%;
  }
}
</style>
