<template>
  <d2-container>
    <template #header>
      <div class="search-bar">
        <el-form :inline="true" size="mini">
          <el-form-item :label="$t(key('username'))">
            <el-input
              v-model="search.username"
              :placeholder="$t(key('enter_username'))"
              clearable
              style="width:200px"
              @keyup.enter.native="onSearch"
            />
          </el-form-item>
          <el-form-item :label="$t(key('full_name'))">
            <el-input
              v-model="search.nickname"
              :placeholder="$t(key('enter_name'))"
              clearable
              style="width:200px"
              @keyup.enter.native="onSearch"
            />
          </el-form-item>
          <el-form-item :label="$t(key('status'))">
            <el-select
              v-model="search.status"
              :placeholder="$t(key('select_status'))"
              clearable
              style="width:140px"
              @change="onSearch"
            >
              <el-option value="1" :label="$t(key('enable'))" />
              <el-option value="0" :label="$t(key('disable'))" />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-search" @click="onSearch">
              {{ $t(key('search')) }}
            </el-button>
            <el-button icon="el-icon-refresh" @click="onReset">
              {{ $t(key('reset')) }}
            </el-button>
          </el-form-item>
        </el-form>
      </div>
    </template>

    <page-table
      ref="pageTable"
      :columns="columns"
      :data="tableData"
      :loading="loading"
      :toolbar-buttons="toolbarButtons"
      :row-buttons="rowButtons"
      :pagination="pagination"
      auto-height
      @page-change="onPageChange"
      @selection-change="onSelect"
    >
      <template #col-status="{ row }">
        <span v-if="String(row.status) === '1'" style="color: #67c23a;">
          <i class="el-icon-circle-check" />
          {{ $t(key('enable')) }}
        </span>
        <span v-else style="color: #909399;">
          <i class="el-icon-circle-close" />
          {{ $t(key('disable')) }}
        </span>
      </template>
    </page-table>

    <page-dialog-form
      ref="dialogForm"
      :visible.sync="dialogVisible"
      :title="dialogTitle"
      width="35%"
      :form-cols="dialogFormCols"
      :form-data="formData"
      :rules="dialogRules"
      label-width="100px"
      :submitting="submitting"
      :confirm-text="key('confirm')"
      :cancel-text="key('cancel')"
      @submit="onDialogSubmit"
      @close="onDialogClose"
    />
  </d2-container>
</template>

<script>
import { useTableColumns } from '@/composables/useTableColumns'
import { useTableButtons } from '@/composables/useTableButtons'
import { i18nMixin } from '@/composables/useI18n'
import { getRoleAll } from '@/api/system-administration/role'
import {
  getUserList,
  createUser,
  editUser,
  deleteUser,
  batchDeleteUser,
  enableUser,
  disableUser,
  resetUserPwd
} from '@/api/system-administration/user'
import PageTable from '@/components/page-table'
import PageDialogForm from '@/components/page-dialog-form'

const ownUserId = () => localStorage.getItem('user_id')

