<template>
  <view class="page">
    <NavBar title="人员管理" :showBack="true" @back="goBack" />

    <!-- 搜索 -->
    <view class="search-bar">
      <view class="search-box">
        <view class="search-icon">
          <view class="si-ring"></view>
          <view class="si-stem"></view>
        </view>
        <input
          class="search-input"
          v-model="keyword"
          placeholder="用户名 / 手机号"
          placeholder-class="search-ph"
          confirm-type="search"
          @confirm="handleSearch"
        />
      </view>
      <view class="search-btn" @click="handleSearch">
        <text class="search-btn-text">搜索</text>
      </view>
    </view>

    <!-- 统计 -->
    <view class="stats" v-if="statistics">
      <view class="stat-item">
        <text class="stat-num">{{ statistics.total || 0 }}</text>
        <text class="stat-label">总数</text>
      </view>
      <view class="stat-divider"></view>
      <view class="stat-item">
        <text class="stat-num active">{{ statistics.active || 0 }}</text>
        <text class="stat-label">启用</text>
      </view>
      <view class="stat-divider"></view>
      <view class="stat-item">
        <text class="stat-num disabled">{{ statistics.disabled || 0 }}</text>
        <text class="stat-label">停用</text>
      </view>
    </view>

    <!-- 列表 -->
    <scroll-view
      class="list-scroll"
      scroll-y
      @scrolltolower="loadMore"
      refresher-enabled
      :refresher-triggered="refreshing"
      @refresherrefresh="onRefresh"
    >
      <view class="card-set" v-if="staffList.length > 0">
        <view
          class="card"
          v-for="item in staffList"
          :key="item.id"
          @click="goForm(item.id)"
          @longpress="showActions(item)"
        >
          <view class="card-avatar" :class="item.status === 2 ? 'off' : ''">
            <text>{{ (item.realName || item.username || '?')[0] }}</text>
          </view>

          <view class="card-info">
            <view class="info-top">
              <text class="info-name">{{ item.realName || item.username }}</text>
              <view class="info-status" :class="item.status === 1 ? 'on' : 'off'">
                <view class="info-dot" :class="item.status === 1 ? 'on' : 'off'"></view>
                <text>{{ item.status === 1 ? '启用' : '停用' }}</text>
              </view>
            </view>
            <view class="info-sub">
              <text class="sub-username">@{{ item.username }}</text>
              <text class="sub-sep" v-if="item.phone">·</text>
              <text class="sub-phone" v-if="item.phone">{{ item.phone }}</text>
            </view>
            <view class="info-role" v-if="getRoleName(item.roleIds)">
              <text class="role-tag">{{ getRoleName(item.roleIds) }}</text>
            </view>
          </view>

          <view class="card-arrow">
            <view class="arr-inner"></view>
          </view>
        </view>
      </view>

      <!-- 加载更多 -->
      <view class="load-tip" v-if="loading">
        <view class="dot-row">
          <view class="pulse-dot"></view>
          <view class="pulse-dot"></view>
          <view class="pulse-dot"></view>
        </view>
      </view>

      <!-- 没有更多 -->
      <view class="end-tip" v-if="!hasMore && staffList.length > 0">
        <view class="end-line"></view>
        <text class="end-text">没有更多了</text>
        <view class="end-line"></view>
      </view>

      <!-- 空状态 -->
      <view class="empty" v-if="!loading && staffList.length === 0">
        <view class="empty-icon">
          <view class="empty-person">
            <view class="ep-head"></view>
            <view class="ep-body"></view>
          </view>
        </view>
        <text class="empty-title">暂无人员</text>
        <text class="empty-desc">点击右下角按钮新增管理员</text>
      </view>
    </scroll-view>

    <!-- 新增按钮 -->
    <view class="fab" @click="goForm()">
      <text class="fab-text">+</text>
    </view>

    <CustomTabBar />
  </view>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import NavBar from '@/components/NavBar.vue';
