<template>
  <section class="workbench" aria-label="个人工作台">
    <PanelHead
      v-if="showHeader"
      eyebrow="Personal Workspace"
      title="个人工作台"
      note="把费用申请、报销进度、制度问答和待办处理集中到一个入口。"
    />

    <article class="panel assistant-hero" :style="{ '--assistant-bg-image': `url(${homepageBackground})` }">
      <div class="assistant-copy">
        <h1>嗨，{{ displayUserName }}，我是您的 <span>AI 费用助手</span></h1>

        <input
          ref="fileInputRef"
          class="assistant-file-input"
          type="file"
          multiple
          accept=".pdf,.jpg,.jpeg,.png,.webp,.doc,.docx,.xls,.xlsx"
          @change="handleWorkbenchFilesChange"
        />

        <div class="assistant-composer">
          <textarea
            ref="assistantInputRef"
            v-model="assistantDraft"
            maxlength="1000"
            rows="2"
            placeholder="请输入费用申请、报销问题、预算查询或制度问答..."
            @keydown.enter.prevent="handleWorkbenchEnter"
          />

          <div class="composer-toolbar">
            <button
              type="button"
              class="composer-icon-button"
              title="上传附件"
              aria-label="上传附件"
              :disabled="Boolean(pendingAction)"
              @click="triggerFileUpload"
            >
              <i class="mdi mdi-paperclip"></i>
            </button>

            <button
              type="button"
              class="composer-related-button"
              :disabled="Boolean(pendingAction)"
              @click="triggerFileUpload"
            >
              <i class="mdi mdi-source-branch"></i>
              <span>关联单据</span>
              <i class="mdi mdi-chevron-down"></i>
            </button>

            <span class="composer-count">{{ assistantDraft.length }}/1000</span>

            <button
              type="button"
              class="composer-send-button"
              :disabled="Boolean(pendingAction)"
              :aria-label="pendingAction === 'expense' ? '处理中' : expenseActionLabel"
              @click="handleExpenseConversationAction"
            >
              <i :class="pendingAction === 'expense' ? 'mdi mdi-loading mdi-spin' : 'mdi mdi-send'"></i>
            </button>
          </div>
        </div>

        <div v-if="selectedFiles.length" class="assistant-file-strip">
          <span class="assistant-file-note">已带入 {{ selectedFiles.length }} 份附件</span>
          <span v-for="file in selectedFiles" :key="file.name" class="assistant-file-chip">{{ file.name }}</span>
          <button type="button" class="assistant-file-clear" @click="clearSelectedFiles">清空</button>
        </div>

        <div class="quick-prompts" aria-label="常用提问">
          <span>常用提问：</span>
          <button
            v-for="prompt in quickPromptItems"
            :key="prompt"
            type="button"
            @click="applyQuickPrompt(prompt)"
          >
            {{ prompt }}
          </button>
          <button type="button" class="quick-more" @click="emit('open-assistant')">
            更多
            <i class="mdi mdi-chevron-right"></i>
          </button>
        </div>
      </div>
    </article>

    <div :class="['capability-grid', capabilityGridClass]" aria-label="AI 财务助手能力">
      <button
        v-for="item in visibleAssistantCapabilities"
        :key="item.key"
        type="button"
        class="capability-card panel"
        :class="`capability-card--${item.tone}`"
        @click="openPromptAssistant(item.prompt)"
      >
        <span class="capability-icon"><i :class="item.icon"></i></span>
        <span class="capability-copy">
          <strong>{{ item.title }}</strong>
          <small>{{ item.primary }}</small>
          <small>{{ item.secondary }}</small>
        </span>
        <i class="mdi mdi-chevron-right capability-arrow"></i>
      </button>
    </div>

    <div class="workbench-content-grid">
      <article class="panel workbench-card todo-panel">
        <div class="section-head">
          <div class="title-with-badge">
            <h2>我的待办</h2>
            <span class="soft-badge">{{ todoAlertCount }}</span>
          </div>
          <button type="button" class="link-action">全部待办 <i class="mdi mdi-chevron-right"></i></button>
        </div>

        <div class="todo-list">
          <button
            v-for="item in visibleTodoItems"
            :key="item.title"
            type="button"
            class="todo-row"
            @click="openPromptAssistant(`帮我处理：${item.title}，${item.description}`)"
          >
            <WorkbenchListIcon
              :icon-key="item.iconKey"
              :color="item.color"
              :accent="item.accent"
            />
            <span class="todo-copy">
              <strong>{{ item.title }}</strong>
              <small>{{ item.description }}</small>
            </span>
            <span class="todo-meta">
              <span class="todo-status" :class="`todo-status--${item.statusTone}`">{{ item.status }}</span>
              <small>{{ item.due }}</small>
            </span>
          </button>
        </div>

      </article>

      <article class="panel workbench-card progress-panel">
        <div class="section-head">
          <h2>费用进度</h2>
          <button type="button" class="link-action">全部进度 <i class="mdi mdi-chevron-right"></i></button>
        </div>

        <div class="progress-list">
          <button
            v-for="item in visibleProgressItems"
            :key="item.id"
            type="button"
            class="progress-row"
            @click="openPromptAssistant(`查询 ${item.id} 的费用进度`)"
          >
            <span class="progress-identity">
              <strong>{{ item.id }}</strong>
              <small>{{ item.title }}</small>
            </span>

            <span class="progress-steps" aria-hidden="true">
              <span
                v-for="(step, index) in progressSteps"
                :key="step"
                class="progress-step"
                :class="{
                  'is-done': index < item.activeStep,
                  'is-current': index === item.activeStep,
                  'is-future': index > item.activeStep
                }"
              >
                <i :class="index <= item.activeStep ? 'mdi mdi-check' : 'mdi mdi-minus'"></i>
                <small>{{ step }}</small>
              </span>
            </span>

            <span class="progress-result">
              <span class="progress-status" :class="`progress-status--${item.statusTone}`">{{ item.status }}</span>
              <strong>{{ item.amount }}</strong>
            </span>
          </button>
        </div>

      </article>

      <aside class="side-column">
        <article class="panel workbench-card side-panel expense-stats-panel">
          <div class="section-head side-card-head">
            <h2>费用统计</h2>
            <button
              type="button"
              class="detail-action"
              @click="openPromptAssistant('查看我的费用统计详情，并说明本月报销金额、审批中和待付款的主要变化。')"
            >
              <span>查看详情</span>
              <i class="mdi mdi-chevron-right"></i>
            </button>
          </div>

          <div class="insight-metric-list" aria-label="费用统计">
            <div
              v-for="item in visibleExpenseStatItems"
              :key="item.key"
              class="insight-metric-row"
              :class="`insight-metric-row--${item.tone}`"
            >
              <span class="insight-metric-label">{{ item.label }}</span>
              <strong class="insight-metric-value">
                {{ item.value }}<small v-if="item.unit">{{ item.unit }}</small>
              </strong>
            </div>
          </div>
        </article>

        <article class="panel workbench-card side-panel usage-profile-panel">
          <div class="section-head side-card-head">
            <h2>用户画像</h2>
            <button
              type="button"
              class="detail-action"
              aria-haspopup="dialog"
              :aria-expanded="expenseProfileModalOpen"
              @click="openExpenseProfileModal"
            >
              <span>查看详情</span>
              <i :class="employeeProfileLoading ? 'mdi mdi-loading mdi-spin' : 'mdi mdi-chevron-right'"></i>
            </button>
          </div>

          <div class="insight-profile-list" aria-label="用户画像">
            <div
              v-for="metric in visibleUsageProfileMetrics"
              :key="metric.key"
              class="insight-profile-card"
              :class="`insight-profile-card--${metric.tone}`"
            >
              <span class="insight-profile-icon" aria-hidden="true">
                <i :class="metric.icon"></i>
              </span>
              <div class="insight-profile-copy">
                <span class="insight-profile-label">{{ metric.label }}</span>
                <strong class="insight-profile-value">
                  {{ metric.value }}<small>{{ metric.unit }}</small>
                </strong>
                <span class="insight-profile-hint">{{ metric.hint }}</span>
              </div>
            </div>
          </div>
        </article>
      </aside>
    </div>

    <ExpenseProfileDetailModal
      :visible="expenseProfileModalOpen"
      :user-name="displayUserName"
      :metrics="expenseProfileModalMetrics"
      :tags="expenseProfileTags"
      :radar-dimensions="expenseProfileRadarDimensions"
      :operations="expenseProfileOperations"
      :loading="employeeProfileLoading"
      :error-message="employeeProfileError"
      :empty-reason="expenseProfileEmptyReason"
      @close="closeExpenseProfileModal"
    />
  </section>
