import { apiRequest } from './api.js'

export const REIMBURSEMENT_LIST_PREVIEW_PARAMS = Object.freeze({ page: 1, pageSize: 100 })
export const REIMBURSEMENT_LIST_FULL_PAGE_SIZE = 100
const REIMBURSEMENT_LIST_MAX_PAGES = 200

function buildListQuery(params = {}) {
  const search = new URLSearchParams()
  const page = params.page
  const pageSize = params.pageSize || params.page_size

  if (page) {
    search.set('page', String(page))
  }

  if (pageSize) {
    search.set('page_size', String(pageSize))
  }

  const query = search.toString()
  return query ? `?${query}` : ''
}

export function extractExpenseClaimItems(payload) {
  if (Array.isArray(payload)) {
    return payload
  }

  return Array.isArray(payload?.items) ? payload.items : []
}

function isPaginatedExpenseClaimPayload(payload) {
  return Boolean(
    payload
    && typeof payload === 'object'
    && Array.isArray(payload.items)
    && Number.isFinite(Number(payload.page))
    && Number.isFinite(Number(payload.page_size))
  )
}

async function fetchAllExpenseClaimPages(fetchPage, params = {}) {
  const pageSize = Number(params.pageSize || params.page_size || REIMBURSEMENT_LIST_FULL_PAGE_SIZE)
  const normalizedPageSize = Number.isFinite(pageSize) && pageSize > 0
    ? Math.min(REIMBURSEMENT_LIST_FULL_PAGE_SIZE, Math.floor(pageSize))
    : REIMBURSEMENT_LIST_FULL_PAGE_SIZE
  let page = Math.max(1, Math.floor(Number(params.page || 1) || 1))
  const items = []

  for (let index = 0; index < REIMBURSEMENT_LIST_MAX_PAGES; index += 1) {
    const payload = await fetchPage({
      ...params,
      page,
      pageSize: normalizedPageSize
    })

    if (!isPaginatedExpenseClaimPayload(payload)) {
      return extractExpenseClaimItems(payload)
    }

    items.push(...extractExpenseClaimItems(payload))

    const total = Number(payload.total || 0)
    const totalPages = Number(payload.total_pages || 0)
    const hasNext = Boolean(payload.has_next)
    if (!hasNext || (totalPages && page >= totalPages) || (total && items.length >= total)) {
      break
    }
    page += 1
  }

  return items
}

export function fetchExpenseClaims(params = {}, options = {}) {
  return apiRequest(`/reimbursements/claims${buildListQuery(params)}`, options)
}

export function fetchAllExpenseClaims(params = {}) {
  return fetchAllExpenseClaimPages(fetchExpenseClaims, params)
}

export function fetchApprovalExpenseClaims(params = {}, options = {}) {
  return apiRequest(`/reimbursements/claims/approvals${buildListQuery(params)}`, options)
}

export function fetchAllApprovalExpenseClaims(params = {}) {
  return fetchAllExpenseClaimPages(fetchApprovalExpenseClaims, params)
}

export function fetchArchivedExpenseClaims(params = {}, options = {}) {
  return apiRequest(`/reimbursements/claims/archives${buildListQuery(params)}`, options)
}

export function fetchAllArchivedExpenseClaims(params = {}) {
  return fetchAllExpenseClaimPages(fetchArchivedExpenseClaims, params)
}

export function fetchExpenseClaimDetail(claimId) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}`)
}

export function fetchExpenseClaimBudgetAnalysis(claimId) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/budget-analysis`)
}

export function fetchEmployeeLatestProfile(employeeId, params = {}) {
  const query = new URLSearchParams()
  Object.entries(params || {}).forEach(([key, value]) => {
    const normalized = String(value ?? '').trim()
    if (normalized) {
      query.set(key, normalized)
    }
  })
  const suffix = query.toString() ? `?${query.toString()}` : ''
  return apiRequest(`/employee-profiles/${encodeURIComponent(String(employeeId || '').trim())}/latest${suffix}`)
}

export function fetchCurrentEmployeeLatestProfile(params = {}) {
  const query = new URLSearchParams()
  Object.entries(params || {}).forEach(([key, value]) => {
    const normalized = String(value ?? '').trim()
    if (normalized) {
      query.set(key, normalized)
    }
  })
  const suffix = query.toString() ? `?${query.toString()}` : ''
  return apiRequest(`/employee-profiles/me/latest${suffix}`)
}