import CustomTabBar from '@/components/CustomTabBar.vue';
import {
  getStaffList,
  getStaffStatistics,
  deleteStaff,
  resetStaffPassword,
  updateStaff,
  getAllRoles,
  type StaffQuery,
  type RoleOption
} from '@/api/staff';

const staffList = ref<any[]>([]);
const loading = ref(false);
const hasMore = ref(true);
const page = ref(1);
const pageSize = 10;
const keyword = ref('');
const refreshing = ref(false);
const statistics = ref<any>(null);
const roleMap = ref<Record<string, string>>({});

const fetchRoles = async () => {
  try {
    const roles: RoleOption[] = await getAllRoles();
    roleMap.value = {};
    roles.forEach(r => {
      roleMap.value[String(r.id)] = r.name;
    });
  } catch (e) {
    // ignore
  }
};

const getRoleName = (roleIds: string): string => {
  if (!roleIds) return '';
  const ids = roleIds.split(',');
  return ids.map(id => roleMap.value[String(id)] || '').filter(Boolean).join('，');
};

const fetchList = async () => {
  if (loading.value) return;
  loading.value = true;
  try {
    const params: StaffQuery = { page: page.value, pageSize };
    if (keyword.value) {
      // 判断输入是手机号还是用户名
      if (/^1[3-9]\d{9}$/.test(keyword.value)) {
        params.phone = keyword.value;
      } else {
        params.username = keyword.value;
      }
    }
    const res = await getStaffList(params);
    if (page.value === 1) {
      staffList.value = res.list || [];
    } else {
      staffList.value = [...staffList.value, ...(res.list || [])];
    }
    hasMore.value = staffList.value.length < (res.total || 0);
  } catch (e) {
    // ignore
  } finally {
    loading.value = false;
    refreshing.value = false;
  }
};

const fetchStats = async () => {
  try {
    statistics.value = await getStaffStatistics();
  } catch (e) {
    // ignore
  }
};

const loadMore = () => {
  if (loading.value || !hasMore.value) return;
  page.value++;
  fetchList();
};

const onRefresh = () => {
  refreshing.value = true;
  page.value = 1;
  hasMore.value = true;
  fetchList();
  fetchStats();
};

const handleSearch = () => {
  page.value = 1;
  hasMore.value = true;
  fetchList();
};

const goForm = (id?: number) => {
  const url = id != null ? `/pages/staff/form?id=${id}` : '/pages/staff/form';
  uni.navigateTo({ url });
};

const goBack = () => {
  uni.navigateBack();
};

const showActions = (item: any) => {
  const isActive = item.status === 1;
  uni.showActionSheet({
    itemList: ['编辑信息', '重置密码', isActive ? '停用账号' : '启用账号', '删除人员'],
    itemColor: '#1E293B',
    success: (res) => {
      switch (res.tapIndex) {
        case 0:
          goForm(item.id);
          break;
        case 1:
          handleResetPassword(item);
          break;
        case 2:
          handleToggleStatus(item);
          break;
        case 3:
          handleDelete(item);
          break;
      }
    }
  });
};

const handleToggleStatus = (item: any) => {
  const newStatus = item.status === 1 ? 2 : 1;
  const actionText = newStatus === 2 ? '停用' : '启用';
  uni.showModal({
    title: '确认操作',
    content: `确认${actionText}人员「${item.realName || item.username}」？`,
    success: async (res) => {
      if (!res.confirm) return;
      try {
        await updateStaff({ id: item.id, status: newStatus } as any);
        uni.showToast({ title: `已${actionText}`, icon: 'success' });
        page.value = 1;
        fetchList();
        fetchStats();
      } catch (e) {
        uni.showToast({ title: '操作失败', icon: 'none' });
      }
    }
  });
};

const handleResetPassword = (item: any) => {
  uni.showModal({
    title: '重置密码',
    content: `确认重置「${item.realName || item.username}」的登录密码？\n密码将重置为默认值。`,
    success: async (res) => {
      if (!res.confirm) return;
      try {
        await resetStaffPassword(item.id, '123456');
        uni.showToast({ title: '密码已重置', icon: 'success' });
      } catch (e) {
        uni.showToast({ title: '操作失败', icon: 'none' });
      }
    }
  });
};

