import { computed, reactive, ref } from 'vue'

import {
  REIMBURSEMENT_LIST_PREVIEW_PARAMS,
  extractExpenseClaimItems,
  fetchExpenseClaims
} from '../services/reimbursements.js'
import { formatDate, toDate } from './requests/requestShared.js'
import { mapExpenseClaimToRequest } from './requests/requestClaimMapper.js'

export { mapExpenseClaimToRequest } from './requests/requestClaimMapper.js'

function getWeekStart(date) {
  const nextDate = new Date(date)
  const day = nextDate.getDay() || 7
  nextDate.setHours(0, 0, 0, 0)
  nextDate.setDate(nextDate.getDate() - day + 1)
  return nextDate
}

function getRecentDaysStart(date, days) {
  const nextDate = new Date(date)
  nextDate.setHours(0, 0, 0, 0)
  nextDate.setDate(nextDate.getDate() - Math.max(0, Number(days || 1) - 1))
  return nextDate
}

function resolveRangeMatch(activeRange, item) {
  if (activeRange === 'custom' || activeRange === '本月') {
    if (activeRange !== '本月') {
      return true
    }
  }

  const targetDate = toDate(item?.submittedAt || item?.createdAt || item?.occurredAt)
  if (!targetDate) {
    return true
  }

  const now = new Date()
  const targetDay = formatDate(targetDate)

  if (activeRange === '今日') {
    return targetDay === formatDate(now)
  }

  if (activeRange === '近10日') {
    const recentStart = getRecentDaysStart(now, 10)
    return targetDate >= recentStart && targetDate <= now
  }

  if (activeRange === '本周') {
    const weekStart = getWeekStart(now)
    const nextWeekStart = new Date(weekStart)
    nextWeekStart.setDate(nextWeekStart.getDate() + 7)
    return targetDate >= weekStart && targetDate < nextWeekStart
  }

  if (activeRange === '本月') {
    return (
      targetDate.getFullYear() === now.getFullYear()
      && targetDate.getMonth() === now.getMonth()
    )
  }

  return true
}

export function useRequests() {
  const requests = ref([])
  const loading = ref(false)
  const loaded = ref(false)
  const error = ref('')
  const search = ref('')
  const filters = reactive({ entity: '全部主体', category: '全部类型', risk: '全部状态' })
  const ranges = ['今日', '近10日', '本周', '本月']
  const activeRange = ref('近10日')

  const filteredRequests = computed(() => {
    const key = search.value.trim().toLowerCase()

    return requests.value.filter((item) => {
      const searchText = [
        item.id,
        item.person,
        item.typeLabel,
        item.title,
        item.sceneTarget,
        item.riskSummary
      ]
        .filter(Boolean)
        .join('')
        .toLowerCase()

      const matchesSearch = !key || searchText.includes(key)
      const matchesRange = resolveRangeMatch(activeRange.value, item)

      return matchesSearch && matchesRange
    })
  })

  async function reload(options = {}) {
    const silent = Boolean(options?.silent)
    if (!silent) {
      loading.value = true
      error.value = ''
    }

    try {
      const payload = await fetchExpenseClaims(REIMBURSEMENT_LIST_PREVIEW_PARAMS)
      requests.value = extractExpenseClaimItems(payload).map((item) => mapExpenseClaimToRequest(item))
      loaded.value = true
    } catch (nextError) {
      if (!silent) {
        requests.value = []
      }
      error.value = nextError instanceof Error ? nextError.message : '个人报销列表加载失败。'
    } finally {
      if (!silent) {
        loading.value = false
      }
    }
  }

  function approveRequest(request) {
    return `${request.id} 未执行本地状态变更，列表当前只展示后端真实数据。`
  }

  function rejectRequest(request) {
    return `${request.id} 未执行本地状态变更，列表当前只展示后端真实数据。`
  }

  function ensureLoaded() {
    return loaded.value ? Promise.resolve() : reload()
  }

  return {
    requests,
    loading,
    loaded,
    error,
    search,
    filters,
    ranges,
    activeRange,
    filteredRequests,
    approveRequest,
    rejectRequest,
    ensureLoaded,
    reload
  }
}
