<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import {
  Document, Download, EditPen, Key, Plus, Search, Upload,
} from '@element-plus/icons-vue'
import http, { apiErrorMessage } from '../api/http'
import { downloadApiFile, importExcel } from '../api/excel'

interface UserRow {
  id: string; userName: string; displayName: string; staffNumber?: string
  collegeId?: string; roles: string[]; isEnabled: boolean; lastLoginAt?: string
}
type DataScope = 'Self' | 'Class' | 'College' | 'All'
interface Role { name: string; description: string; dataScope: DataScope }

const users = ref<UserRow[]>([])
const roles = ref<Role[]>([])
const colleges = ref<any[]>([])
const loading = ref(false)
const importing = ref(false)
const fileInput = ref<HTMLInputElement>()
const dialogVisible = ref(false)
const roleDialogVisible = ref(false)
const passwordDialogVisible = ref(false)
const editingUser = ref<UserRow | null>(null)
const passwordUser = ref<UserRow | null>(null)
const editingRoles = ref<string[]>([])
const editingStaffNumber = ref('')
const editingCollegeId = ref<string>()
const keyword = ref('')
const roleFilter = ref<string>()
const collegeFilter = ref<string>()
const enabledFilter = ref<boolean>()
const loginFilter = ref<boolean>()
const page = ref(1)
const total = ref(0)
const pageSize = 20
const passwordForm = reactive({ newPassword: '', confirmPassword: '' })
const form = reactive({
  userName: '', displayName: '', password: '', staffNumber: '',
  collegeId: undefined as string | undefined, roles: [] as string[],
})
const scopePriority: Record<DataScope, number> = {
  Self: 0,
  Class: 1,
  College: 2,
  All: 3,
}
const scopeNames: Record<DataScope, string> = {
  Self: '本人数据',
  Class: '所带班级',
  College: '所属学院',
  All: '全校数据',
}
const editingScope = computed(() => {
  const values = roles.value
    .filter((role) => editingRoles.value.includes(role.name))
    .map((role) => role.dataScope)
  const effective = values.reduce<DataScope>(
    (current, value) =>
      scopePriority[value] > scopePriority[current] ? value : current,
    'Self',
  )
  return scopeNames[effective]
})
async function load(resetPage = false) {
  if (resetPage) page.value = 1
  loading.value = true
  try {
    const [userRes, roleRes, collegeRes] = await Promise.all([
      http.get('/users', {
        params: {
          page: page.value,
          pageSize,
          keyword: keyword.value.trim() || undefined,
          roleName: roleFilter.value,
          collegeId: collegeFilter.value,
          isEnabled: enabledFilter.value,
          hasLoggedIn: loginFilter.value,
        },
      }),
      http.get('/users/roles'),
      http.get('/base-data/colleges'),
    ])
    users.value = userRes.data.items
    total.value = userRes.data.total
    roles.value = roleRes.data
    colleges.value = collegeRes.data
    if (users.value.length === 0 && page.value > 1) {
      page.value--
      await load()
    }
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  } finally {
    loading.value = false
  }
}