const handleDelete = (item: any) => {
  uni.showModal({
    title: '确认删除',
    content: `确认删除人员「${item.realName || item.username}」？\n删除后不可恢复。`,
    success: async (res) => {
      if (!res.confirm) return;
      try {
        await deleteStaff(item.id);
        uni.showToast({ title: '已删除', icon: 'success' });
        page.value = 1;
        fetchList();
        fetchStats();
      } catch (e) {
        uni.showToast({ title: '删除失败', icon: 'none' });
      }
    }
  });
};

onMounted(() => {
  fetchRoles();
  fetchList();
  fetchStats();
});
</script>

<style lang="scss" scoped>
// ====== Page ======
.page {
  height: 100vh;
  background: $bg-color-page;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

// ====== Search ======
.search-bar {
  display: flex;
  align-items: center;
  gap: 16rpx;
  padding: 20rpx 24rpx;
  background: $bg-color-card;
  flex-shrink: 0;
}

.search-box {
  flex: 1;
  display: flex;
  align-items: center;
  background: $bg-color-page;
  border-radius: 40rpx;
  padding: 14rpx 24rpx;
  height: 68rpx;
}

.search-icon {
  position: relative;
  width: 30rpx;
  height: 30rpx;
  margin-right: 14rpx;
  flex-shrink: 0;

  .si-ring {
    width: 22rpx; height: 22rpx;
    border: 3rpx solid $text-color-muted;
    border-radius: 50%;
    position: absolute; top: 0; left: 0;
  }
  .si-stem {
    width: 9rpx; height: 3rpx;
    background: $text-color-muted;
    border-radius: 2rpx;
    position: absolute; bottom: 3rpx; right: 2rpx;
    transform: rotate(45deg);
  }
}

.search-input {
  flex: 1;
  font-size: 28rpx;
  color: $text-color-primary;
}

.search-ph {
  color: $text-color-muted;
  font-size: 26rpx;
}

.search-btn {
  background: $primary-color;
  border-radius: 36rpx;
  padding: 14rpx 32rpx;
  flex-shrink: 0;
  transition: opacity 0.15s ease;
  &:active { opacity: 0.8; }

  .search-btn-text {
    font-size: 28rpx;
    color: $text-color-primary;
    font-weight: 500;
  }
}

// ====== Stats ======
.stats {
  display: flex;
  align-items: center;
  padding: 20rpx 32rpx;
  background: $bg-color-card;
  border-bottom: 1rpx solid $border-color-light;
  flex-shrink: 0;
}

.stat-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4rpx;
}

.stat-num {
  font-size: 32rpx;
  font-weight: 700;
  color: $text-color-primary;
  &.active { color: $success-color; }
  &.disabled { color: $text-color-muted; }
}

.stat-label {
  font-size: 22rpx;
  color: $text-color-muted;
}

.stat-divider {
  width: 1rpx;
  height: 36rpx;
  background: $border-color-light;
}

// ====== List ======
.list-scroll {
  flex: 1;
  height: 0;
}

.card-set {
  padding: 20rpx 24rpx;
  display: flex;
  flex-direction: column;
  gap: 14rpx;
}

// ====== Card ======
.card {
  display: flex;
  align-items: center;
  background: $bg-color-card;
  border-radius: 20rpx;
  padding: 24rpx;
  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
  transition: opacity 0.15s ease;
  gap: 18rpx;

  &:active { opacity: 0.7; }
}

.card-avatar {
  width: 72rpx;
  height: 72rpx;
  border-radius: 50%;
  background: $primary-color-bg;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;

  text {
    font-size: 32rpx;
    font-weight: 700;
    color: $primary-color-dark;
  }

  &.off {
    background: $bg-color-page;
    text { color: $text-color-placeholder; }
  }
}

.card-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.info-top {
  display: flex;
  align-items: center;
  gap: 12rpx;
}

