<!--
  邀请入群页

  设计系统：design-system/echochat/MASTER.md
  色板：Primary #2563EB / BG #F8FAFC / Surface #F1F5F9 / Text #1E293B
  功能：好友列表多选（排除已在群内的成员）、搜索过滤、已选展示、确认邀请
-->
<template>
  <view class="page-wrapper">
    <!-- 已选好友展示区 -->
    <view v-if="selectedList.length > 0" class="section">
      <view class="section-header">
        <text class="section-title">已选好友（{{ selectedList.length }}）</text>
      </view>
      <scroll-view class="selected-scroll" scroll-x>
        <view class="selected-list">
          <view
            v-for="friend in selectedList"
            :key="friend.user_id"
            class="selected-item"
            @tap="toggleSelect(friend)"
          >
            <view class="selected-avatar" :style="{ backgroundColor: getAvatarColor(friend.nickname || friend.username) }">
              <text class="selected-avatar-text">{{ getInitial(friend.nickname || friend.username) }}</text>
              <view class="selected-remove">
                <text class="selected-remove-text">×</text>
              </view>
            </view>
            <text class="selected-name">{{ friend.remark || friend.nickname || friend.username }}</text>
          </view>
        </view>
      </scroll-view>
    </view>

    <!-- 搜索成员 -->
    <view class="section">
      <view class="section-header">
        <text class="section-title">选择成员</text>
      </view>
      <view class="search-bar">
        <uni-icons type="search" size="18" color="#94A3B8" />
        <input
          class="search-input"
          v-model="searchKeyword"
          placeholder="搜索好友或用户名"
          placeholder-style="color: #94A3B8"
        />
        <view v-if="searchKeyword" class="search-clear" @tap="searchKeyword = ''">
          <uni-icons type="clear" size="16" color="#94A3B8" />
        </view>
      </view>
    </view>

    <!-- 好友列表 -->
    <view v-if="loading" class="skeleton-list">
      <view v-for="i in 5" :key="i" class="skeleton-item">
        <view class="skeleton-check"></view>
        <view class="skeleton-avatar"></view>
        <view class="skeleton-info">
          <view class="skeleton-line skeleton-line--name"></view>
        </view>
      </view>
    </view>

    <view v-else-if="availableFriends.length > 0" class="friend-list">
      <view
        v-for="friend in availableFriends"
        :key="friend.user_id"
        class="friend-item"
        @tap="toggleSelect(friend)"
      >
        <view class="checkbox" :class="{ 'checkbox--checked': isSelected(friend.user_id) }">
          <text v-if="isSelected(friend.user_id)" class="checkbox-icon">✓</text>
        </view>
        <view class="avatar" :style="{ backgroundColor: getAvatarColor(friend.nickname || friend.username) }">
          <text class="avatar-text">{{ getInitial(friend.nickname || friend.username) }}</text>
        </view>
        <view class="friend-info">
          <text class="friend-name">{{ friend.remark || friend.nickname || friend.username }}</text>
          <text v-if="friend.remark" class="friend-account">{{ friend.nickname || friend.username }}</text>
        </view>
      </view>
    </view>

    <view v-else class="empty-state">
      <text class="empty-text">{{ searchKeyword ? '未找到匹配的好友' : '没有可邀请的好友' }}</text>
    </view>

    <!-- 搜索到的非好友用户 -->
    <view v-if="showSearchSection" class="section" style="margin-top: 16rpx;">
      <view class="section-header">
        <text class="section-title">搜索到的其他用户</text>
      </view>
      <view v-if="searching" class="loading-tip">
        <text class="loading-tip-text">搜索中...</text>
      </view>
      <view v-else-if="nonFriendResults.length > 0" class="friend-list">
        <view
          v-for="user in nonFriendResults"
          :key="user.id"
          class="friend-item"
          @tap="toggleSelect(user)"
        >
          <view class="checkbox" :class="{ 'checkbox--checked': isSelected(user.id) }">
            <text v-if="isSelected(user.id)" class="checkbox-icon">✓</text>
          </view>
          <view class="avatar" :style="{ backgroundColor: getAvatarColor(user.nickname || user.username) }">
            <text class="avatar-text">{{ getInitial(user.nickname || user.username) }}</text>
          </view>
          <view class="friend-info">
            <text class="friend-name">{{ user.nickname || user.username }}</text>
            <text class="friend-account">@{{ user.username }}</text>
          </view>
          <text class="non-friend-tag">非好友</text>
        </view>
      </view>
      <view v-else class="empty-state">
        <text class="empty-text">未找到其他匹配用户</text>
      </view>
    </view>

    <!-- 底部占位 -->
    <view class="bottom-spacer"></view>

    <!-- 底部固定邀请按钮 -->
    <view class="bottom-bar">
      <view
        class="invite-btn"
        :class="{ 'invite-btn--disabled': selectedList.length === 0 || submitting }"
        @tap="handleInvite"
      >
        <text class="invite-btn-text">
          {{ submitting ? '邀请中...' : `确认邀请${selectedList.length > 0 ? '（' + selectedList.length + '人）' : ''}` }}
        </text>
      </view>
    </view>
  </view>