async function downloadTemplate() {
  try {
    await downloadApiFile('/users/template', '用户与权限导入模板.xlsx')
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

async function exportRows() {
  try {
    await downloadApiFile('/users/export', '用户与权限.xlsx')
    ElMessage.success('用户与权限已导出')
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

function chooseImportFile() {
  fileInput.value?.click()
}

async function handleImport(event: Event) {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]
  input.value = ''
  if (!file) return
  importing.value = true
  try {
    const { data } = await importExcel('/users/import', file)
    ElMessage.success(`导入完成：新增 ${data.created} 个，更新 ${data.updated} 个`)
    await load()
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  } finally {
    importing.value = false
  }
}

function openCreate() {
  Object.assign(form, {
    userName: '', displayName: '', password: '', staffNumber: '',
    collegeId: undefined, roles: [],
  })
  dialogVisible.value = true
}

async function create() {
  try {
    await http.post('/users', form)
    ElMessage.success('账号已创建')
    dialogVisible.value = false
    await load()
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

async function setStatus(row: any) {
  try {
    await http.put(`/users/${row.id}/status`, { isEnabled: !row.isEnabled })
    ElMessage.success(row.isEnabled ? '账号已停用' : '账号已启用')
    await load()
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

function openRoleEditor(row: any) {
  editingUser.value = row
  editingRoles.value = [...row.roles]
  editingStaffNumber.value = row.staffNumber ?? ''
  editingCollegeId.value = row.collegeId
  roleDialogVisible.value = true
}

async function saveRoles() {
  if (!editingUser.value) return
  try {
    await http.put(`/users/${editingUser.value.id}/roles`, {
      staffNumber: editingStaffNumber.value,
      collegeId: editingCollegeId.value,
      roles: editingRoles.value,
    })
    ElMessage.success('角色与数据范围已更新')
    roleDialogVisible.value = false
    await load()
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

function openPasswordReset(row: any) {
  passwordUser.value = row
  Object.assign(passwordForm, { newPassword: '', confirmPassword: '' })
  passwordDialogVisible.value = true
}

async function resetPassword() {
  if (!passwordUser.value) return
  if (passwordForm.newPassword.length < 8) {
    ElMessage.warning('新密码至少需要 8 位。')
    return
  }
  if (passwordForm.newPassword !== passwordForm.confirmPassword) {
    ElMessage.warning('两次输入的密码不一致。')
    return
  }
  try {
    await http.put(`/users/${passwordUser.value.id}/password`, {
      newPassword: passwordForm.newPassword,
    })
    ElMessage.success(`已重置 ${passwordUser.value.displayName} 的密码`)
    passwordDialogVisible.value = false
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

onMounted(load)
</script>

<template>
  <div class="page-stack">
    <section class="page-intro">
      <div>
        <span class="section-kicker">IDENTITY & ACCESS</span>
        <h2>用户与权限</h2>
        <p>账号决定谁能进入系统，角色与学院范围决定能看到哪些数据。</p>
      </div>
      <el-button type="primary" :icon="Plus" @click="openCreate">创建账号</el-button>
    </section>

    <section class="data-card">
      <div class="table-toolbar">
        <el-input
          v-model="keyword"
          :prefix-icon="Search"
          clearable
          placeholder="搜索账号、姓名、工号或角色"
          @clear="load(true)"
          @keyup.enter="load(true)"
        />
        <el-select v-model="roleFilter" clearable placeholder="全部角色" @change="load(true)">
          <el-option v-for="role in roles" :key="role.name" :label="role.name" :value="role.name" />
        </el-select>
        <el-select v-model="collegeFilter" clearable placeholder="全部学院" @change="load(true)">
          <el-option v-for="college in colleges" :key="college.id" :label="college.name" :value="college.id" />
        </el-select>
        <el-select v-model="enabledFilter" clearable placeholder="全部账号状态" @change="load(true)">
          <el-option label="启用" :value="true" />
          <el-option label="停用" :value="false" />
        </el-select>
        <el-select v-model="loginFilter" clearable placeholder="全部登录情况" @change="load(true)">
          <el-option label="已登录过" :value="true" />
          <el-option label="从未登录" :value="false" />
        </el-select>
        <el-button :icon="Search" @click="load(true)">查询</el-button>
        <el-button :icon="Document" @click="downloadTemplate">下载模板</el-button>
        <el-button :icon="Upload" :loading="importing" @click="chooseImportFile">Excel 导入</el-button>
        <el-button :icon="Download" @click="exportRows">导出全部</el-button>
        <input
          ref="fileInput"
          class="visually-hidden"
          type="file"
          accept=".xlsx"
          @change="handleImport"
        />
        <span>共 {{ total }} 个账号</span>
      </div>
      <el-table
        v-loading="loading"
        :data="users"
      >
        <el-table-column prop="userName" label="账号" min-width="130" />
        <el-table-column prop="displayName" label="姓名" min-width="120" />
        <el-table-column prop="staffNumber" label="工号/学号" min-width="130">
          <template #default="{ row }">{{ row.staffNumber || '—' }}</template>
        </el-table-column>
        <el-table-column label="角色" min-width="220">
          <template #default="{ row }">
            <el-tag v-for="role in row.roles" :key="role" class="role-tag" effect="plain">{{ role }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="最后登录" min-width="170">
          <template #default="{ row }">{{ row.lastLoginAt ? new Date(row.lastLoginAt).toLocaleString() : '尚未登录' }}</template>
        </el-table-column>
        <el-table-column label="状态" width="90">
          <template #default="{ row }"><span class="table-status" :class="{ off: !row.isEnabled }">{{ row.isEnabled ? '启用' : '停用' }}</span></template>
        </el-table-column>
        <el-table-column label="操作" width="250" fixed="right">
          <template #default="{ row }">
            <el-button link type="primary" :icon="EditPen" @click="openRoleEditor(row)">
              调整角色
            </el-button>
            <el-button link type="primary" :icon="Key" @click="openPasswordReset(row)">
              重置密码
            </el-button>
            <el-button link :type="row.isEnabled ? 'danger' : 'primary'" @click="setStatus(row)">
              {{ row.isEnabled ? '停用' : '启用' }}
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        v-if="total > pageSize"
        v-model:current-page="page"
        :page-size="pageSize"
        :total="total"
        layout="total, prev, pager, next"
        class="table-pagination"
        @current-change="() => load()"
      />
    </section>

    <el-dialog v-model="dialogVisible" title="创建账号" width="540px">
      <el-form label-position="top" class="entity-form">
        <div class="form-grid">
          <el-form-item label="登录账号" required><el-input v-model="form.userName" /></el-form-item>
          <el-form-item label="姓名" required><el-input v-model="form.displayName" /></el-form-item>
        </div>
        <div class="form-grid">
          <el-form-item label="初始密码" required><el-input v-model="form.password" type="password" show-password /></el-form-item>
          <el-form-item label="工号/学号"><el-input v-model="form.staffNumber" /></el-form-item>
        </div>
        <el-form-item label="所属学院">
          <el-select v-model="form.collegeId" clearable>
            <el-option v-for="item in colleges" :key="item.id" :label="item.name" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="角色" required>
          <el-select v-model="form.roles" multiple>
            <el-option v-for="role in roles" :key="role.name" :label="`${role.name} · ${role.description}`" :value="role.name" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="create">创建账号</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="passwordDialogVisible" title="重置密码" width="460px">
      <div v-if="passwordUser" class="role-editor-summary">
        <strong>{{ passwordUser.displayName }}</strong>
        <span>{{ passwordUser.userName }}</span>
      </div>
      <el-alert
        :closable="false"
        type="warning"
        show-icon
        title="保存后旧密码立即失效，请通过安全渠道通知本人。"
      />
      <el-form label-position="top" class="entity-form password-reset-form">
        <el-form-item label="新密码" required>
          <el-input v-model="passwordForm.newPassword" type="password" show-password />
        </el-form-item>
        <el-form-item label="再次输入新密码" required>
          <el-input
            v-model="passwordForm.confirmPassword"
            type="password"
            show-password
            @keyup.enter="resetPassword"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="passwordDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="resetPassword">确认重置</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="roleDialogVisible" title="调整角色与数据范围" width="540px">
      <div v-if="editingUser" class="role-editor-summary">
        <strong>{{ editingUser.displayName }}</strong>
        <span>{{ editingUser.userName }} · {{ editingUser.staffNumber || '未关联工号/学号' }}</span>
      </div>
      <el-form label-position="top" class="entity-form">
        <div class="form-grid">
          <el-form-item label="工号/学号">
            <el-input v-model="editingStaffNumber" />
          </el-form-item>
          <el-form-item label="所属学院">
            <el-select v-model="editingCollegeId" clearable>
              <el-option
                v-for="item in colleges"
                :key="item.id"
                :label="item.name"
                :value="item.id"
              />
            </el-select>
          </el-form-item>
        </div>
        <el-form-item label="角色" required>
          <el-select v-model="editingRoles" multiple>
            <el-option
              v-for="role in roles"
              :key="role.name"
              :label="`${role.name} · ${role.description}`"
              :value="role.name"
            />
          </el-select>
        </el-form-item>
        <el-alert
          :closable="false"
          type="info"
          show-icon
          :title="`保存后有效范围：${editingScope}`"
          description="多角色账号自动采用最高数据范围。教师或学生角色要求账号的工号/学号能匹配对应档案。"
        />
      </el-form>
      <template #footer>
        <el-button @click="roleDialogVisible = false">取消</el-button>
        <el-button type="primary" :disabled="!editingRoles.length" @click="saveRoles">
          保存角色
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>