export function updateExpenseClaim(claimId, payload = {}) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}`, {
    method: 'PATCH',
    body: JSON.stringify(payload)
  })
}

export function acceptExpenseClaimStandardAdjustment(claimId, payload = {}) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/standard-adjustment`, {
    method: 'POST',
    body: JSON.stringify(payload)
  })
}

export function calculateTravelReimbursement(payload = {}) {
  return apiRequest('/reimbursements/travel-calculator', {
    method: 'POST',
    body: JSON.stringify(payload)
  })
}

export function createExpenseClaimItem(claimId, payload = {}) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/items`, {
    method: 'POST',
    body: JSON.stringify(payload)
  })
}

export function deleteExpenseClaimItem(claimId, itemId) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/items/${encodeURIComponent(String(itemId || '').trim())}`, {
    method: 'DELETE'
  })
}

export function uploadExpenseClaimItemAttachment(claimId, itemId, file) {
  const formData = new FormData()
  formData.append('file', file)
  if (file?.receiptId) {
    formData.append('receipt_id', String(file.receiptId))
  }

  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/items/${encodeURIComponent(String(itemId || '').trim())}/attachment`, {
    method: 'POST',
    body: formData,
    contentType: null
  })
}

export function fetchExpenseClaimItemAttachmentMeta(claimId, itemId) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/items/${encodeURIComponent(String(itemId || '').trim())}/attachment/meta`)
}

export function fetchExpenseClaimItemAttachmentPreview(claimId, itemId) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/items/${encodeURIComponent(String(itemId || '').trim())}/attachment/preview`, {
    responseType: 'blob'
  })
}

export function fetchExpenseClaimItemAttachment(claimId, itemId) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/items/${encodeURIComponent(String(itemId || '').trim())}/attachment`, {
    responseType: 'blob'
  })
}

export async function fetchExpenseClaimAttachmentAsset(pathOrUrl) {
  const target = String(pathOrUrl || '').trim()
  if (!target) {
    throw new Error('预览地址为空。')
  }

  if (/^https?:\/\//i.test(target)) {
    const response = await fetch(target)
    if (!response.ok) {
      throw new Error(`预览加载失败（${response.status}）。`)
    }
    return response.blob()
  }

  return apiRequest(target, {
    responseType: 'blob'
  })
}

export function deleteExpenseClaimItemAttachment(claimId, itemId) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/items/${encodeURIComponent(String(itemId || '').trim())}/attachment`, {
    method: 'DELETE'
  })
}

export function updateExpenseClaimItem(claimId, itemId, payload) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/items/${encodeURIComponent(String(itemId || '').trim())}`, {
    method: 'PATCH',
    body: JSON.stringify(payload)
  })
}

function createPreReviewRequestId() {
  if (typeof globalThis.crypto?.randomUUID === 'function') {
    return `pre-review:${globalThis.crypto.randomUUID()}`
  }
  return `pre-review:${Date.now()}:${Math.random().toString(16).slice(2)}`
}

export function createExpenseClaimActionRequestId(action, claimId) {
  const normalizedAction = String(action || 'action').trim() || 'action'
  const normalizedClaimId = String(claimId || 'claim').trim() || 'claim'
  if (typeof globalThis.crypto?.randomUUID === 'function') {
    return `${normalizedAction}:${normalizedClaimId}:${globalThis.crypto.randomUUID()}`
  }
  return `${normalizedAction}:${normalizedClaimId}:${Date.now()}:${Math.random().toString(16).slice(2)}`
}

export function preReviewExpenseClaim(claimId, requestId = '') {
  const normalizedRequestId = String(requestId || '').trim() || createPreReviewRequestId()
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/pre-review`, {
    method: 'POST',
    headers: { 'X-Request-ID': normalizedRequestId },
    body: JSON.stringify({})
  })
}

export function submitExpenseClaim(claimId, payload = {}) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/submit`, {
    method: 'POST',
    body: JSON.stringify(payload || {})
  })
}

export function returnExpenseClaim(claimId, payload = {}) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/return`, {
    method: 'POST',
    body: JSON.stringify(payload)
  })
}

export function approveExpenseClaim(claimId, payload = {}) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/approve`, {
    method: 'POST',
    body: JSON.stringify(payload)
  })
}

export function payExpenseClaim(claimId, payload = {}) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}/pay`, {
    method: 'POST',
    body: JSON.stringify(payload)
  })
}

export function deleteExpenseClaim(claimId) {
  return apiRequest(`/reimbursements/claims/${encodeURIComponent(String(claimId || '').trim())}`, {
    method: 'DELETE'
  })
}