</template>

<script>
import { ref, computed, watch } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { useContactStore } from '@/store/contact'
import { useGroupStore } from '@/store/group'
import userApi from '@/api/user'
import { getAvatarColor, getInitial } from '@/utils/avatar'

export default {
  name: 'GroupInvite',
  setup() {
    const contactStore = useContactStore()
    const groupStore = useGroupStore()

    const groupId = ref(0)
    const searchKeyword = ref('')
    const selectedMap = ref({})
    const loading = ref(true)
    const submitting = ref(false)
    const searchedUsers = ref([])
    const searching = ref(false)
    let searchTimer = null

    /** 已在群内的成员 ID 集合 */
    const memberIdSet = computed(() => {
      const set = new Set()
      for (const m of groupStore.currentMembers) {
        set.add(m.user_id)
      }
      return set
    })

    /** 好友 ID 集合 */
    const friendIdSet = computed(() => new Set(contactStore.friendList.map(f => f.user_id)))

    /** 过滤掉已在群内的好友 + 搜索关键词过滤 */
    const availableFriends = computed(() => {
      const filtered = contactStore.friendList.filter(f => !memberIdSet.value.has(f.user_id))
      const kw = searchKeyword.value.trim().toLowerCase()
      if (!kw) return filtered
      return filtered.filter(f => {
        const nickname = (f.nickname || '').toLowerCase()
        const username = (f.username || '').toLowerCase()
        const remark = (f.remark || '').toLowerCase()
        return nickname.includes(kw) || username.includes(kw) || remark.includes(kw)
      })
    })

    /** 搜索到的非好友、非群成员用户 */
    const nonFriendResults = computed(() => {
      return searchedUsers.value.filter(u => !friendIdSet.value.has(u.id) && !memberIdSet.value.has(u.id))
    })

    /** 是否显示全站搜索区块 */
    const showSearchSection = computed(() => {
      return searchKeyword.value.trim().length > 0 && (nonFriendResults.value.length > 0 || searching.value)
    })

    /** 已选中的用户列表 */
    const selectedList = computed(() => Object.values(selectedMap.value))

    /** 判断用户是否已选中 */
    const isSelected = (userId) => {
      return !!selectedMap.value[userId]
    }

    /** 切换用户选中状态 */
    const toggleSelect = (friend) => {
      const newMap = { ...selectedMap.value }
      const uid = friend.user_id || friend.id
      if (newMap[uid]) {
        delete newMap[uid]
      } else {
        newMap[uid] = {
          user_id: uid,
          nickname: friend.nickname || friend.username || '',
          username: friend.username || '',
          remark: friend.remark || '',
          avatar: friend.avatar || ''
        }
      }
      selectedMap.value = newMap
    }

    /** 搜索关键词变化时延迟搜索全站用户 */
    watch(searchKeyword, (val) => {
      if (searchTimer) clearTimeout(searchTimer)
      const kw = val.trim()
      if (kw.length < 2) {
        searchedUsers.value = []
        return
      }
      searchTimer = setTimeout(async () => {
        searching.value = true
        try {
          const res = await userApi.searchUsers(kw, 1, 20)
          searchedUsers.value = res.data?.list || []
        } catch {
          searchedUsers.value = []
        }
        searching.value = false
      }, 400)
    })

    /** 提交邀请 */
    const handleInvite = async () => {
      if (selectedList.value.length === 0 || submitting.value) return

      submitting.value = true
      try {
        const userIds = selectedList.value.map(f => f.user_id || f.id)
        await groupStore.inviteMembers(groupId.value, userIds)

        uni.showToast({ title: '邀请成功', icon: 'success' })

        setTimeout(() => {
          uni.navigateBack()
        }, 500)
      } catch (e) {
        console.error('邀请入群失败', e)
        uni.showToast({
          title: e?.message || '邀请失败',
          icon: 'none'
        })
      } finally {
        submitting.value = false
      }
    }

    // ==================== 生命周期 ====================

    onLoad(async (query) => {
      groupId.value = parseInt(query.groupId) || 0

      try {
        const tasks = [contactStore.fetchFriends()]
        if (groupId.value) {
          tasks.push(groupStore.fetchMembers(groupId.value))
        }
        await Promise.all(tasks)
      } catch (e) {
        console.error('加载数据失败', e)
      }
      loading.value = false
    })

    return {
      searchKeyword,
      selectedList,
      availableFriends,
      nonFriendResults,
      showSearchSection,
      searching,
      loading,
      submitting,
      isSelected,
      toggleSelect,
      handleInvite,
      getAvatarColor,
      getInitial
    }
  }
}
</script>

<style scoped>
.page-wrapper {
  min-height: 100vh;
  background-color: #F8FAFC;
  padding-bottom: env(safe-area-inset-bottom);
}

/* 区块通用 */
.section {
  margin-bottom: 16rpx;
}