</template>

<script setup>
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import PanelHead from '../shared/PanelHead.vue'
import ExpenseProfileDetailModal from './ExpenseProfileDetailModal.vue'
import WorkbenchListIcon from '../shared/WorkbenchListIcon.vue'
import homepageBackground from '../../assets/homepage_backgraound.png'
import { useSystemState } from '../../composables/useSystemState.js'
import { useToast } from '../../composables/useToast.js'
import {
  assistantCapabilities,
  buildExpenseStatItems,
  progressItems,
  progressSteps,
  quickPromptItems,
  todoItems,
} from '../../data/personalWorkbench.js'
import { fetchAgentRuns } from '../../services/agentAssets.js'
import { clearUserConversations, fetchLatestConversation } from '../../services/orchestrator.js'
import { fetchCurrentEmployeeLatestProfile } from '../../services/reimbursements.js'
import {
  ASSISTANT_SESSION_SNAPSHOT_EVENT,
  hasAssistantSessionSnapshot
} from '../../utils/assistantSessionSnapshot.js'
import {
  buildProfileOperationsFromAgentRuns,
  buildUserProfileMetricCards,
  buildUserProfileSummaryMetrics,
  normalizeUserProfileRadarDimensions,
  normalizeUserProfileTags,
  resolveCurrentUserProfileError
} from '../../utils/employeeProfileViewModel.js'

