<script setup lang="ts">
import { ref, onMounted, h } from 'vue'
import { useRouter } from 'vue-router'
import { NCard, NDataTable, NButton, NInput, NTag, NModal, NForm, NFormItem, NSelect, NPopconfirm, NEmpty, NSkeleton, NAlert, NTabPane, NTabs, NIcon, NPagination, type FormRules } from 'naive-ui'
import { AddOutline, PersonAddOutline, SendOutline } from '@vicons/ionicons5'
import { api } from '../../api/client'
import { useAuthStore } from '../../stores/auth'
import { useToast } from '../../composables/useToast'
import { trackAction } from '../../composables/useAnalytics'
import { toBeijingDate, toBeijingDateTime, relativeTime } from '../../utils/date'

const router = useRouter()

const auth = useAuthStore()
const toast = useToast()

interface Member { id: string; display_name: string; email: string; title: string; role: string; joined_at: string; [key: string]: unknown }
interface Invitation { id: string; email: string; role: string; status: string; expires_at: string; [key: string]: unknown }
interface SharedFolder { id: string; name: string; description: string | null; color: string; article_count: number; created_at: string; [key: string]: unknown }
interface Activity { type: string; user_id: string; user_name: string; detail: string; created_at: string; [key: string]: unknown }
interface Ranking { user_id: string; display_name: string; title: string | null; saved_count: number; [key: string]: unknown }

const members = ref<Member[]>([])
const invitations = ref<Invitation[]>([])
const folders = ref<SharedFolder[]>([])
const activities = ref<Activity[]>([])
const rankings = ref<Ranking[]>([])
const loading = ref(true)
const activeTab = ref('members')

// ── 审计 tab ──
const memberStats = ref<any[]>([])
const auditItems = ref<any[]>([])
const auditTotal = ref(0)
const auditLoading = ref(false)
const auditPage = ref(1)
const auditType = ref<string | null>(null)
const auditUserId = ref<string | null>(null)
const auditDays = ref(7)

const activityTypeColors: Record<string, string> = {
  page_view: '#2080f0', search: '#f0a020', view_literature: '#18a058',
  save_literature: '#7c4dff', export: '#d03050', browse_cancer: '#eb2f96',
  browse_journals: '#13c2c2', click_tag: '#fa8c16',
}
const activityTypeLabels: Record<string, string> = {
  page_view: '页面访问', search: '搜索', view_literature: '查看文献',
  save_literature: '收藏文献', export: '导出', browse_cancer: '浏览癌种',
  browse_journals: '浏览期刊', click_tag: '点击标签',
}
const inviteLoading = ref(false)
const folderLoading = ref(false)
const showInvite = ref(false)
const inviteForm = ref({ email: '', role: 'viewer' })
const inviteFormRef = ref()
const inviteRules: FormRules = {
  email: [
    { required: true, message: '请输入邮箱地址', trigger: 'blur' },
    { type: 'email', message: '邮箱格式不正确', trigger: 'blur' },
  ],
}

// ── Shared Folder modal ──
const showFolderModal = ref(false)
const folderForm = ref({ name: '', description: '', color: '#1a5276' })
const folderFormRef = ref()
const folderRules: FormRules = {
  name: { required: true, message: '请输入收藏夹名称', trigger: 'blur' },
}

onMounted(loadData)
async function loadData() {
  loading.value = true
  try {
    const [mRes, iRes, fRes, aRes, rRes] = await Promise.all([
      api.get('/teams/members'),
      api.get('/teams/invitations'),
      api.get('/teams/shared-folders').catch(() => ({ data: { folders: [] } })),
      api.get('/teams/activity', { params: { limit: 20 } }).catch(() => ({ data: { activities: [] } })),
      api.get('/teams/reading-rankings').catch(() => ({ data: { rankings: [] } })),
    ])
    members.value = mRes.data.members || []
    invitations.value = iRes.data.items || []
    folders.value = fRes.data.folders || []
    activities.value = aRes.data.activities || []
    rankings.value = rRes.data.rankings || []
  } finally { loading.value = false }
}