.info-name {
  font-size: 30rpx;
  font-weight: 600;
  color: $text-color-primary;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.info-status {
  display: flex;
  align-items: center;
  gap: 6rpx;
  flex-shrink: 0;

  text { font-size: 22rpx; font-weight: 500; }

  &.on text { color: $success-color; }
  &.off text { color: $text-color-muted; }
}

.info-dot {
  width: 10rpx; height: 10rpx; border-radius: 50%;
  &.on { background: $success-color; }
  &.off { background: $text-color-placeholder; }
}

.info-sub {
  display: flex;
  align-items: center;
  gap: 6rpx;
}

.sub-username {
  font-size: 24rpx;
  color: $text-color-muted;
}

.sub-sep {
  font-size: 22rpx;
  color: $border-color;
}

.sub-phone {
  font-size: 24rpx;
  color: $text-color-secondary;
}

.info-role {
  display: flex;
  align-items: center;
}

.role-tag {
  font-size: 22rpx;
  color: $accent-color;
  background: $accent-color-bg;
  padding: 2rpx 12rpx;
  border-radius: 6rpx;
  font-weight: 500;
}

.card-arrow {
  width: 36rpx;
  height: 36rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;

  .arr-inner {
    width: 14rpx; height: 14rpx;
    border-top: 2rpx solid $text-color-placeholder;
    border-right: 2rpx solid $text-color-placeholder;
    transform: rotate(45deg);
  }
}

// ====== Load more ======
.load-tip {
  display: flex;
  justify-content: center;
  padding: 36rpx 0 20rpx;
}

.dot-row {
  display: flex;
  gap: 8rpx;
}

.pulse-dot {
  width: 9rpx; height: 9rpx;
  background: $text-color-placeholder;
  border-radius: 50%;
  animation: pulse 1.2s ease-in-out infinite;
  &:nth-child(2) { animation-delay: 0.2s; }
  &:nth-child(3) { animation-delay: 0.4s; }
}

@keyframes pulse {
  0%, 80%, 100% { transform: scale(0.5); opacity: 0.4; }
  40% { transform: scale(1); opacity: 1; }
}

// ====== End ======
.end-tip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16rpx;
  padding: 36rpx 0 20rpx;
}
.end-line { width: 44rpx; height: 1rpx; background: $border-color; }
.end-text { font-size: 24rpx; color: $text-color-muted; }

// ====== Empty ======
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 100rpx 0 60rpx;
  gap: 20rpx;
}

.empty-icon {
  width: 120rpx;
  height: 120rpx;
  border-radius: 50%;
  background: $bg-color-secondary;
  display: flex;
  align-items: center;
  justify-content: center;
}

.empty-person {
  position: relative;
  width: 40rpx;
  height: 48rpx;
  .ep-head {
    position: absolute; top: 0; left: 50%;
    transform: translateX(-50%);
    width: 18rpx; height: 18rpx;
    background: $text-color-placeholder;
    border-radius: 50%;
  }
  .ep-body {
    position: absolute; bottom: 0; left: 50%;
    transform: translateX(-50%);
    width: 34rpx; height: 20rpx;
    background: $text-color-placeholder;
    border-radius: 17rpx 17rpx 4rpx 4rpx;
  }
}

.empty-title { font-size: 28rpx; color: $text-color-secondary; font-weight: 500; }
.empty-desc { font-size: 24rpx; color: $text-color-muted; }

// ====== FAB ======
.fab {
  position: fixed;
  right: 40rpx;
  bottom: 240rpx;
  width: 96rpx;
  height: 96rpx;
  border-radius: 50%;
  background: $primary-color;
  box-shadow: 0 8rpx 24rpx rgba(255, 193, 7, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  transition: opacity 0.15s ease;

  &:active { opacity: 0.8; }

  .fab-text {
    font-size: 48rpx;
    color: $text-color-primary;
    font-weight: 300;
    line-height: 1;
    margin-top: -4rpx;
  }
}
</style>
