<template>
  <div class="content-view">
    <div class="table-head-tool">
      <div class="table-title-row">
        <Button type="primary" @click="openEdit(null)">新增</Button>
      </div>

      <Form ref="formInline" :model="param.seachOption" inline :label-width="80">
        <FormItem label="条件">
          <Select v-model="param.seachOption.key" style="width: 140px">
            <Option value="mobile">手机</Option>
            <Option value="company_name">公司</Option>
            <Option value="status">状态</Option>
          </Select>
          <Input v-model="param.seachOption.value" placeholder="关键字" style="width: 220px" class="ml10" search
            @on-search="load(1)" />
        </FormItem>
        <FormItem>
          <Button type="primary" @click="load(1)">查询</Button>
          <Button type="default" @click="resetQuery" class="ml10">重置</Button>
          <Button type="default" @click="doExport" class="ml10">导出 CSV</Button>
        </FormItem>
      </Form>
    </div>

    <div class="table-body">
      <Table :columns="columns" :data="rows" border stripe />
      <div class="table-page-bar">
        <Page :total="total" :current="param.pageOption.page" :page-size="param.pageOption.pageSize" show-total
          @on-change="onPage" @on-page-size-change="onSize" />
      </div>
    </div>

    <Modal v-model="modal" :title="form.id ? '编辑用户' : '新增用户'" width="640" :loading="saving" @on-ok="save">
      <Form ref="formRef" :model="form" :rules="rules" :label-width="100">
        <FormItem label="名称" prop="name">
          <Input v-model="form.name" />
        </FormItem>
        <FormItem label="手机" prop="mobile">
          <Input v-model="form.mobile" />
        </FormItem>
        <FormItem label="邮箱">
          <Input v-model="form.email" />
        </FormItem>
        <FormItem label="公司">
          <Input v-model="form.company_name" />
        </FormItem>
        <FormItem label="状态" prop="status">
          <Select v-model="form.status" style="width: 100%">
            <Option value="active">正常</Option>
            <Option value="disabled">禁用</Option>
          </Select>
        </FormItem>
      </Form>
    </Modal>

    <Modal v-model="detailVisible" title="用户详情" width="800" footer-hide>
      <p v-if="detail" class="mb8">Token 数量：{{ detail.tokenCount }}</p>
      <p v-if="detail && detail.tokens && detail.tokens.length" class="sub-title">API Token</p>
      <Table
        v-if="detail && detail.tokens && detail.tokens.length"
        :columns="tokenCols"
        :data="detail.tokens"
        size="small"
        border
        highlight-row
        class="mb16"
        @on-row-click="onTokenRowClick"
      />
      <p v-if="detail && detail.subscriptions && detail.subscriptions.length" class="sub-title">订阅记录</p>
      <Table v-if="detail && detail.subscriptions" :columns="subCols" :data="detail.subscriptions" size="small"
        border />
    </Modal>

    <Modal v-model="tokenListVisible" :title="tokenListTitle" width="820" footer-hide>
      <p v-if="tokenListRows.length" class="text-muted mb8">点击表格某一行查看该 Token 详情（明文不可查，需重新创建）</p>
      <Table
        v-if="tokenListRows.length"
        :columns="tokenCols"
        :data="tokenListRows"
        size="small"
        border
        highlight-row
        @on-row-click="onTokenRowClick"
      />
      <p v-else class="text-muted">暂无 Token</p>
    </Modal>

    <Modal v-model="tokenDetailVisible" title="Token 详情" width="520" footer-hide>
      <div v-if="selectedToken" class="token-detail">
        <p><span class="label">ID</span>{{ selectedToken.id }}</p>
        <p><span class="label">名称</span>{{ selectedToken.token_name }}</p>
        <p><span class="label">用户</span>{{ selectedToken.user_id }}</p>
        <p><span class="label">套餐</span>{{ selectedToken.plan_id != null ? selectedToken.plan_id : '—' }}</p>
        <p><span class="label">状态</span>{{ selectedToken.status }}</p>
        <p><span class="label">过期时间</span>{{ selectedToken.expire_at || '—' }}</p>
        <p><span class="label">最后使用</span>{{ selectedToken.last_used_at || '—' }}</p>
      </div>
    </Modal>
  </div>
</template>

<script>
import userServer from '@/api/subscription/user_server.js'
import { downloadCsvFromRows } from '@/utils/csvExport.js'