async function sendInvite() {
  try { await inviteFormRef.value?.validate() } catch { return }
  inviteLoading.value = true
  try { await api.post('/teams/invitations', inviteForm.value); trackAction('team_invite', 'team', inviteForm.value.email, { role: inviteForm.value.role }); inviteForm.value = { email: '', role: 'viewer' }; showInvite.value = false; loadData() } catch (e) { toast.apiError(e, '发送邀请失败') } finally { inviteLoading.value = false }
}
async function changeRole(member: Member, newRole: string) {
  try { await api.put(`/teams/members/${member.id}/role?role=${newRole}`); trackAction('team_role_change', 'member', member.id, { role: newRole }); loadData() } catch (e) { toast.apiError(e, '修改角色失败') }
}
async function removeMember(member: Member) {
  try { await api.delete(`/teams/members/${member.id}`); trackAction('team_remove_member', 'member', member.id); loadData() } catch (e) { toast.apiError(e, '移除成员失败') }
}
async function revokeInvite(inv: Invitation) {
  try { await api.delete(`/teams/invitations/${inv.id}`); loadData() } catch (e) { toast.apiError(e, '撤销邀请失败') }
}

// ── Folder actions ──
async function createFolder() {
  try { await folderFormRef.value?.validate() } catch { return }
  folderLoading.value = true
  try {
    await api.post('/teams/shared-folders', folderForm.value)
    folderForm.value = { name: '', description: '', color: '#1a5276' }
    showFolderModal.value = false
    loadData()
    toast.success('共享收藏夹已创建')
  } catch (e) { toast.apiError(e, '创建失败') } finally { folderLoading.value = false }
}
async function deleteFolder(fid: string) {
  try { await api.delete(`/teams/shared-folders/${fid}`); loadData(); toast.success('已删除') }
  catch (e) { toast.apiError(e, '删除失败') }
}

// ── Folder detail modal ──
const showFolderDetail = ref(false)
const selectedFolder = ref<SharedFolder | null>(null)
const folderArticles = ref<any[]>([])
const folderArticleLoading = ref(false)
const folderArticleTotal = ref(0)
const folderArticlePage = ref(1)
async function openFolderDetail(f: SharedFolder) {
  selectedFolder.value = f
  showFolderDetail.value = true
  folderArticlePage.value = 1
  await loadFolderArticles()
}
async function loadFolderArticles() {
  if (!selectedFolder.value) return
  folderArticleLoading.value = true
  try {
    const { data } = await api.get(`/teams/shared-folders/${selectedFolder.value.id}/articles`, {
      params: { page: folderArticlePage.value, page_size: 10 }
    })
    folderArticles.value = data.items || []
    folderArticleTotal.value = data.total || 0
  } catch (e) { toast.apiError(e, '加载文献失败') }
  finally { folderArticleLoading.value = false }
}
function closeFolderDetail() {
  showFolderDetail.value = false
  selectedFolder.value = null
  folderArticles.value = []
  folderArticleTotal.value = 0
}

// ── Audit functions ──
async function loadMemberStats() {
  try {
    const { data } = await api.get('/teams/member-stats')
    memberStats.value = data.items || []
  } catch (e) { /* admin only — ignore */ }
}
async function loadAudit() {
  auditLoading.value = true
  try {
    const params: Record<string, any> = { page: auditPage.value, page_size: 30, days: auditDays.value }
    if (auditType.value) params.activity_type = auditType.value
    if (auditUserId.value) params.user_id = auditUserId.value
    const { data } = await api.get('/teams/activity-audit', { params })
    auditItems.value = data.items || []
    auditTotal.value = data.total || 0
  } catch (e) { /* admin only — ignore */ }
  finally { auditLoading.value = false }
}
function formatDuration(s: number | null): string {
  if (!s || s <= 0) return ''
  if (s < 60) return `${s}s`
  if (s < 3600) return `${Math.floor(s / 60)}m ${s % 60}s`
  return `${Math.floor(s / 3600)}h ${Math.floor((s % 3600) / 60)}m`
}

