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

const COMMON_DESTINATION_PREFIXES = [
  '上海',
  '北京',
  '广州',
  '深圳',
  '杭州',
  '南京',
  '苏州',
  '成都',
  '重庆',
  '武汉',
  '西安',
  '天津',
  '宁波',
  '青岛',
  '长沙',
  '郑州',
  '济南',
  '合肥',
  '福州',
  '厦门',
  '昆明',
  '南昌',
  '沈阳',
  '大连',
  '无锡',
  '佛山',
  '东莞'
]

const CHINESE_DAY_NUMBERS = {
  一: 1,
  二: 2,
  两: 2,
  三: 3,
  四: 4,
  五: 5,
  六: 6,
  七: 7,
  八: 8,
  九: 9,
  十: 10
}

const COMPOSER_DATE_RANGE_PREFIX_RE = /^20\d{2}-\d{1,2}-\d{1,2}(?:\s*至\s*20\d{2}-\d{1,2}-\d{1,2})?[，,。\s]*/u
const COMPOSER_LABELED_TIME_PREFIX_RE = /^(?:业务)?发生时间[:：]\s*[^，,。\n]+(?:至\s*[^，,。\n]+)?[，,。\s]*/u

function normalizeComposerText(value) {
  return String(value || '').trim().replace(/\s+/g, ' ')
}

function parseDayCount(value) {
  const text = String(value || '').trim()
  const numericValue = Number.parseInt(text, 10)
  if (Number.isFinite(numericValue) && numericValue > 0) {
    return numericValue
  }
  if (text === '十') {
    return 10
  }
  if (/^十[一二三四五六七八九]$/.test(text)) {
    return 10 + (CHINESE_DAY_NUMBERS[text.slice(1)] || 0)
  }
  if (/^[一二两三四五六七八九]十$/.test(text)) {
    return (CHINESE_DAY_NUMBERS[text.slice(0, 1)] || 1) * 10
  }
  if (/^[一二两三四五六七八九]十[一二三四五六七八九]$/.test(text)) {
    return (CHINESE_DAY_NUMBERS[text.slice(0, 1)] || 1) * 10 + (CHINESE_DAY_NUMBERS[text.slice(2)] || 0)
  }
  return CHINESE_DAY_NUMBERS[text] || 0
}

function calculateBusinessDays(businessTimeContext) {
  const startDate = String(businessTimeContext?.start_date || '').trim()
  const endDate = String(businessTimeContext?.end_date || startDate).trim()
  if (!startDate || !endDate || startDate > endDate) {
    return 0
  }
  const startAt = Date.parse(`${startDate}T00:00:00Z`)
  const endAt = Date.parse(`${endDate}T00:00:00Z`)
  if (!Number.isFinite(startAt) || !Number.isFinite(endAt)) {
    return 0
  }
  return Math.max(1, Math.round((endAt - startAt) / 86400000) + 1)
}

function stripBusinessTimePrefix(text) {
  return normalizeComposerText(text)
    .replace(COMPOSER_LABELED_TIME_PREFIX_RE, '')
    .replace(COMPOSER_DATE_RANGE_PREFIX_RE, '')
    .trim()
}

function resolveDestinationFromText(text) {
  const normalized = normalizeComposerText(text).replace(/\s+/g, '')
  const targetMatch = normalized.match(/(?:出差|去|到|赴|前往)([^，,。；;]+)/u)
  const targetText = String(targetMatch?.[1] || '').trim()
  if (!targetText) {
    return ''
  }

  const knownDestination = COMMON_DESTINATION_PREFIXES.find((item) => targetText.startsWith(item))
  if (knownDestination) {
    return knownDestination
  }

  const verbIndex = targetText.search(/支撑|支持|部署|实施|驻场|出差|拜访|处理|办理|参加|进行|协助|服务器|项目/u)
  if (verbIndex > 0) {
    return targetText.slice(0, verbIndex)
  }
  return targetText.slice(0, 12)
}

function resolveTripDaysFromText(text, businessTimeContext) {
  const dayMatch = normalizeComposerText(text).match(/(?:出差|共|总计)?\s*([0-9]+|[一二两三四五六七八九十]{1,3})\s*天/u)
  const explicitDays = parseDayCount(dayMatch?.[1])
  return explicitDays || calculateBusinessDays(businessTimeContext)
}