export default {
  name: 'SubscriptionUsers',
  data() {
    return {
      rows: [],
      total: 0,
      param: {
        seachOption: { key: 'mobile', value: '' },
        pageOption: { page: 1, pageSize: 20, total: 0 },
      },
      modal: false,
      saving: false,
      form: {},
      rules: {
        name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
        status: [{ required: true, message: '请选择状态', trigger: 'change' }],
      },
      detailVisible: false,
      detail: null,
      tokenListVisible: false,
      tokenListRows: [],
      tokenListUserName: '',
      tokenDetailVisible: false,
      selectedToken: null,
      subCols: [
        { title: 'ID', key: 'id', width: 80 },
        { title: '套餐ID', key: 'plan_id', width: 90 },
        { title: '状态', key: 'status', width: 100 },
        { title: '开始', key: 'start_time', minWidth: 160 },
        { title: '结束', key: 'end_time', minWidth: 160 },
      ],
    }
  },
  computed: {
    columns() {
      return [
        { title: 'ID', key: 'id', width: 80 },
        { title: '名称', key: 'name', minWidth: 120 },
        { title: '手机', key: 'mobile', width: 130 },
        { title: '公司', key: 'company_name', minWidth: 140 },
        { title: '状态', key: 'status', width: 90 },
        {
          title: 'API Token',
          key: 'token_count',
          width: 130,
          render: (h, p) => {
            const n = p.row.token_count != null ? Number(p.row.token_count) : 0
            return h('div', [
              h('span', { class: { mr8: true } }, String(n)),
              h(
                'Button',
                {
                  props: { type: 'primary', size: 'small', ghost: true },
                  on: { click: () => this.openTokenList(p.row) },
                },
                '查看'
              ),
            ])
          },
        },
        {
          title: '操作',
          key: 'a',
          width: 380,
          render: (h, p) => {
            return h('div', [
              h(
                'Button',
                {
                  props: { type: 'info', size: 'small' },
                  on: { click: () => this.openEdit(p.row) },
                },
                '编辑'
              ),
              h(
                'Button',
                {
                  props: { type: 'default', size: 'small' },
                  class: { ml8: true },
                  on: { click: () => this.showDetail(p.row) },
                },
                '详情'
              ),
              p.row.status === 'disabled'
                ? h(
                    'Button',
                    {
                      props: { type: 'success', size: 'small' },
                      class: { ml8: true },
                      on: { click: () => this.doEnable(p.row) },
                    },
                    '启用'
                  )
                : h(
                    'Button',
                    {
                      props: { type: 'warning', size: 'small' },
                      class: { ml8: true },
                      on: { click: () => this.doDisable(p.row) },
                    },
                    '禁用'
                  ),
              h(
                'Button',
                {
                  props: { type: 'default', size: 'small' },
                  class: { ml8: true },
                  on: { click: () => this.revokeAllTokens(p.row) },
                },
                '吊销全部Token'
              ),
              h(
                'Button',
                {
                  props: { type: 'error', size: 'small' },
                  class: { ml8: true },
                  on: { click: () => this.doDel(p.row) },
                },
                '删除'
              ),
            ])
          },
        },
      ]
    },
    tokenCols() {
      return [
        { title: 'ID', key: 'id', width: 72 },
        { title: '名称', key: 'token_name', minWidth: 100 },
        { title: '套餐', key: 'plan_id', width: 80 },
        { title: '状态', key: 'status', width: 90 },
        { title: '过期', key: 'expire_at', minWidth: 150 },
        { title: '最后使用', key: 'last_used_at', minWidth: 150 },
      ]
    },
    tokenListTitle() {
      const name = this.tokenListUserName || ''
      return name ? `Token 列表 — ${name}` : 'Token 列表'
    },
  },
  mounted() {
    this.load(1)
  },
  methods: {
    async load(page) {
      if (page) this.param.pageOption.page = page
      const res = await userServer.page({ param: this.param })
      if (res && res.code === 0) {
        this.rows = res.data.rows || []
        this.total = res.data.count || 0
      } else {
        this.$Message.error((res && res.message) || '加载失败')
      }
    },
    onPage(p) {
      this.param.pageOption.page = p
      this.load()
    },
    onSize(s) {
      this.param.pageOption.pageSize = s
      this.load(1)
    },
    openEdit(row) {
      if (row) {
        this.form = { ...row }
      } else {
        this.form = { name: '', mobile: '', email: '', company_name: '', status: 'active' }
      }
      this.modal = true
    },
    save() {
      this.saving = true
      this.$refs.formRef.validate(async (ok) => {
        if (!ok) {
          this.saving = false
          return
        }
        try {
          const res = this.form.id
            ? await userServer.edit(this.form)
            : await userServer.add(this.form)
          if (res && res.code === 0) {
            this.$Message.success('保存成功')
            this.modal = false
            this.load(1)
          } else {
            this.$Message.error((res && res.message) || '保存失败')
          }
        } finally {
          this.saving = false
        }
      })
    },
    async showDetail(row) {
      const res = await userServer.detail(row.id)
      if (res && res.code === 0) {
        this.detail = res.data
        this.detailVisible = true
      } else {
        this.$Message.error((res && res.message) || '加载详情失败')
      }
    },
    async openTokenList(row) {
      const res = await userServer.detail(row.id)
      if (res && res.code === 0) {
        this.tokenListRows = res.data.tokens || []
        this.tokenListUserName = row.name || String(row.id)
        this.tokenListVisible = true
      } else {
        this.$Message.error((res && res.message) || '加载 Token 失败')
      }
    },
    onTokenRowClick(row) {
      this.selectedToken = row
      this.tokenDetailVisible = true
    },
    doDisable(row) {
      this.$Modal.confirm({
        title: '禁用用户',
        content: '确认禁用该用户？',
        onOk: async () => {
          const res = await userServer.disable({ id: row.id })
          if (res && res.code === 0) {
            this.$Message.success('已禁用')
            this.load(1)
          } else {
            this.$Message.error((res && res.message) || '操作失败')
          }
        },
      })
    },
    doEnable(row) {
      this.$Modal.confirm({
        title: '启用用户',
        content: '确认重新启用该用户？',
        onOk: async () => {
          const res = await userServer.enable({ id: row.id })
          if (res && res.code === 0) {
            this.$Message.success('已启用')
            this.load(1)
          } else {
            this.$Message.error((res && res.message) || '操作失败')
          }
        },
      })
    },
    doDel(row) {
      this.$Modal.confirm({
        title: '删除用户',
        content: '确认删除？若存在订阅/Token 可能受外键限制。',
        onOk: async () => {
          const res = await userServer.del({ id: row.id })
          if (res && res.code === 0) {
            this.$Message.success('已删除')
            this.load(1)
          } else {
            this.$Message.error((res && res.message) || '删除失败')
          }
        },
      })
    },
    async doExport() {
      const res = await userServer.exportRows({ param: this.param })
      if (res && res.code === 0 && res.data && res.data.rows) {
        downloadCsvFromRows(res.data.rows, 'users.csv')
        this.$Message.success('已导出')
      } else {
        this.$Message.error((res && res.message) || '导出失败')
      }
    },
    revokeAllTokens(row) {
      this.$Modal.confirm({
        title: '吊销全部 Token',
        content: '将吊销该用户下所有有效 Token，是否继续？',
        onOk: async () => {
          const res = await userServer.revokeAllTokens({ user_id: row.id })
          if (res && res.code === 0) {
            const n = (res.data && res.data.revoked) != null ? res.data.revoked : 0
            this.$Message.success('已吊销 ' + n + ' 条')
            this.load(1)
          } else {
            this.$Message.error((res && res.message) || '操作失败')
          }
        },
      })
    },
    resetQuery() {
      this.param.seachOption = { key: 'mobile', value: '' }
      this.load(1)
    },
  },
}
</script>

<style lang="less" scoped>
.content-view {
  width: 100%;
  max-width: 1720px;
  margin: 0 auto;
  padding: 26px 36px 36px;
  box-sizing: border-box;
}

.table-head-tool {
  margin-bottom: 16px;
}

.table-title-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-bottom: 12px;
}

.ml10 {
  margin-left: 10px;
}

.ml8 {
  margin-left: 8px;
}

.table-page-bar {
  margin-top: 12px;
  text-align: right;
}

.mb8 {
  margin-bottom: 8px;
}

.mb16 {
  margin-bottom: 16px;
}

.sub-title {
  font-weight: 600;
  margin: 10px 0 8px;
}

.text-muted {
  color: #808695;
}

.mr8 {
  margin-right: 8px;
}

.token-detail .label {
  display: inline-block;
  width: 88px;
  color: #808695;
}
</style>