const roleOptions = [{ label: 'Owner', value: 'owner' }, { label: 'Admin', value: 'admin' }, { label: 'Editor', value: 'editor' }, { label: 'Viewer', value: 'viewer' }]
const isAdmin = () => auth.currentRole === 'owner' || auth.currentRole === 'admin'

const memberCols = [
  { title: '姓名', key: 'display_name', width: 100 },
  { title: '邮箱', key: 'email', width: 180, ellipsis: true },
  { title: '职称', key: 'title', width: 80 },
  { title: '角色', key: 'role', width: 120, render: (r: Member) => r.role === 'owner' ? h(NTag, { size: 'tiny', type: 'primary' }, 'Owner') : h(NSelect, { value: r.role, size: 'tiny', options: roleOptions.filter(o => o.value !== 'owner'), disabled: !isAdmin(), onUpdateValue: (v: string) => changeRole(r, v) }) },
  { title: '加入时间', key: 'joined_at', width: 100, render: (r: Member) => toBeijingDate(r.joined_at) || '—' },
  { title: '操作', key: 'actions', width: 60, render: (r: Member) => r.role !== 'owner' && isAdmin() ? h(NPopconfirm, { onPositiveClick: () => removeMember(r) }, { trigger: () => h(NButton, { size: 'tiny', type: 'error', text: true }, '移除'), default: () => '确认移除？' }) : null },
]

const inviteCols = [
  { title: '邮箱', key: 'email', width: 180 },
  { title: '角色', key: 'role', width: 80 },
  { title: '状态', key: 'status', width: 80, render: (r: Invitation) => h(NTag, { size: 'tiny', type: r.status === 'pending' ? 'warning' : r.status === 'accepted' ? 'success' : 'default' }, r.status) },
  { title: '有效期', key: 'expires_at', width: 100, render: (r: Invitation) => toBeijingDate(r.expires_at) || '—' },
  { title: '操作', key: 'actions', width: 60, render: (r: Invitation) => r.status === 'pending' && isAdmin() ? h(NButton, { size: 'tiny', text: true, onClick: () => revokeInvite(r) }, '撤销') : null },
]

const auditByTypeOptions = Object.entries(activityTypeLabels).map(([k, v]) => ({ label: v, value: k }))

const statsCols = [
  { title: '姓名', key: 'display_name', width: 100 },
  { title: '角色', key: 'role', width: 80, render: (r: any) => h(NTag, { size: 'tiny', type: r.role === 'owner' ? 'primary' : r.role === 'admin' ? 'warning' : 'default' }, r.role) },
  { title: 'PV', key: 'pv_count', width: 60 },
  { title: '行为数', key: 'action_count', width: 70 },
  { title: '活跃天数', key: 'active_days', width: 80 },
  { title: '收藏数', key: 'saved_count', width: 70 },
  { title: '最后活跃', key: 'last_active', width: 120, render: (r: any) => relativeTime(r.last_active) },
]
const auditCols = [
  { title: '姓名', key: 'display_name', width: 80 },
  { title: '类型', key: 'activity_type', width: 90, render: (r: any) => {
      const c = activityTypeColors[r.activity_type]
      return h(NTag as any, { size: 'tiny', color: c ? { color: c } : undefined, bordered: false }, { default: () => activityTypeLabels[r.activity_type] || r.activity_type })
    } },
  { title: '目标', key: 'target_id', ellipsis: { tooltip: true }, render: (r: any) => {
      const d = r.detail || {}
      if (r.activity_type === 'search') return d.keywords || r.target_id || ''
      if (r.activity_type === 'view_literature') return d.title || `PMID ${r.target_id}`
      return d.title || r.target_id || ''
    } },
  { title: '停留', key: 'duration_seconds', width: 60, render: (r: any) => r.activity_type === 'page_view' ? formatDuration(r.duration_seconds) : '' },
  { title: 'IP', key: 'ip_address', width: 100, ellipsis: { tooltip: true } },
  { title: '时间', key: 'created_at', width: 120, render: (r: any) => {
      const rt = relativeTime(r.created_at)
      return h('span', { title: r.created_at }, rt)
    } },
]

const memberColsScrollX = 640
const inviteColsScrollX = 500
const statsColsScrollX = 580
const auditColsScrollX = 750
</script>

