import { computed, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'

import { useNavigation, navItems } from './useNavigation.js'
import { useRequests } from './useRequests.js'
import { useSystemState } from './useSystemState.js'
import { useToast } from './useToast.js'
import { fetchLatestConversation } from '../services/orchestrator.js'
import { clearAssistantSessionSnapshotForDraftClaim } from '../utils/assistantSessionSnapshot.js'
import { buildDetailAlerts } from '../utils/detailAlerts.js'
import { normalizeRequestForUi } from '../utils/requestViewModel.js'
import { buildWorkbenchSummary } from '../utils/workbenchSummary.js'

const SESSION_TYPE_EXPENSE = 'expense'
const SMART_ENTRY_SOURCE_APPLICATION = 'application'
const SMART_ENTRY_SOURCE_REIMBURSEMENT = 'topbar'

export function useAppShell() {
  const route = useRoute()
  const router = useRouter()

  const smartEntryOpen = ref(false)
  const smartEntryContext = ref({
    prompt: '',
    source: 'documents',
    request: null,
    files: [],
    conversation: null,
    scope: null
  })
  const smartEntrySessionId = ref(0)
  const smartEntryRevealToken = ref(0)
  const smartEntryInvalidatedDraftClaimId = ref('')
  const selectedRequestSnapshot = ref(null)

  const { activeView, currentView, setView } = useNavigation()
  const {
    requests,
    loading: requestsLoading,
    error: requestsError,
    search,
    filters,
    ranges,
    activeRange,
    filteredRequests,
    approveRequest,
    rejectRequest,
    reload: reloadRequests
  } = useRequests()
  const { currentUser } = useSystemState()
  const { toast } = useToast()

  const customRange = ref({ start: '2024-07-06', end: '2024-07-12' })

  const selectedRequest = computed(() => {
    const requestId = String(route.params.requestId || '')

    if (!requestId) {
      return null
    }

    const rawRequest = requests.value.find(
      (item) => String(item.claimId || '').trim() === requestId || String(item.id || '').trim() === requestId
    )
    const normalizedRequest = normalizeRequestForUi(rawRequest)
    if (normalizedRequest) {
      return normalizedRequest
    }

    const snapshot = normalizeRequestForUi(selectedRequestSnapshot.value)
    if (
      snapshot
      && (
        String(snapshot.claimId || '').trim() === requestId
        || String(snapshot.id || '').trim() === requestId
        || String(snapshot.documentNo || '').trim() === requestId
      )
    ) {
      return snapshot
    }

    return null
  })

  const detailMode = computed(() => route.name === 'app-document-detail')
  const logDetailMode = computed(() => route.name === 'app-log-detail')
  const detailAlerts = computed(() => (detailMode.value ? buildDetailAlerts(selectedRequest.value) : []))

  const documentsListActive = computed(() => activeView.value === 'documents' && !detailMode.value)
  const workbenchActive = computed(() => activeView.value === 'workbench')

  watch(documentsListActive, (isActive, wasActive) => {
    if (isActive && !wasActive) {
      void reloadRequests()
    }
  })

  watch(workbenchActive, (isActive, wasActive) => {
    if (isActive && !wasActive) {
      void reloadRequests()
    }
  })

  const workbenchSummary = computed(() =>
    buildWorkbenchSummary(requests.value, currentUser.value)
  )

  const topBarView = computed(() => {
    if (detailMode.value) {
      const request = selectedRequest.value || {}
      const claimNo = request.claimNo || request.claim_no || request.documentNo || request.id || ''
      const isApplicationDocument = isApplicationDocumentPayload(request, claimNo)
      return {
        title: isApplicationDocument ? '申请单详情' : '报销单详情',
        desc: isApplicationDocument
          ? '查看申请信息、预计金额与审批进度。'
          : '查看报销明细、票据材料、审批进度与风险提示。'
      }
    }

    if (logDetailMode.value) {
      return {
        title: '日志详情',
        desc: '查看单条日志的解析结果、上下文信息与原始记录。'
      }
    }

    return currentView.value
  })

  const requestSummary = computed(() =>
    filteredRequests.value.reduce(
      (summary, item) => {
        const request = normalizeRequestForUi(item)
        if (!request) {
          return summary
        }

        summary.total += 1

        if (request.approvalKey === 'draft') {
          summary.draft += 1
        } else if (request.approvalKey === 'in_progress') {
          summary.inProgress += 1
        } else if (request.approvalKey === 'supplement') {
          summary.supplement += 1
        } else if (request.approvalKey === 'completed') {
          summary.completed += 1
        }

        return summary
      },
      { total: 0, draft: 0, inProgress: 0, supplement: 0, completed: 0 }
    )
  )

  function handleApprove(request) {
    const message = approveRequest(request)
    toast(message)
  }

  function handleReject(request) {
    const message = rejectRequest(request)
    toast(message)
  }

  function handleNavigate(view) {
    smartEntryOpen.value = false
    setView(view)
  }

  function openFinancialAssistantCreate(source) {
    if (smartEntryOpen.value) {
      smartEntryRevealToken.value += 1
      return
    }
    smartEntryOpen.value = true
    smartEntryContext.value = {
      prompt: '',
      source,
      request: null,
      files: [],
      conversation: null,
      scope: null
    }
    smartEntrySessionId.value += 1
  }

  function openTravelCreate() {
    openFinancialAssistantCreate(SMART_ENTRY_SOURCE_REIMBURSEMENT)
  }

  function openExpenseApplicationCreate() {
    openFinancialAssistantCreate(SMART_ENTRY_SOURCE_APPLICATION)
  }

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

  function resolveSmartEntryClaimScope(payload = {}) {
    const request = payload.request && typeof payload.request === 'object' ? payload.request : null
    const payloadScope = payload.scope && typeof payload.scope === 'object' ? payload.scope : null
    const claimId = String(
      payloadScope?.claimId ||
        payloadScope?.claim_id ||
        request?.claimId ||
        request?.claim_id ||
        ''
    ).trim()
    if (!claimId) {
      return null
    }
    return { type: 'claim', claimId }
  }

  function isDetailClaimScopedPayload(payload = {}) {
    return String(payload.source || '').trim() === 'detail' && Boolean(resolveSmartEntryClaimScope(payload))
  }

  function isApplicationDocumentPayload(payload = {}, claimNo = '') {
    const documentType = String(
      payload.documentType
      || payload.document_type
      || payload.documentTypeCode
      || payload.document_type_code
      || payload.draftType
      || payload.draft_type
      || ''
    ).trim()
    const normalizedClaimNo = String(claimNo || payload.claimNo || payload.claim_no || '').trim().toUpperCase()
    return (
      documentType === 'application'
      || documentType === 'expense_application'
      || normalizedClaimNo.startsWith('AP-')
      || normalizedClaimNo.startsWith('APP-')
    )
  }

  async function resolveSmartEntryConversation(payload = {}) {
    if (payload.conversation) {
      return payload.conversation
    }

    if (isDetailClaimScopedPayload(payload)) {
      return null
    }

    if (!payload.restoreLatestConversation) {
      return null
    }

    try {
      const latestPayload = await fetchLatestConversation(resolveCurrentUserId(), SESSION_TYPE_EXPENSE, {
        preferRecoverable: true
      })
      return latestPayload?.found ? latestPayload.conversation || null : null
    } catch (error) {
      console.warn('Failed to restore latest expense conversation for smart entry:', error)
      toast(error?.message || '恢复最近报销会话失败，请稍后重试。')
      return null
    }
  }

  async function openSmartEntry(payload = {}) {
    const shouldReplaceOpenEntry = Boolean(
      payload?.source === 'budget'
        || payload?.sessionType
        || String(payload?.prompt || '').trim()
        || (Array.isArray(payload?.files) && payload.files.length)
        || payload?.conversation
    )
    if (smartEntryOpen.value && !shouldReplaceOpenEntry) {
      smartEntryRevealToken.value += 1
      return
    }
    const conversation = await resolveSmartEntryConversation(payload)
    const scope = resolveSmartEntryClaimScope(payload)
    smartEntryOpen.value = true

    smartEntryContext.value = {
      prompt: payload.prompt ?? '',
      source: payload.source ?? 'workbench',
      request: payload.request ?? selectedRequest.value,
      files: Array.isArray(payload.files) ? payload.files : [],
      conversation,
      scope
    }
    smartEntrySessionId.value += 1
  }

  function closeSmartEntry() {
    smartEntryOpen.value = false
  }

  async function handleDraftSaved(payload = {}) {
    const claimNo = String(payload.claimNo || payload.claim_no || '').trim()
    const status = String(payload.status || payload.claimStatus || '').trim()
    const approvalStage = String(payload.approvalStage || payload.approval_stage || '').trim()
    const isApplicationDocument = isApplicationDocumentPayload(payload, claimNo)
    await reloadRequests()
    if (status === 'submitted') {
      smartEntryOpen.value = false
      toast(
        isApplicationDocument
          ? `${claimNo || '该'}申请单已提交${approvalStage ? `，当前节点：${approvalStage}` : '，等待直属领导审批'}。`
          : `${claimNo || '该'}单据已完成 AI预审${approvalStage ? `，当前节点：${approvalStage}` : '，并已提交审批'}。`
      )
      router.push({ name: 'app-documents' })
      return
    }
    toast(
      isApplicationDocument
        ? `${claimNo || '该'}申请单已保存为草稿，可继续补充申请信息。`
        : `${claimNo || '该'}单据已保存为草稿，可继续上传票据或补充信息。`
    )
  }

  function openRequestDetail(request) {
    selectedRequestSnapshot.value = request || null
    router.push({
      name: 'app-document-detail',
      params: { requestId: request.claimId || request.id }
    })
  }

  function closeRequestDetail() {
    router.push({ name: 'app-documents' })
  }

  async function handleRequestUpdated() {
    await reloadRequests()
  }

  async function handleRequestDeleted(payload = {}) {
    const deletedClaimId = String(payload.claimId || payload.claim_id || '').trim()
    if (deletedClaimId) {
      clearAssistantSessionSnapshotForDraftClaim(resolveCurrentUserId(), deletedClaimId, SESSION_TYPE_EXPENSE)
      smartEntryInvalidatedDraftClaimId.value = deletedClaimId
    }

    await reloadRequests()
    selectedRequestSnapshot.value = null
    router.push({ name: 'app-documents' })
  }

  return {
    activeRange,
    activeView,
    closeRequestDetail,
    closeSmartEntry,
    currentView,
    customRange,
    detailMode,
    logDetailMode,
    filteredRequests,
    filters,
    handleApprove,
    handleDraftSaved,
    handleNavigate,
    handleReject,
    handleRequestDeleted,
    handleRequestUpdated,
    navItems,
    openExpenseApplicationCreate,
    openRequestDetail,
    openSmartEntry,
    openTravelCreate,
    ranges,
    requestSummary,
    workbenchSummary,
    requestsError,
    requestsLoading,
    reloadRequests,
    requests,
    search,
    selectedRequest,
    setView,
    smartEntryContext,
    smartEntryInvalidatedDraftClaimId,
    smartEntryOpen,
    smartEntryRevealToken,
    smartEntrySessionId,
    detailAlerts,
    toast,
    topBarView
  }
}
