<script setup lang="ts">
import { computed, onActivated, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { roundTo } from '@/lib/decimal'
import { parseNumberOrNull } from '@/lib/number'
import { formatThousandsFlexible } from '@/lib/numberFormat'
import { useZxFwPricingStore } from '@/pinia/zxFwPricing'

interface RateMethodState {
  rate: number | null
  budgetFee?: number | null
  remark: string
}

const props = defineProps<{
  storageKey: string
  contractId?: string
  htMainStorageKey?: string
  htRowId?: string
  htMethodType?: 'rate-fee'
}>()
const zxFwPricingStore = useZxFwPricingStore()
const { t } = useI18n()

const rate = ref<number | null>(null)
const remark = ref('')
const rateInput = ref('')
const baseValue = ref<number | null>(null)
const lastSavedSnapshot = ref('')
const useHtMethodState = computed(
  () => Boolean(props.htMainStorageKey && props.htRowId && props.htMethodType)
)
const contractIdText = computed(() => {
  const contractId = String(props.contractId || '').trim()
  return contractId
})
const isReserveFee = computed(() => {
  const mainKey = String(props.htMainStorageKey || '').trim()
  if (mainKey) return mainKey.endsWith('-reserve')
  return String(props.storageKey || '').includes('-reserve')
})
const contractStateSignature = computed(() => {
  const contractId = contractIdText.value
  if (!contractId) return ''
  return JSON.stringify(zxFwPricingStore.contracts[contractId] || null)
})
const additionalWorkStateSignature = computed(() => {
  if (!isReserveFee.value) return ''
  const contractId = contractIdText.value
  if (!contractId) return ''
  const additionalStorageKey = `htExtraFee-${contractId}-additional-work`
  return JSON.stringify(zxFwPricingStore.htFeeMainStates[additionalStorageKey] || null)
})
const baseLabel = computed(() =>
  isReserveFee.value ? t('htFeeRate.reserveBaseLabel') : t('htFeeRate.baseLabel')
)

const budgetFee = computed<number | null>(() => {
  if (baseValue.value == null || rate.value == null) return null
  return roundTo(baseValue.value * rate.value / 100, 2)
})

const formatAmount = (value: number | null) =>
  value == null ? '' : formatThousandsFlexible(value, 3)

const ensureContractLoaded = async () => {
  const contractId = contractIdText.value
  if (!contractId) return
  try {
    await zxFwPricingStore.loadContract(contractId)
    const serviceBase = zxFwPricingStore.getBaseSubtotal(contractId)
    if (!isReserveFee.value) {
      baseValue.value = serviceBase == null ? null : roundTo(serviceBase, 3)
      return
    }
    const additionalStorageKey = `htExtraFee-${contractId}-additional-work`
    const additionalState = await zxFwPricingStore.loadHtFeeMainState<{
      rateFee?: unknown
      hourlyFee?: unknown
      quantityUnitPriceFee?: unknown
    }>(additionalStorageKey)
    const additionalTotal = (additionalState?.detailRows || []).reduce((total, row) => {
      const rateFee = Number(row?.rateFee)
      const hourlyFee = Number(row?.hourlyFee)
      const quantityFee = Number(row?.quantityUnitPriceFee)
      const safeRateFee = Number.isFinite(rateFee) ? rateFee : 0
      const safeHourlyFee = Number.isFinite(hourlyFee) ? hourlyFee : 0
      const safeQuantityFee = Number.isFinite(quantityFee) ? quantityFee : 0
      return total + safeRateFee + safeHourlyFee + safeQuantityFee
    }, 0)
    const serviceBaseSafe = typeof serviceBase === 'number' && Number.isFinite(serviceBase) ? serviceBase : 0
    const hasAny = (serviceBase != null) || additionalTotal !== 0
    baseValue.value = hasAny ? roundTo(serviceBaseSafe + additionalTotal, 3) : null
  } catch (error) {
    console.error('load contract for rate base failed:', error)
    baseValue.value = null
  }
}

const loadForm = async () => {
  try {
    const data = useHtMethodState.value
      ? await zxFwPricingStore.loadHtFeeMethodState<RateMethodState>(
          props.htMainStorageKey!,
          props.htRowId!,
          props.htMethodType!
        )
      : await zxFwPricingStore.loadKeyState<RateMethodState>(props.storageKey)
    rate.value = typeof data?.rate === 'number' ? data.rate : null
    remark.value = typeof data?.remark === 'string' ? data.remark : ''
    rateInput.value = rate.value == null ? '' : String(rate.value)
    const snapshot: RateMethodState = {
      rate: rate.value,
      budgetFee: budgetFee.value,
      remark: remark.value
    }
    lastSavedSnapshot.value = JSON.stringify(snapshot)
  } catch (error) {
    console.error('load rate form failed:', error)
    rate.value = null
    remark.value = ''
    rateInput.value = ''
    lastSavedSnapshot.value = ''
  }
}

const saveForm = async (force = false) => {
  try {
    const payload: RateMethodState = {
      rate: rate.value,
      budgetFee: budgetFee.value,
      remark: remark.value
    }
    const snapshot = JSON.stringify(payload)
    if (!force && snapshot === lastSavedSnapshot.value) return
    if (useHtMethodState.value) {
      zxFwPricingStore.setHtFeeMethodState(
        props.htMainStorageKey!,
        props.htRowId!,
        props.htMethodType!,
        payload,
        { force }
      )
    } else {
      zxFwPricingStore.setKeyState(props.storageKey, payload, { force })
    }
    lastSavedSnapshot.value = snapshot
  } catch (error) {
    console.error('save rate form failed:', error)
  }
}

const applyRateInput = () => {
  const next = parseNumberOrNull(rateInput.value, { sanitize: true, precision: 2 })
  rate.value = next
  rateInput.value = next == null ? '' : String(next)
}



watch([rate, remark, budgetFee], () => {
  void saveForm()
})

watch(
  () => props.storageKey,
  () => {
    void loadForm()
  }
)

watch(
  () => contractIdText.value,
  () => {
    void ensureContractLoaded()
  }
)

watch(
  () => [props.storageKey, props.htMainStorageKey, props.htRowId, props.htMethodType],
  () => {
    void ensureContractLoaded()
  }
)

watch([contractStateSignature, additionalWorkStateSignature], ([nextContractSig, nextAdditionalSig], [prevContractSig, prevAdditionalSig]) => {
  if (nextContractSig === prevContractSig && nextAdditionalSig === prevAdditionalSig) return
  void ensureContractLoaded()
})

onMounted(async () => {
  await Promise.all([ensureContractLoaded(), loadForm()])
})

onActivated(async () => {
  await Promise.all([ensureContractLoaded(), loadForm()])
})

onBeforeUnmount(() => {
  void saveForm(true)
})
</script>

<template>
  <div class="h-full min-h-0 flex flex-col">
    <div class="rounded-lg border bg-card p-4">
      <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
        <label class="space-y-1.5">
          <div class="text-xs text-muted-foreground">{{ baseLabel }}</div>
          <input type="text" :value="baseValue" readonly disabled tabindex="-1"
            class="h-9 w-full cursor-not-allowed rounded-md border bg-muted/40 px-3 text-sm text-foreground select-none" />
        </label>

        <label class="space-y-1.5">
          <div class="text-xs text-muted-foreground">{{ t('htFeeRate.rateLabel') }}</div>
          <input v-model="rateInput" type="text" inputmode="decimal" :placeholder="t('htFeeRate.ratePlaceholder')"
            class="rate-input h-9 w-full rounded-md border bg-background px-3 text-sm text-foreground outline-none focus:ring-2 focus:ring-primary/30"
            @blur="applyRateInput"
            @keydown.enter.prevent="applyRateInput" />
        </label>

        <label class="space-y-1.5">
          <div class="text-xs text-muted-foreground">{{ t('htFeeRate.budgetFeeLabel') }}</div>
          <input type="text" :value="formatAmount(budgetFee)" readonly disabled tabindex="-1"
            class="h-9 w-full cursor-not-allowed rounded-md border bg-muted/40 px-3 text-sm text-foreground select-none" />
        </label>

        <label class="space-y-1.5 md:col-span-2">
          <div class="text-xs text-muted-foreground">{{ t('htFeeRate.remarkLabel') }}</div>
          <textarea v-model="remark" rows="4" :placeholder="t('htFeeRate.remarkPlaceholder')"
            class="w-full rounded-md border bg-background px-3 py-2 text-sm text-foreground outline-none focus:ring-2 focus:ring-primary/30" />
        </label>
      </div>
    </div>
  </div>
</template>

<style scoped>
:deep(.rate-input) {
  text-align: left !important;
}
</style>