const props = defineProps({
  showHeader: { type: Boolean, default: true },
  assistantModalOpen: { type: Boolean, default: false },
  workbenchSummary: { type: Object, default: () => ({}) }
})

const emit = defineEmits(['open-assistant'])
const { currentUser } = useSystemState()
const { toast } = useToast()
const assistantDraft = ref('')
const assistantInputRef = ref(null)
const fileInputRef = ref(null)
const selectedFiles = ref([])
const pendingAction = ref('')
const latestExpenseConversation = ref(null)
const hasLocalExpenseSnapshot = ref(false)
const expenseProfileModalOpen = ref(false)
const employeeProfile = ref(null)
const employeeProfileRuns = ref([])
const employeeProfileLoading = ref(false)
const employeeProfileError = ref('')
let employeeProfileLoadSeq = 0
const MAX_ATTACHMENTS = 10
const SESSION_TYPE_EXPENSE = 'expense'
const SESSION_TYPE_KNOWLEDGE = 'knowledge'
const FINANCIAL_CAPABILITY_KEYS = new Set(['budget-planning', 'finance-analysis'])
const FINANCIAL_CAPABILITY_ROLE_CODES = new Set(['budget_monitor', 'executive', 'admin'])
const FINANCIAL_CAPABILITY_ROLE_LABELS = new Set(['预算监控员', '高级财务人员', '管理员'])