<template>
  <div class="team-view" style="max-width:1400px;margin:0 auto;padding:24px">
    <div class="team-view-header" style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px">
      <h2 style="margin:0">👥 科室团队 ({{ members.length }})</h2>
      <NButton type="primary" @click="showInvite = true" v-if="isAdmin()" class="sky-btn"><template #icon><NIcon size="14"><PersonAddOutline /></NIcon></template>邀请成员</NButton>
    </div>

    <NAlert v-if="auth.currentTenant?.plan_type === 'free'" type="warning" style="margin-bottom:16px"
            title="团队功能需要 Team 及以上方案。升级后即可邀请成员、共享文献。" />

    <NTabs v-model:value="activeTab" type="line" @update:value="(tab: string) => {
      if (tab === 'member-stats') loadMemberStats()
      if (tab === 'audit') { auditPage = 1; loadAudit() }
    }">
      <!-- 成员 -->
      <NTabPane name="members" tab="👥 成员">
        <NSkeleton v-if="loading" text :repeat="6" />
        <template v-else>
          <NCard title="科室成员" size="small" style="margin-bottom:16px">
            <NEmpty v-if="!members.length" description="暂无成员" />
            <NDataTable v-else :columns="memberCols" :data="members" size="small" :bordered="false" :scroll-x="memberColsScrollX" />
          </NCard>
          <NCard v-if="invitations.length" title="待接受的邀请" size="small">
            <NDataTable :columns="inviteCols" :data="invitations.filter(i => i.status === 'pending')" size="small" :bordered="false" :scroll-x="inviteColsScrollX" />
          </NCard>
        </template>
      </NTabPane>

      <!-- 共享收藏夹 -->
      <NTabPane name="folders" tab="📁 共享收藏夹">
        <div style="display:flex;justify-content:flex-end;margin-bottom:12px">
          <NButton class="sky-btn" v-if="isAdmin()" size="small" @click="showFolderModal=true"><template #icon><NIcon size="14"><AddOutline /></NIcon></template>新建收藏夹</NButton>
        </div>
        <div v-if="!folders.length" style="text-align:center;padding:40px;color:var(--text-muted);font-size:13px">暂无共享收藏夹</div>
        <div v-else class="folder-grid" style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
          <NCard v-for="f in folders" :key="f.id" size="small" class="folder-card" :style="`border-left:4px solid ${f.color}`" @click="openFolderDetail(f)">
            <div style="display:flex;justify-content:space-between;align-items:flex-start">
              <div>
                <div style="font-weight:600;font-size:14px;margin-bottom:4px">{{ f.name }}</div>
                <div v-if="f.description" style="font-size:12px;color:var(--text-secondary);margin-bottom:6px">{{ f.description }}</div>
                <div style="font-size:12px;color:var(--text-muted)">{{ f.article_count }} 篇文献</div>
              </div>
              <NPopconfirm v-if="isAdmin()" @positive-click="deleteFolder(f.id)" @click.stop>
                <template #trigger><NButton size="tiny" text type="error">删除</NButton></template>
                确定删除收藏夹"{{ f.name }}"?
              </NPopconfirm>
            </div>
          </NCard>
        </div>
      </NTabPane>

      <!-- 团队活动 -->
      <NTabPane name="activity" tab="📋 团队动态">
        <NCard size="small">
          <div v-if="!activities.length" style="text-align:center;padding:40px;color:var(--text-muted);font-size:13px">暂无动态</div>
          <div v-else class="activity-timeline">
            <div v-for="a in activities" :key="a.created_at + a.type + a.user_id" class="activity-item">
              <div class="activity-dot" :class="a.type === 'member_joined' ? 'dot-join' : 'dot-save'"></div>
              <div class="activity-content">
                <div class="activity-text">{{ a.detail }}</div>
                <div class="activity-time">{{ toBeijingDateTime(a.created_at) }}</div>
              </div>
            </div>
          </div>
        </NCard>
      </NTabPane>

      <!-- 成员活跃度（仅 admin/owner） -->
      <NTabPane v-if="isAdmin()" name="member-stats" tab="📊 成员活跃度">
        <NCard size="small" title="活跃度统计">
          <NDataTable v-if="memberStats.length" :columns="statsCols" :data="memberStats" size="small" :bordered="false" :scroll-x="statsColsScrollX" />
          <NEmpty v-else description="暂无活动数据" style="padding:40px 0" />
        </NCard>
      </NTabPane>

      <!-- 行为审计（仅 admin/owner） -->
      <NTabPane v-if="isAdmin()" name="audit" tab="🔍 行为审计">
        <NCard size="small">
          <template #header>
            <div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center">
              <span style="font-weight:600">审计日志</span>
              <NSelect v-if="auditByTypeOptions.length" v-model:value="auditType" :options="auditByTypeOptions"
                placeholder="筛选类型" style="width:140px" size="tiny" clearable @update:value="() => { auditPage=1; loadAudit() }" />
              <NButton size="tiny" :type="auditDays===7?'primary':'default'" @click="auditDays=7;auditPage=1;loadAudit()">7天</NButton>
              <NButton size="tiny" :type="auditDays===30?'primary':'default'" @click="auditDays=30;auditPage=1;loadAudit()">30天</NButton>
              <NButton size="tiny" :type="auditDays===90?'primary':'default'" @click="auditDays=90;auditPage=1;loadAudit()">90天</NButton>
            </div>
          </template>
          <NDataTable v-if="auditItems.length" :columns="auditCols" :data="auditItems" size="small" :bordered="false" :scroll-x="auditColsScrollX" />
          <NEmpty v-else description="暂无审计日志" style="padding:40px 0" />
          <div v-if="auditTotal > 30" style="display:flex;justify-content:center;margin-top:12px">
            <NPagination :page="auditPage" :page-size="30" :item-count="auditTotal"
              @update:page="p => { auditPage=p; loadAudit() }" />
          </div>
        </NCard>
      </NTabPane>

      <!-- 阅读排行 -->
      <NTabPane name="rankings" tab="🏆 阅读排行">
        <NCard size="small">
          <div v-if="!rankings.length" style="text-align:center;padding:40px;color:var(--text-muted);font-size:13px">暂无数据</div>
          <div v-else class="ranking-list">
            <div v-for="(r, i) in rankings" :key="r.user_id" class="ranking-item">
              <span class="ranking-num" :class="{ 'rank-gold': i === 0, 'rank-silver': i === 1, 'rank-bronze': i === 2 }">{{ i + 1 }}</span>
              <div class="ranking-info">
                <span class="ranking-name">{{ r.display_name }}</span>
                <span v-if="r.title" class="ranking-title">{{ r.title }}</span>
              </div>
              <span class="ranking-count">{{ r.saved_count }} 篇</span>
            </div>
          </div>
        </NCard>
      </NTabPane>
    </NTabs>

    <!-- Invite Modal -->
    <NModal v-model:show="showInvite" title="邀请成员" preset="card" style="width:400px">
      <NForm ref="inviteFormRef" :model="inviteForm" :rules="inviteRules" label-placement="left" label-width="60">
        <NFormItem path="email" label="邮箱" required><NInput v-model:value="inviteForm.email" placeholder="colleague@hospital.com" /></NFormItem>
        <NFormItem label="角色"><NSelect v-model:value="inviteForm.role" :options="roleOptions.filter(o => o.value !== 'owner')" /></NFormItem>
        <NButton class="sky-btn" type="primary" block :loading="inviteLoading" @click="sendInvite"><template #icon><NIcon size="14"><SendOutline /></NIcon></template>发送邀请</NButton>
      </NForm>
    </NModal>

    <!-- Folder Modal -->
    <NModal v-model:show="showFolderModal" title="新建共享收藏夹" preset="card" style="width:400px">
      <NForm ref="folderFormRef" :model="folderForm" :rules="folderRules" label-placement="left" label-width="70">
        <NFormItem path="name" label="名称" required><NInput v-model:value="folderForm.name" placeholder="e.g. 近期重要文献" /></NFormItem>
        <NFormItem label="描述"><NInput v-model:value="folderForm.description" placeholder="可选" /></NFormItem>
        <NButton class="sky-btn" type="primary" block :loading="folderLoading" @click="createFolder"><template #icon><NIcon size="14"><AddOutline /></NIcon></template>创建</NButton>
      </NForm>
    </NModal>

    <!-- Folder Detail Modal -->
    <NModal v-model:show="showFolderDetail" title="" preset="card" style="width:700px" @close="closeFolderDetail" :mask-closable="true">
      <template #header><span style="font-weight:600;font-size:16px">📁 {{ selectedFolder?.name }}</span></template>
      <div v-if="selectedFolder?.description" style="font-size:13px;color:var(--text-secondary);margin-bottom:12px">{{ selectedFolder.description }}</div>
      <NSkeleton v-if="folderArticleLoading" text :repeat="5" />
      <template v-else-if="!folderArticles.length">
        <NEmpty description="该收藏夹暂无文献" style="padding:40px 0" />
      </template>
      <template v-else>
        <NCard v-for="item in folderArticles" :key="item.pmid" size="small" class="folder-article-card" @click="router.push(`/app/literature/${item.pmid}`)">
          <div style="font-size:14px;font-weight:500;margin-bottom:4px">{{ item.title }}</div>
          <div style="font-size:12px;color:var(--text-muted);display:flex;gap:8px;flex-wrap:wrap">
            <span>{{ item.journal }}</span>
            <span v-if="item.pub_year">· {{ item.pub_year }}</span>
            <span v-if="item.saved_by">· 由 {{ item.saved_by }} 保存</span>
            <span v-if="item.saved_at">· {{ toBeijingDate(item.saved_at) }}</span>
          </div>
        </NCard>
        <div style="text-align:center;margin-top:12px">
          <NButton size="tiny" text :disabled="folderArticlePage <= 1" @click="folderArticlePage--; loadFolderArticles()">上一页</NButton>
          <span style="font-size:12px;color:var(--text-muted);margin:0 12px">{{ folderArticlePage }} / {{ Math.ceil(folderArticleTotal / 10) }}</span>
          <NButton size="tiny" text :disabled="folderArticlePage * 10 >= folderArticleTotal" @click="folderArticlePage++; loadFolderArticles()">下一页</NButton>
        </div>
      </template>
    </NModal>
  </div>