.section-header {
  padding: 20rpx 32rpx 12rpx;
}

.section-title {
  font-size: 26rpx;
  color: #94A3B8;
  font-weight: 500;
}

/* 已选好友区 */
.selected-scroll {
  white-space: nowrap;
  background-color: #FFFFFF;
  padding: 20rpx 32rpx;
}

.selected-list {
  display: flex;
  gap: 24rpx;
}

.selected-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100rpx;
  flex-shrink: 0;
}

.selected-avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.selected-avatar-text {
  font-size: 32rpx;
  color: #FFFFFF;
  font-weight: 600;
}

.selected-remove {
  position: absolute;
  top: -6rpx;
  right: -6rpx;
  width: 32rpx;
  height: 32rpx;
  border-radius: 50%;
  background-color: #EF4444;
  display: flex;
  align-items: center;
  justify-content: center;
}

.selected-remove-text {
  font-size: 20rpx;
  color: #FFFFFF;
  font-weight: 600;
  line-height: 1;
}

.selected-name {
  font-size: 22rpx;
  color: #475569;
  margin-top: 8rpx;
  max-width: 100rpx;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
}

/* 搜索栏 */
.search-bar {
  display: flex;
  align-items: center;
  background-color: #FFFFFF;
  padding: 0 24rpx;
  height: 80rpx;
  gap: 12rpx;
}

.search-input {
  flex: 1;
  font-size: 28rpx;
  color: #1E293B;
  height: 80rpx;
}

.search-clear {
  flex-shrink: 0;
  padding: 8rpx;
}

/* 骨架屏 */
.skeleton-list {
  background-color: #FFFFFF;
}

.skeleton-item {
  display: flex;
  align-items: center;
  padding: 20rpx 32rpx;
  gap: 20rpx;
  border-bottom: 1rpx solid #F1F5F9;
}

.skeleton-check {
  width: 40rpx;
  height: 40rpx;
  border-radius: 8rpx;
  background: linear-gradient(90deg, #F1F5F9 25%, #E2E8F0 50%, #F1F5F9 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  flex-shrink: 0;
}

.skeleton-avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  background: linear-gradient(90deg, #F1F5F9 25%, #E2E8F0 50%, #F1F5F9 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  flex-shrink: 0;
}

.skeleton-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 10rpx;
}

.skeleton-line {
  border-radius: 8rpx;
  background: linear-gradient(90deg, #F1F5F9 25%, #E2E8F0 50%, #F1F5F9 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

.skeleton-line--name {
  width: 40%;
  height: 28rpx;
}

@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* 好友列表 */
.friend-list {
  background-color: #FFFFFF;
}

.friend-item {
  display: flex;
  align-items: center;
  padding: 20rpx 32rpx;
  border-bottom: 1rpx solid #F1F5F9;
  gap: 20rpx;
  cursor: pointer;
  transition: background-color 150ms ease;
}

.friend-item:active {
  background-color: #F8FAFC;
}

.friend-item:last-child {
  border-bottom: none;
}

/* 复选框 */
.checkbox {
  width: 40rpx;
  height: 40rpx;
  border-radius: 8rpx;
  border: 2rpx solid #CBD5E1;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: all 200ms ease;
}

.checkbox--checked {
  background-color: #2563EB;
  border-color: #2563EB;
}

.checkbox-icon {
  font-size: 24rpx;
  color: #FFFFFF;
  font-weight: 700;
  line-height: 1;
}

/* 头像 */
.avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.avatar-text {
  font-size: 32rpx;
  color: #FFFFFF;
  font-weight: 600;
}

/* 好友信息 */
.friend-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4rpx;
  min-width: 0;
}

.friend-name {
  font-size: 30rpx;
  color: #1E293B;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.friend-account {
  font-size: 24rpx;
  color: #94A3B8;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.non-friend-tag {
  color: #D97706;
  font-size: 22rpx;
  background-color: #FFFBEB;
  padding: 2rpx 12rpx;
  border-radius: 8rpx;
}

.loading-tip {
  padding: 40rpx 0;
  display: flex;
  justify-content: center;
}

.loading-tip-text {
  font-size: 26rpx;
  color: #94A3B8;
}

/* 空状态 */
.empty-state {
  padding: 80rpx 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.empty-text {
  font-size: 28rpx;
  color: #94A3B8;
}

/* 底部占位 */
.bottom-spacer {
  height: 140rpx;
}

/* 底部固定按钮 */
.bottom-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 16rpx 32rpx;
  padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
  background-color: #FFFFFF;
  box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.04);
}

.invite-btn {
  height: 88rpx;
  border-radius: 16rpx;
  background-color: #2563EB;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: opacity 200ms ease;
}

.invite-btn:active {
  opacity: 0.85;
}

.invite-btn--disabled {
  background-color: #CBD5E1;
  pointer-events: none;
}

.invite-btn-text {
  font-size: 30rpx;
  color: #FFFFFF;
  font-weight: 600;
}
</style>