function resolveReasonFromText(text, destination) {
  let reason = normalizeComposerText(text)
    .replace(/^(?:出差|去|到|赴|前往)\s*/u, '')
    .trim()

  if (destination && reason.startsWith(destination)) {
    reason = reason.slice(destination.length).trim()
  }

  return reason
    .replace(/[，,。\s]*(?:出差|共|总计)?\s*(?:[0-9]+|[一二两三四五六七八九十]{1,3})\s*天/u, '')
    .replace(/[，,。\s]*(?:申请|发起|办理)?(?:差旅费|差旅|费用)?报销(?:申请)?[。.!！]?$/u, '')
    .replace(/^[，,。；;\s]+|[，,。；;\s]+$/gu, '')
    .trim()
}

export function buildStructuredComposerSubmitText(rawText, businessTimeContext = null) {
  const normalizedText = normalizeComposerText(rawText)
  const timeDisplay = String(
    businessTimeContext?.business_time ||
      businessTimeContext?.time_range ||
      businessTimeContext?.display_value ||
      ''
  ).trim()
  if (!timeDisplay || !normalizedText) {
    return normalizedText
  }

  const bodyText = stripBusinessTimePrefix(normalizedText)
  if (!bodyText) {
    return `发生时间：${timeDisplay}`
  }

  const destination = resolveDestinationFromText(bodyText)
  const reason = resolveReasonFromText(bodyText, destination)
  const days = resolveTripDaysFromText(bodyText, businessTimeContext)
  const lines = [`发生时间：${timeDisplay}`]

  if (destination) {
    lines.push(`地点：${destination}`)
  }
  if (reason) {
    lines.push(`事由：${reason}`)
  }
  if (days > 0 && (days > 1 || /出差|差旅|至/.test(timeDisplay) || /出差|差旅/.test(bodyText))) {
    lines.push(`天数：${days}天`)
  }

  return lines.join('\n')
}