const hasExpenseConversation = computed(() =>
  Boolean(latestExpenseConversation.value?.conversation_id || latestExpenseConversation.value?.conversationId)
    || hasLocalExpenseSnapshot.value
)
const displayUserName = computed(() => {
  const user = currentUser.value || {}
  return String(user.name || user.username || '同事').trim() || '同事'
})
const expenseActionLabel = computed(() => (hasExpenseConversation.value ? '继续报销' : '新建报销'))
const currentRoleCodes = computed(() => {
  const user = currentUser.value || {}
  const rawCodes = Array.isArray(user.roleCodes)
    ? user.roleCodes
    : Array.isArray(user.role_codes)
      ? user.role_codes
      : []
  return new Set(rawCodes.map((code) => String(code || '').trim().toLowerCase()).filter(Boolean))
})
const canViewFinancialCapabilities = computed(() => {
  const user = currentUser.value || {}
  const roleLabel = String(user.role || '').trim()
  return Boolean(user.isAdmin)
    || FINANCIAL_CAPABILITY_ROLE_LABELS.has(roleLabel)
    || Array.from(currentRoleCodes.value).some((code) => FINANCIAL_CAPABILITY_ROLE_CODES.has(code))
})
const visibleAssistantCapabilities = computed(() =>
  assistantCapabilities.filter((item) => canViewFinancialCapabilities.value || !FINANCIAL_CAPABILITY_KEYS.has(item.key))
)
const capabilityGridClass = computed(() =>
  canViewFinancialCapabilities.value ? 'capability-grid--privileged' : 'capability-grid--standard'
)
const expenseStatItems = computed(() => buildExpenseStatItems(props.workbenchSummary))
const visibleExpenseStatItems = computed(() => {
  const preferredKeys = ['monthly-amount', 'monthly-count', 'in-review', 'pending-payment']
  return preferredKeys
    .map((key) => expenseStatItems.value.find((item) => item.key === key))
    .filter(Boolean)
})
const visibleUsageProfileMetrics = computed(() => {
  return buildUserProfileMetricCards(
    employeeProfile.value,
    employeeProfileRuns.value,
    currentUser.value
  ).slice(0, 4)
})
const expenseProfileModalMetrics = computed(() => {
  return buildUserProfileSummaryMetrics(
    employeeProfile.value,
    employeeProfileRuns.value,
    currentUser.value
  )
})
const expenseProfileTags = computed(() => normalizeUserProfileTags(employeeProfile.value))
const expenseProfileRadarDimensions = computed(() => normalizeUserProfileRadarDimensions(employeeProfile.value))
const expenseProfileOperations = computed(() =>
  buildProfileOperationsFromAgentRuns(employeeProfileRuns.value, currentUser.value)
)
const expenseProfileEmptyReason = computed(() => String(employeeProfile.value?.empty_reason || '').trim())
const currentUserProfileKey = computed(() => {
  const user = currentUser.value || {}
  return [
    user.username,
    user.email,
    user.name,
    user.employeeNo,
    user.employee_no
  ].map((item) => String(item || '').trim()).filter(Boolean).join('|')
})
const visibleTodoItems = computed(() => todoItems.slice(0, 5))
const visibleProgressItems = computed(() => progressItems.slice(0, 5))
const todoAlertCount = computed(() => visibleTodoItems.value.length)

function buildSelectedFileKey(file) {
  return [file?.name, file?.size, file?.lastModified, file?.type].join('__')
}

function mergeSelectedFiles(existingFiles, incomingFiles) {
  const nextFiles = []
  const seen = new Set()

  for (const file of existingFiles) {
    const key = buildSelectedFileKey(file)
    if (seen.has(key)) continue
    seen.add(key)
    nextFiles.push(file)
  }

  let overflowCount = 0

  for (const file of incomingFiles) {
    const key = buildSelectedFileKey(file)
    if (seen.has(key)) continue
    if (nextFiles.length >= MAX_ATTACHMENTS) {
      overflowCount += 1
      continue
    }
    seen.add(key)
    nextFiles.push(file)
  }

  return {
    files: nextFiles,
    overflowCount
  }
}

function resolveCurrentUserId() {
  const user = currentUser.value || {}
  return String(user.username || user.name || 'anonymous').trim() || 'anonymous'
}

function buildAssistantPayload() {
  return {
    prompt: assistantDraft.value.trim(),
    source: 'workbench',
    files: Array.from(selectedFiles.value)
  }
}

function clearSelectedFiles() {
  selectedFiles.value = []
  if (fileInputRef.value) {
    fileInputRef.value.value = ''
  }
}

function resetWorkbenchDraft() {
  assistantDraft.value = ''
  clearSelectedFiles()
}

function emitAssistant(payload) {
  emit('open-assistant', payload)
  resetWorkbenchDraft()
}

async function loadLatestConversation() {
  const payload = await fetchLatestConversation(resolveCurrentUserId(), SESSION_TYPE_EXPENSE, {
    preferRecoverable: true
  })
  return payload?.found ? payload.conversation || null : null
}

function focusAssistantInput() {
  nextTick(() => {
    assistantInputRef.value?.focus()
  })
}

function applyQuickPrompt(prompt) {
  assistantDraft.value = String(prompt || '').trim()
  focusAssistantInput()
}

function openPromptAssistant(prompt) {
  if (pendingAction.value) {
    return
  }

  emitAssistant({
    prompt: String(prompt || '').trim(),
    source: 'workbench',
    files: Array.from(selectedFiles.value),
    conversation: null
  })
}

async function loadCurrentEmployeeProfile() {
  const sequence = ++employeeProfileLoadSeq
  employeeProfileLoading.value = true
  employeeProfileError.value = ''

  const [profileResult, runsResult] = await Promise.allSettled([
    fetchCurrentEmployeeLatestProfile({
      scene: 'operations',
      window_days: 90,
      expense_type_scope: 'overall'
    }),
    fetchAgentRuns({ limit: 100 })
  ])

  if (sequence !== employeeProfileLoadSeq) {
    return
  }

  if (profileResult.status === 'fulfilled') {
    employeeProfile.value = profileResult.value || null
  } else {
    employeeProfile.value = null
    employeeProfileError.value = resolveCurrentUserProfileError(profileResult.reason)
  }

  employeeProfileRuns.value = runsResult.status === 'fulfilled' ? runsResult.value || [] : []
  employeeProfileLoading.value = false
}