export default {
  name: 'system-administration-user',
  components: { PageTable, PageDialogForm },
  mixins: [i18nMixin('page.system_administration.user_management.user')],
  data () {
    const key = this.key.bind(this)
    const $t = this.$t.bind(this)
    const normalizeList = res => {
      const data = res && res.data !== undefined ? res.data : res
      if (Array.isArray(data)) return data
      if (data && Array.isArray(data.list)) return data.list
      if (data && Array.isArray(data.data)) return data.data
      if (data && data.data && Array.isArray(data.data.data)) return data.data.data
      return []
    }
    const validateUsernameUnique = async (rule, value, callback) => {
      const username = String(value || '').trim()
      if (!username || username.length < 3) {
        callback()
        return
      }
      try {
        const res = await getUserList({ username, page_no: 1, page_size: 10000 })
        const exists = normalizeList(res).some(item => {
          const sameName = String(item.username || '') === username
          const sameUser = this.handleType === 'edit' && String(item.user_id) === String(this.editId)
          return sameName && !sameUser
        })
        callback(exists ? new Error($t(key('username_exists'))) : undefined)
      } catch {
        callback()
      }
    }
    const validatePasswordConfirm = (rule, value, callback) => {
      if (this.handleType === 'create' && value && value !== this.formData.password) {
        callback(new Error($t(key('password_not_match'))))
        return
      }
      callback()
    }
    return {
      loading: false,
      submitting: false,
      tableData: [],
      selectedRows: [],
      dialogVisible: false,
      dialogTitle: '',
      editId: '',
      handleType: 'create',
      search: { username: '', nickname: '', status: '' },
      pagination: { current: 1, size: 10, total: 0 },
      roleOptions: [],
      columns: [],
      toolbarButtons: [],
      rowButtons: [],
      formData: {
        username: '',
        password: '',
        password_confirm: '',
        role_id: '',
        nickname: '',
        pass_number: '',
        status: '1'
      },
      baseFormCols: {
        create: [
          [{ type: 'input', prop: 'username', label: key('username'), placeholder: key('enter_username'), clearable: true, style: { width: '90%' } }],
          [{ type: 'input', prop: 'password', inputType: 'password', label: key('password'), placeholder: key('enter_password'), clearable: true, showPassword: true, style: { width: '90%' } }],
          [{ type: 'input', prop: 'password_confirm', inputType: 'password', label: key('confirm_password'), placeholder: key('enter_confirm_password'), clearable: true, showPassword: true, style: { width: '90%' } }],
          [{ type: 'select', prop: 'role_id', label: key('user_group'), placeholder: key('select_user_group'), clearable: true, style: { width: '90%' }, options: [] }],
          [{ type: 'input', prop: 'nickname', label: key('full_name'), placeholder: key('enter_name'), clearable: true, style: { width: '90%' } }],
          [{ type: 'input', prop: 'pass_number', label: key('pass_number'), placeholder: key('enter_pass_number'), clearable: true, style: { width: '90%' } }],
          [{ type: 'select', prop: 'status', label: key('status'), clearable: false, style: { width: '90%' }, options: [{ value: '1', label: $t(key('enable')) }, { value: '0', label: $t(key('disable')) }] }]
        ],
        edit: [
          [{ type: 'input', prop: 'username', label: key('username'), placeholder: key('enter_username'), clearable: true, style: { width: '90%' } }],
          [{ type: 'select', prop: 'role_id', label: key('user_group'), placeholder: key('select_user_group'), clearable: true, style: { width: '90%' }, options: [] }],
          [{ type: 'input', prop: 'nickname', label: key('full_name'), placeholder: key('enter_name'), clearable: true, style: { width: '90%' } }],
          [{ type: 'input', prop: 'pass_number', label: key('pass_number'), placeholder: key('enter_pass_number'), clearable: true, style: { width: '90%' } }],
          [{ type: 'select', prop: 'status', label: key('status'), clearable: false, style: { width: '90%' }, options: [{ value: '1', label: $t(key('enable')) }, { value: '0', label: $t(key('disable')) }] }]
        ]
      },
      baseRules: {
        username: [
          { required: true, message: key('enter_username'), trigger: 'blur' },
          { min: 3, max: 20, message: key('username_length'), trigger: 'blur' },
          { validator: validateUsernameUnique, trigger: 'blur' }
        ],
        password: [
          { required: true, message: key('enter_password'), trigger: 'blur' },
          { min: 6, max: 64, message: key('password_length'), trigger: 'blur' }
        ],
        password_confirm: [
          { required: true, message: key('enter_confirm_password'), trigger: 'blur' },
          { min: 6, max: 64, message: key('password_length'), trigger: 'blur' },
          { validator: validatePasswordConfirm, trigger: ['blur', 'change'] }
        ],
        role_id: [
          { required: true, message: key('select_user_group'), trigger: 'change' }
        ],
        status: [
          { required: true, message: key('select_status'), trigger: 'change' }
        ]
      }
    }
  },
  computed: {
    dialogFormCols () {
      const cols = this.baseFormCols[this.handleType] || this.baseFormCols.create
      const roleIdx = this.handleType === 'create' ? 3 : 1
      if (cols[roleIdx] && cols[roleIdx][0]) {
        cols[roleIdx][0].options = this.roleOptions
      }
      return cols
    },
    dialogRules () {
      if (this.handleType === 'edit') {
        return {
          username: this.baseRules.username,
          role_id: this.baseRules.role_id,
          status: this.baseRules.status
        }
      }
      return this.baseRules
    }
  },
  created () {
    this.initRoleOptions()
    this.columns = useTableColumns([
      { prop: 'sort', label: this.key('index'), width: 80 },
      { prop: 'username', label: this.key('username'), minWidth: 120 },
      { prop: 'nickname', label: this.key('full_name'), minWidth: 100 },
      { prop: 'pass_number', label: this.key('pass_number'), minWidth: 120 },
      { prop: 'status', label: this.key('status'), slot: 'status', width: 100 },
      { prop: 'role_name', label: this.key('user_group'), minWidth: 100 },
      { prop: 'last_ip', label: this.key('login_ip'), width: 130 },
      { prop: 'create_time', label: this.key('last_login_time'), width: 160 },
      { prop: '_actions', label: this.key('actions'), width: 240, fixed: 'right' }
    ])
    const btns = useTableButtons({
      toolbar: [
        {
          key: 'add',
          label: this.key('add'),
          icon: 'el-icon-plus',
          type: 'primary',
          auth: '/system_settings/user_management/member/create',
          onClick: this.openAdd
        },
        {
          key: 'enable',
          label: this.key('enable'),
          icon: 'el-icon-check',
          type: 'success',
          auth: '/system_settings/user_management/member/enable',
          onClick: () => this.batchUpdateStatus(1)
        },
        {
          key: 'disable',
          label: this.key('disable'),
          icon: 'el-icon-close',
          type: 'warning',
          auth: '/system_settings/user_management/member/disable',
          onClick: () => this.batchUpdateStatus(0)
        },
        {
          key: 'batch_delete',
          label: this.key('batch_delete'),
          icon: 'el-icon-delete',
          type: 'danger',
          auth: '/system_settings/user_management/member/batch-delete',
          onClick: this.handleBatchDelete
        }
      ],
      row: [
        {
          key: 'edit',
          label: this.key('edit'),
          icon: 'el-icon-edit',
          auth: '/system_settings/user_management/member/edit',
          onClick: this.openEdit
        },
        {
          key: 'reset_pwd',
          label: this.key('reset_password'),
          icon: 'el-icon-refresh',
          auth: '/system_settings/user_management/member/reset-pwd',
          onClick: this.handleResetPwd
        },
        {
          key: 'delete',
          label: this.key('delete'),
          icon: 'el-icon-delete',
          color: 'danger',
          auth: '/system_settings/user_management/member/delete',
          onClick: this.handleDelete
        }
      ]
    }, this.$permission)
    this.toolbarButtons = btns.toolbarButtons
    this.rowButtons = btns.rowButtons
    this.fetchData()
  },
  methods: {
    async initRoleOptions () {
      try {
        const res = await getRoleAll()
        const data = this.normalizeResponse(res).list
        this.roleOptions = data.map(item => ({ value: item.id, label: item.name }))
      } catch { /* 忽略 */ }
    },
    normalizeResponse (res) {
      const getTotal = (source, fallback) => {
        if (!source) return fallback
        const total = source.count ?? source.total ?? source.total_count ?? source.record_count
        const value = Number(total)
        return Number.isNaN(value) ? fallback : value
      }
      const containers = [res, res && res.data, res && res.data && res.data.data].filter(Boolean)
      for (const item of containers) {
        if (Array.isArray(item)) {
          return { list: item, total: getTotal(res, item.length) }
        }
        const list = item.data || item.list || item.rows || item.records || item.items
        if (Array.isArray(list)) {
          return { list, total: getTotal(item, getTotal(res, list.length)) }
        }
      }
      return { list: [], total: 0 }
    },
    async fetchData () {
      this.loading = true
      try {
        const res = await getUserList({
          ...this.search,
          page_no: this.pagination.current,
          page_size: this.pagination.size
        })
        const data = this.normalizeResponse(res)
        this.tableData = data.list
        this.pagination.total = data.total
      } finally {
        this.loading = false
      }
    },
    onSearch () {
      this.pagination.current = 1
      this.fetchData()
    },
    onReset () {
      this.search = { username: '', nickname: '', status: '' }
      this.pagination.current = 1
      this.fetchData()
    },
    onPageChange (page) {
      this.pagination.current = page.current
      this.pagination.size = page.size
      this.fetchData()
    },
    onSelect (rows) {
      this.selectedRows = rows
    },
    resetForm () {
      this.formData = {
        username: '',
        password: '',
        password_confirm: '',
        role_id: '',
        nickname: '',
        pass_number: '',
        status: '1'
      }
      this.editId = ''
    },
    openAdd () {
      this.handleType = 'create'
      this.dialogTitle = this.key('add_title')
      this.$nextTick(() => {
        this.$refs.dialogForm && this.$refs.dialogForm.reset()
        this.resetForm()
        this.dialogVisible = true
      })
    },
    openEdit (row) {
      this.handleType = 'edit'
      this.dialogTitle = this.key('edit_title')
      this.editId = row.user_id
      this.formData = {
        username: row.username,
        role_id: row.role_id,
        nickname: row.nickname || '',
        pass_number: row.pass_number || '',
        status: String(row.status)
      }
      this.dialogVisible = true
    },
    async onDialogSubmit () {
      this.submitting = true
      try {
        if (this.handleType === 'create') {
          if (this.formData.password !== this.formData.password_confirm) {
            this.$message.error(this.$t(this.key('password_not_match')))
            return
          }
          await createUser(this.formData)
        } else {
          await editUser({ ...this.formData, id: this.editId })
        }
        this.$message.success(this.$t(this.key('operation_success')))
        this.dialogVisible = false
        this.fetchData()
      } finally {
        this.submitting = false
      }
    },
    onDialogClose () {
      this.resetForm()
    },
    batchUpdateStatus (status) {
      const uid = ownUserId()
      const rows = this.selectedRows.filter(row => String(row.user_id) !== uid)
      if (rows.length === 0 && this.selectedRows.length > 0) {
        this.$message.warning(this.$t(this.key('cannot_operate_self')))
        return
      }
      if (rows.length === 0) {
        this.$message.warning(this.$t(this.key('select_rows_first')))
        return
      }
      const ids = rows.map(row => row.user_id)
      this.$confirm(
        this.$t(this.key('confirm_execute')),
        this.$t(this.key('prompt')),
        {
          confirmButtonText: this.$t(this.key('confirm')),
          cancelButtonText: this.$t(this.key('cancel')),
          type: 'warning',
          closeOnClickModal: false
        }
      ).then(async () => {
        try {
          await (status === 1 ? enableUser({ id: ids, status }) : disableUser({ id: ids, status: 0 }))
          this.$message.success(this.$t(this.key('operation_success')))
          this.fetchData()
        } catch { /* 拦截器已处理 */ }
      }).catch(() => {})
    },
    async confirmAction (message, action) {
      try {
        await this.$confirm(
          this.$t(message),
          this.$t(this.key('prompt')),
          {
            confirmButtonText: this.$t(this.key('confirm')),
            cancelButtonText: this.$t(this.key('cancel')),
            type: 'warning',
            closeOnClickModal: false
          }
        )
      } catch {
        return false
      }
      await action()
      return true
    },
    async handleDelete (row) {
      if (String(row.user_id) === ownUserId()) {
        this.$message.warning(this.$t(this.key('cannot_delete_self')))
        return
      }
      const ok = await this.confirmAction(
        this.key('confirm_delete'),
        () => deleteUser({ id: [row.user_id] })
      )
      if (!ok) return
      this.$message.success(this.$t(this.key('operation_success')))
      this.pagination.current = Math.min(
        this.pagination.current,
        Math.ceil((this.pagination.total - 1) / this.pagination.size) || 1
      )
      this.fetchData()
    },
    async handleBatchDelete () {
      const uid = ownUserId()
      const rows = this.selectedRows.filter(row => String(row.user_id) !== uid)
      if (rows.length === 0 && this.selectedRows.length > 0) {
        this.$message.warning(this.$t(this.key('cannot_delete_self')))
        return
      }
      if (rows.length === 0) {
        this.$message.warning(this.$t(this.key('select_rows_first')))
        return
      }
      const ok = await this.confirmAction(
        this.key('confirm_batch_delete'),
        () => batchDeleteUser({ id: rows.map(row => row.user_id) })
      )
      if (!ok) return
      this.$message.success(this.$t(this.key('operation_success')))
      this.fetchData()
    },
    async handleResetPwd (row) {
      try {
        await this.$confirm(
          this.$t(this.key('confirm_reset_pwd')),
          this.$t(this.key('prompt')),
          {
            confirmButtonText: this.$t(this.key('confirm')),
            cancelButtonText: this.$t(this.key('cancel')),
            type: 'warning',
            closeOnClickModal: false
          }
        )
        await resetUserPwd({ id: row.user_id })
        this.$message.success(this.$t(this.key('operation_success')))
      } catch { /* 取消或失败 */ }
    }
  }
}
</script>

<style scoped>
.search-bar {
  padding: 10px 0;
}
/deep/ .el-form-item--mini.el-form-item {
  margin-bottom: 4px;
}
</style>