export function useTravelReimbursementComposerTools({
  currentUser,
  activeReviewPayload,
  reviewInlineForm,
  latestReviewMessage,
  currentInsight,
  messages,
  composerDraft,
  composerTextareaRef,
  adjustComposerTextareaHeight,
  scrollToBottom,
  toast,
  calculateTravelReimbursement,
  createMessage,
  buildReviewSlotMap,
  isValidIsoDateString,
  buildLocallySyncedReviewPayload,
  formatDateInputValue,
  onComposerDateSelection
}) {
    const composerDatePickerOpen = ref(false)
    const composerDateMode = ref('single')
    const composerSingleDate = ref(formatDateInputValue())
    const composerRangeStartDate = ref(formatDateInputValue())
    const composerRangeEndDate = ref(formatDateInputValue())
    const composerBusinessTimeTags = ref([])
    const composerBusinessTimeDraftTouched = ref(false)
    const travelCalculatorOpen = ref(false)
    const travelCalculatorBusy = ref(false)
    const travelCalculatorError = ref('')
    const travelCalculatorResult = ref(null)
    const travelCalculatorForm = ref({
      days: '1',
      location: ''
    })
    const composerCanApplyDateSelection = computed(() => {
      if (composerDateMode.value === 'single') {
        return Boolean(composerSingleDate.value)
      }
      return Boolean(
        composerRangeStartDate.value
        && composerRangeEndDate.value
        && composerRangeStartDate.value <= composerRangeEndDate.value
      )
    })
    const travelCalculatorCanSubmit = computed(() =>
      !travelCalculatorBusy.value
      && Number(travelCalculatorForm.value.days) >= 1
      && Boolean(String(travelCalculatorForm.value.location || '').trim())
    )
    function buildComposerBusinessTimeLabel() {
      if (composerDateMode.value === 'single') {
        return composerSingleDate.value
      }
      if (composerRangeStartDate.value === composerRangeEndDate.value) {
        return composerRangeStartDate.value
      }
      return `${composerRangeStartDate.value} 至 ${composerRangeEndDate.value}`
    }

    function hasComposerBusinessTimeSelection() {
      return composerBusinessTimeTags.value.length > 0 || composerBusinessTimeDraftTouched.value
    }

    function buildComposerBusinessTimeContextFromSelection() {
      const mode = composerDateMode.value === 'range' ? 'range' : 'single'
      const startDate = String(mode === 'range' ? composerRangeStartDate.value : composerSingleDate.value).trim()
      const endDate = String(mode === 'range' ? composerRangeEndDate.value : startDate).trim()
      if (!isValidIsoDateString(startDate) || !isValidIsoDateString(endDate) || startDate > endDate) {
        return null
      }

      const displayValue = mode === 'range' && startDate !== endDate
        ? `${startDate} 至 ${endDate}`
        : startDate
      return {
        mode,
        start_date: startDate,
        end_date: endDate,
        occurred_date: startDate,
        time_range: displayValue,
        business_time: displayValue,
        time_range_raw: buildComposerBusinessTimeLabel()
      }
    }

    function buildComposerBusinessTimeContext() {
      if (!hasComposerBusinessTimeSelection()) {
        return null
      }

      return buildComposerBusinessTimeContextFromSelection()
    }

    function buildComposerBusinessTimeSelection() {
      const context = buildComposerBusinessTimeContextFromSelection()
      if (!context) {
        return null
      }
      return {
        label: buildComposerBusinessTimeLabel(),
        context,
        mode: context.mode,
        startDate: context.start_date,
        endDate: context.end_date
      }
    }

    function mergeBusinessTimeIntoExtraContext(extraContext, businessTimeContext) {
      if (!businessTimeContext) {
        return extraContext
      }

      const baseReviewFormValues =
        extraContext.review_form_values && typeof extraContext.review_form_values === 'object'
          ? extraContext.review_form_values
          : {}

      return {
        ...extraContext,
        occurred_date: businessTimeContext.occurred_date,
        business_time: businessTimeContext.business_time,
        business_time_context: {
          mode: businessTimeContext.mode,
          start_date: businessTimeContext.start_date,
          end_date: businessTimeContext.end_date,
          display_value: businessTimeContext.business_time
        },
        review_form_values: {
          ...baseReviewFormValues,
          occurred_date: businessTimeContext.occurred_date,
          time_range: businessTimeContext.time_range,
          business_time: businessTimeContext.business_time,
          time_range_raw: businessTimeContext.time_range_raw
        }
      }
    }

    function syncComposerBusinessTimeToReviewCard(businessTimeContext) {
      if (!businessTimeContext || !activeReviewPayload.value) {
        return
      }

      const nextInlineState = {
        ...reviewInlineForm.value,
        occurred_date: businessTimeContext.occurred_date
      }
      const nextReviewPayload = buildLocallySyncedReviewPayload(activeReviewPayload.value, nextInlineState)
      reviewInlineForm.value = nextInlineState
      if (latestReviewMessage.value) {
        latestReviewMessage.value.reviewPayload = nextReviewPayload
      }
      if (currentInsight.value?.agent) {
        currentInsight.value = {
          ...currentInsight.value,
          agent: {
            ...currentInsight.value.agent,
            reviewPayload: nextReviewPayload
          }
        }
      }
    }

    function resolveComposerSubmitText(explicitRawText) {
      const draftPart = String(explicitRawText ?? composerDraft.value).trim()
      const tagPart = composerBusinessTimeTags.value.map((item) => item.label).join('，')
      if (!tagPart) {
        return draftPart
      }
      if (!draftPart) {
        return tagPart
      }
      return `${tagPart}，${draftPart}`
    }

    function resolveComposerDisplaySubmitText(rawText) {
      const businessTimeContext = buildComposerBusinessTimeContext()
      if (!businessTimeContext) {
        return String(rawText || '').trim()
      }
      return buildStructuredComposerSubmitText(rawText, businessTimeContext)
    }

    function toggleComposerDatePicker() {
      composerDatePickerOpen.value = !composerDatePickerOpen.value
      if (composerDatePickerOpen.value) {
        travelCalculatorOpen.value = false
      }
    }

    function closeComposerDatePicker() {
      composerDatePickerOpen.value = false
    }

    function setComposerDateMode(mode) {
      composerDateMode.value = mode === 'range' ? 'range' : 'single'
    }

    async function commitComposerDateSelection({ closePicker = true, focusComposer = true } = {}) {
      if (!composerCanApplyDateSelection.value) {
        return false
      }

      const selection = buildComposerBusinessTimeSelection()
      if (!selection) {
        return false
      }

      const handled = onComposerDateSelection?.(selection) === true
      if (handled) {
        composerBusinessTimeDraftTouched.value = false
        composerBusinessTimeTags.value = []
      } else {
        composerBusinessTimeDraftTouched.value = true
        composerBusinessTimeTags.value = [
          {
            id: `biz-time-${Date.now()}`,
            label: selection.label
          }
        ]
        syncComposerBusinessTimeToReviewCard(selection.context)
      }

      if (closePicker) {
        composerDatePickerOpen.value = false
      }
      await nextTick()
      adjustComposerTextareaHeight()
      if (focusComposer) {
        composerTextareaRef.value?.focus()
      }
      return true
    }

    function handleComposerDateInputChange(part = 'single') {
      if (composerDateMode.value !== 'range' || part === 'single') {
        void commitComposerDateSelection()
        return
      }

      if (part === 'range-start') {
        if (!composerRangeEndDate.value || composerRangeEndDate.value < composerRangeStartDate.value) {
          composerRangeEndDate.value = composerRangeStartDate.value
        }
        if (!onComposerDateSelection) {
          composerBusinessTimeDraftTouched.value = true
          syncComposerBusinessTimeToReviewCard(buildComposerBusinessTimeContextFromSelection())
        }
        return
      }

      void commitComposerDateSelection()
    }

    function removeComposerBusinessTimeTag(tagId) {
      composerBusinessTimeTags.value = composerBusinessTimeTags.value.filter((item) => item.id !== tagId)
      if (!composerBusinessTimeTags.value.length) {
        composerBusinessTimeDraftTouched.value = false
      }
    }

    function handleComposerDatePickerOutside(event) {
      if (!composerDatePickerOpen.value && !travelCalculatorOpen.value) {
        return
      }
      if (event.target instanceof Element && event.target.closest('.composer-date-anchor')) {
        return
      }
      if (event.target instanceof Element && event.target.closest('.travel-calculator-anchor')) {
        return
      }
      if (composerDatePickerOpen.value) {
        composerDatePickerOpen.value = false
      }
      if (travelCalculatorOpen.value && !travelCalculatorBusy.value) {
        travelCalculatorOpen.value = false
      }
    }

    async function applyComposerDateSelection() {
      await commitComposerDateSelection()
    }

    function resolveTravelCalculatorInitialDays() {
      const businessTimeContext = buildComposerBusinessTimeContext()
      if (!businessTimeContext) {
        return 1
      }
      const startDate = businessTimeContext.start_date
      const endDate = businessTimeContext.end_date || startDate
      if (!isValidIsoDateString(startDate) || !isValidIsoDateString(endDate) || startDate > endDate) {
        return 1
      }
      const startAt = Date.parse(`${startDate}T00:00:00Z`)
      const endAt = Date.parse(`${endDate}T00:00:00Z`)
      if (!Number.isFinite(startAt) || !Number.isFinite(endAt)) {
        return 1
      }
      return Math.max(1, Math.round((endAt - startAt) / 86400000) + 1)
    }

    function resolveTravelCalculatorInitialLocation() {
      const slotMap = buildReviewSlotMap(activeReviewPayload.value)
      const candidates = [
        reviewInlineForm.value.location,
        slotMap.business_location?.normalized_value,
        slotMap.business_location?.value,
        slotMap.location?.normalized_value,
        slotMap.location?.value,
        currentUser.value?.location
      ]
      return String(candidates.find((item) => String(item || '').trim()) || '').trim()
    }

    function openTravelCalculator() {
      closeComposerDatePicker()
      travelCalculatorError.value = ''
      travelCalculatorResult.value = null
      travelCalculatorForm.value = {
        days: String(resolveTravelCalculatorInitialDays()),
        location: resolveTravelCalculatorInitialLocation()
      }
      travelCalculatorOpen.value = true
    }

    function toggleTravelCalculator() {
      if (travelCalculatorOpen.value) {
        closeTravelCalculator()
        return
      }
      openTravelCalculator()
    }

    function closeTravelCalculator() {
      if (travelCalculatorBusy.value) {
        return
      }
      travelCalculatorOpen.value = false
    }

    function formatTravelCalculatorMoney(value) {
      const amount = Number(value)
      if (!Number.isFinite(amount)) {
        return String(value || '0')
      }
      return amount.toFixed(2)
    }

    function buildTravelCalculatorResultText(result) {
      const days = Number(result?.days) || 1
      const location = String(result?.location || '').trim() || '未填写地点'
      const matchedCity = String(result?.matched_city || location).trim()
      const grade = String(result?.grade || '').trim() || '当前职级'
      const gradeBandLabel = String(result?.grade_band_label || result?.grade_band || '').trim() || '对应档位'
      const allowanceRegion = String(result?.allowance_region || '').trim() || '默认区域'
      const ruleName = String(result?.rule_name || '').trim() || '公司差旅费报销规则'
      const ruleVersion = String(result?.rule_version || '').trim()
      const hotelRate = formatTravelCalculatorMoney(result?.hotel_rate)
      const hotelAmount = formatTravelCalculatorMoney(result?.hotel_amount)
      const mealRate = formatTravelCalculatorMoney(result?.meal_allowance_rate)
      const basicRate = formatTravelCalculatorMoney(result?.basic_allowance_rate)
      const allowanceRate = formatTravelCalculatorMoney(result?.total_allowance_rate)
      const allowanceAmount = formatTravelCalculatorMoney(result?.allowance_amount)
      const totalAmount = formatTravelCalculatorMoney(result?.total_amount)
      const ruleVersionText = ruleVersion ? `（${ruleVersion}）` : ''
      const user = currentUser.value || {}
      const displayName = String(user.name || user.display_name || user.username || '').trim()
      const greeting = displayName ? `您好，${displayName}，` : '您好，'

      return [
        `${greeting}根据您输入的地点和天数，我匹配到您要出差的地区为：**${matchedCity}**，出差天数为：**${days} 天**，我根据公司的报销文件给您预估金额如下：`,
        '',
        `**参考可报销合计：${totalAmount} 元**`,
        '',
        '| 项目 | 标准口径 | 天数 | 小计 |',
        '| --- | --- | ---: | ---: |',
        `| 住宿费 | ${matchedCity} / ${grade}（${gradeBandLabel}）标准：${hotelRate} 元/天 | ${days} | ${hotelAmount} 元 |`,
        `| 出差补贴 | ${allowanceRegion}：伙食 ${mealRate} 元 + 基本 ${basicRate} 元 = ${allowanceRate} 元/天 | ${days} | ${allowanceAmount} 元 |`,
        '',
        '**计算过程**',
        `1. 住宿费：${hotelRate} × ${days} = ${hotelAmount} 元`,
        `2. 出差补贴：(${mealRate} + ${basicRate}) × ${days} = ${allowanceRate} × ${days} = ${allowanceAmount} 元`,
        `3. 合计：${hotelAmount} + ${allowanceAmount} = ${totalAmount} 元`,
        '',
        `**规则依据**：${ruleName}${ruleVersionText}。出差地点“${location}”匹配为“${matchedCity}”，当前职级“${grade}”匹配“${gradeBandLabel}”档。`,
        '',
        '这个结果是提交前的规则测算参考，最终仍以实际票据、审批意见和财务复核口径为准。'
      ].join('\n')
    }

    async function submitTravelCalculator() {
      if (!travelCalculatorCanSubmit.value) {
        travelCalculatorError.value = '请填写出差天数和地点后再计算。'
        return
      }

      travelCalculatorBusy.value = true
      travelCalculatorError.value = ''
      try {
        const user = currentUser.value || {}
        const payload = await calculateTravelReimbursement({
          days: Math.max(1, Number.parseInt(String(travelCalculatorForm.value.days || '1'), 10) || 1),
          location: String(travelCalculatorForm.value.location || '').trim(),
          grade: String(user.grade || '').trim()
        })
        travelCalculatorResult.value = payload
        messages.value.push(createMessage('assistant', buildTravelCalculatorResultText(payload), [], {
          meta: ['差旅计算器'],
          metaTone: 'low'
        }))
        travelCalculatorOpen.value = false
        nextTick(scrollToBottom)
      } catch (error) {
        travelCalculatorError.value = error?.message || '差旅金额测算失败，请稍后重试。'
      } finally {
        travelCalculatorBusy.value = false
      }
    }

    return {
      composerDatePickerOpen,
      composerDateMode,
      composerSingleDate,
      composerRangeStartDate,
      composerRangeEndDate,
      composerBusinessTimeTags,
      composerBusinessTimeDraftTouched,
      composerCanApplyDateSelection,
      travelCalculatorOpen,
      travelCalculatorBusy,
      travelCalculatorError,
      travelCalculatorResult,
      travelCalculatorForm,
      travelCalculatorCanSubmit,
      buildComposerBusinessTimeLabel,
      hasComposerBusinessTimeSelection,
      buildComposerBusinessTimeSelection,
      buildComposerBusinessTimeContext,
      mergeBusinessTimeIntoExtraContext,
      syncComposerBusinessTimeToReviewCard,
      resolveComposerSubmitText,
      resolveComposerDisplaySubmitText,
      toggleComposerDatePicker,
      closeComposerDatePicker,
      setComposerDateMode,
      handleComposerDateInputChange,
      removeComposerBusinessTimeTag,
      handleComposerDatePickerOutside,
      applyComposerDateSelection,
      resolveTravelCalculatorInitialDays,
      resolveTravelCalculatorInitialLocation,
      openTravelCalculator,
      toggleTravelCalculator,
      closeTravelCalculator,
      formatTravelCalculatorMoney,
      buildTravelCalculatorResultText,
      submitTravelCalculator
    }
}