</template>

<style scoped>
.activity-timeline { padding: 8px 0; }
.activity-item { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--border-color); }
.activity-item:last-child { border-bottom: none; }
.activity-dot { width: 10px; height: 10px; border-radius: 50%; margin-top: 5px; flex-shrink: 0; }
.dot-join { background: #2080f0; }
.dot-save { background: #18a058; }
.activity-content { flex: 1; }
.activity-text { font-size: 13px; color: var(--text-primary); }
.activity-time { font-size: 11px; color: var(--text-muted); margin-top: 2px; }

.ranking-list { padding: 0; }
.ranking-item { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border-color); }
.ranking-item:last-child { border-bottom: none; }
.ranking-num { width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; background: var(--bg-hover); color: var(--text-secondary); flex-shrink: 0; }
.rank-gold { background: #f5a623; color: #fff; }
.rank-silver { background: #bdc3c7; color: #fff; }
.rank-bronze { background: #cd7f32; color: #fff; }
.ranking-info { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.ranking-name { font-size: 14px; font-weight: 500; color: var(--text-primary); }
.ranking-title { font-size: 11px; color: var(--text-muted); }
.ranking-count { font-size: 13px; font-weight: 600; color: #1a5276; }

.folder-card { cursor: pointer; }
.folder-card:hover { box-shadow: 0 2px 8px var(--shadow); }
.folder-article-card { margin-bottom: 4px; cursor: pointer; }
.folder-article-card:hover { background: var(--bg-hover); }

@media (max-width: 768px) {
  .team-view { padding: 16px; }
  .team-view-header { flex-direction: column; align-items: flex-start; gap: 8px; }
  .team-view-header h2 { font-size: 20px; }
  .folder-grid { grid-template-columns: 1fr; }
  .activity-item { gap: 8px; }
  .ranking-item { gap: 8px; }
}
</style>