function openExpenseProfileModal() {
  expenseProfileModalOpen.value = true
  if (!employeeProfile.value && !employeeProfileLoading.value) {
    void loadCurrentEmployeeProfile()
  }
}

function closeExpenseProfileModal() {
  expenseProfileModalOpen.value = false
}

function handleWorkbenchEnter(event) {
  if (event.isComposing) {
    return
  }

  handleExpenseConversationAction()
}

function triggerFileUpload() {
  fileInputRef.value?.click()
}

function handleWorkbenchFilesChange(event) {
  const mergeResult = mergeSelectedFiles(selectedFiles.value, Array.from(event.target.files ?? []))
  selectedFiles.value = mergeResult.files
  if (mergeResult.overflowCount > 0) {
    toast(`一次最多上传 ${MAX_ATTACHMENTS} 份附件，已保留前 ${MAX_ATTACHMENTS} 份。`)
  }
  if (fileInputRef.value) {
    fileInputRef.value.value = ''
  }
}

async function refreshLatestExpenseConversation() {
  refreshLocalExpenseSnapshot()
  try {
    latestExpenseConversation.value = await loadLatestConversation()
  } catch (error) {
    console.warn('Failed to refresh latest expense conversation:', error)
    latestExpenseConversation.value = null
  }
}

function refreshLocalExpenseSnapshot() {
  hasLocalExpenseSnapshot.value = hasAssistantSessionSnapshot(resolveCurrentUserId(), SESSION_TYPE_EXPENSE)
}

function handleAssistantSessionSnapshotChange(event) {
  const sessionType = String(event?.detail?.sessionType || '').trim()
  if (!sessionType || sessionType === SESSION_TYPE_EXPENSE) {
    refreshLocalExpenseSnapshot()
  }
}

async function clearKnowledgeHistoryBeforeExpense() {
  await clearUserConversations(resolveCurrentUserId(), SESSION_TYPE_KNOWLEDGE)
}

async function handleExpenseConversationAction() {
  if (pendingAction.value) {
    return
  }

  const nextPayload = buildAssistantPayload()
  const shouldOpenImmediately = Boolean(nextPayload.prompt || nextPayload.files.length)

  if (shouldOpenImmediately) {
    emitAssistant({
      ...nextPayload,
      conversation: null
    })
    void clearKnowledgeHistoryBeforeExpense().catch((error) => {
      console.warn('Failed to clear knowledge history before expense:', error)
    })
    return
  }

  pendingAction.value = 'expense'

  try {
    await clearKnowledgeHistoryBeforeExpense()
    const conversation = await loadLatestConversation()
    latestExpenseConversation.value = conversation
    emitAssistant({
      ...nextPayload,
      conversation
    })
  } catch (error) {
    console.warn('Failed to open expense conversation:', error)
    toast(error?.message || '打开报销会话失败，请稍后重试。')
  } finally {
    pendingAction.value = ''
  }
}

onMounted(() => {
  refreshLocalExpenseSnapshot()
  refreshLatestExpenseConversation()
  loadCurrentEmployeeProfile()
  window.addEventListener(ASSISTANT_SESSION_SNAPSHOT_EVENT, handleAssistantSessionSnapshotChange)
})

onBeforeUnmount(() => {
  window.removeEventListener(ASSISTANT_SESSION_SNAPSHOT_EVENT, handleAssistantSessionSnapshotChange)
})

watch(
  () => props.assistantModalOpen,
  (open, previous) => {
    if (previous && !open) {
      refreshLatestExpenseConversation()
    }
  }
)

watch(currentUserProfileKey, (nextKey, previousKey) => {
  if (nextKey && nextKey !== previousKey) {
    loadCurrentEmployeeProfile()
  }
})
</script>

<style scoped src="../../assets/styles/components/personal-workbench.css"></style>
<style scoped src="../../assets/styles/components/personal-workbench-insights.css"></style>
<style scoped src="../../assets/styles/components/personal-workbench-responsive.css"></style>
