<script setup lang="ts">
import { computed, nextTick, onActivated, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { AgGridVue } from 'ag-grid-vue3'
import type { ColDef, GridApi, GridOptions, GridReadyEvent } from 'ag-grid-community'
import { AG_GRID_LOCALE_CN } from '@ag-grid-community/locale'
import { myTheme, gridOptions, agGridWrapClass, agGridStyle } from '@/lib/diyAgGridOptions'
import { withReadonlyAutoHeight } from '@/lib/agGridReadonlyAutoHeight'
import { formatThousandsFlexible } from '@/lib/numberFormat'
import { createScaleAutoGroupColumn } from '@/lib/pricingScaleColumns'
import { buildScaleDetailDict, buildScaleIdLabelMap } from '@/lib/pricingScaleDict'
import { parseProjectIndexFromPathKey } from '@/lib/pricingScaleLink'
import { useZxFwPricingStore } from '@/pinia/zxFwPricing'
import { getMajorDictEntries } from '@/sql'
import type { ScaleDetailRow } from '@/types/pricing'

const props = defineProps<{
  contractId: string
  serviceId: string | number
  method: 'investScale' | 'landScale'
}>()

type MajorLite = {
  code: string
  name: string
  defCoe: number | null
  hasCost?: boolean
  hasArea?: boolean
}

const { t } = useI18n()
const zxFwPricingStore = useZxFwPricingStore()
const gridApi = ref<GridApi<ScaleDetailRow> | null>(null)
let autoHeightTimer: ReturnType<typeof setTimeout> | null = null

const isInvestmentFormula = computed(() => props.method === 'investScale')
const methodLabel = computed(() =>
  isInvestmentFormula.value
    ? t('zxFwView.categories.investmentScaleFormula')
    : t('zxFwView.categories.landScaleFormula')
)

const ensureMethodStateLoaded = async () => {
  await zxFwPricingStore.loadServicePricingMethodState<ScaleDetailRow>(
    props.contractId,
    props.serviceId,
    props.method
  )
}

const methodState = computed(() =>
  zxFwPricingStore.getServicePricingMethodState<ScaleDetailRow>(
    props.contractId,
    props.serviceId,
    props.method
  )
)

const rowData = computed<ScaleDetailRow[]>(() => {
  const rows = methodState.value?.detailRows
  return Array.isArray(rows) ? rows : []
})

const idLabelMap = computed(() => {
  const majorEntries = getMajorDictEntries().map(({ id, item }) => [id, item] as [string, MajorLite])
  const detailDict = buildScaleDetailDict(
    majorEntries,
    isInvestmentFormula.value
      ? ({ hasCost, hasArea }) => hasCost && !hasArea
      : ({ hasArea }) => hasArea
  )
  return buildScaleIdLabelMap(detailDict)
})

const numberFormatter = (params: { value?: unknown }) =>
  typeof params.value === 'number' && Number.isFinite(params.value)
    ? formatThousandsFlexible(params.value, 3)
    : ''

const scaleValueColumnField = computed<keyof ScaleDetailRow>(() =>
  isInvestmentFormula.value ? 'amount' : 'landArea'
)

const scaleValueColumnHeader = computed(() =>
  isInvestmentFormula.value
    ? t('pricingScale.columns.investAmount')
    : t('pricingScale.columns.landArea')
)

const columnDefs = computed<ColDef<ScaleDetailRow>[]>(() =>
  withReadonlyAutoHeight<ScaleDetailRow>([
    {
      headerName: scaleValueColumnHeader.value,
      field: scaleValueColumnField.value,
      minWidth: 130,
      flex: 1,
      headerClass: 'ag-right-aligned-header',
      cellClassRules: {
        'ag-right-aligned-cell': () => true
      },
      valueFormatter: numberFormatter
    },
    {
      headerName: t('pricingScale.columns.basicWork'),
      field: 'benchmarkBudgetBasic',
      minWidth: 130,
      flex: 1,
      headerClass: 'ag-right-aligned-header',
      cellClassRules: {
        'ag-right-aligned-cell': () => true
      },
      valueFormatter: numberFormatter
    },
    {
      headerName: t('zxFwView.formulaColumns.basicFormula'),
      field: 'basicFormula',
      minWidth: 260,
      flex: 2
    },
    {
      headerName: t('pricingScale.columns.optionalWork'),
      field: 'benchmarkBudgetOptional',
      minWidth: 130,
      flex: 1,
      headerClass: 'ag-right-aligned-header',
      cellClassRules: {
        'ag-right-aligned-cell': () => true
      },
      valueFormatter: numberFormatter
    },
    {
      headerName: t('zxFwView.formulaColumns.optionalFormula'),
      field: 'optionalFormula',
      minWidth: 260,
      flex: 2
    }
  ]) as ColDef<ScaleDetailRow>[]
)

const autoGroupColumnDef = computed<ColDef<ScaleDetailRow>>(() =>
  createScaleAutoGroupColumn<ScaleDetailRow>({
    totalLabel: methodLabel.value,
    idLabelMap: idLabelMap.value,
    parseProjectIndexFromPathKey
  })
)

const detailGridOptions: GridOptions<ScaleDetailRow> = {
  ...gridOptions
}

const syncAutoRowHeights = async () => {
  await nextTick()
  const api = gridApi.value
  if (!api || api.isDestroyed?.()) return
  api.resetRowHeights()
  api.onRowHeightChanged()
  api.refreshCells({ force: true })
}

const scheduleAutoRowHeights = () => {
  if (autoHeightTimer) clearTimeout(autoHeightTimer)
  autoHeightTimer = setTimeout(() => {
    autoHeightTimer = null
    void syncAutoRowHeights()
  }, 0)
}

const onGridReady = (event: GridReadyEvent<ScaleDetailRow>) => {
  gridApi.value = event.api
  scheduleAutoRowHeights()
}

watch(rowData, () => {
  scheduleAutoRowHeights()
}, { deep: true })

watch(() => props.method, () => {
  void ensureMethodStateLoaded()
  scheduleAutoRowHeights()
})

onMounted(() => {
  void ensureMethodStateLoaded()
})

onActivated(() => {
  void ensureMethodStateLoaded()
  scheduleAutoRowHeights()
})

onBeforeUnmount(() => {
  if (autoHeightTimer) clearTimeout(autoHeightTimer)
})
</script>

<template>
  <div class="flex h-full min-h-0 flex-col gap-3">
    <div class="flex items-center justify-between gap-3">
      <div>
        <h3 class="text-sm font-semibold text-foreground">{{ methodLabel }}</h3>
        <p class="text-xs text-muted-foreground">{{ t('zxFwView.formulaColumns.subtitle') }}</p>
      </div>
    </div>

    <div :class="agGridWrapClass">
      <AgGridVue
        :theme="myTheme"
        :style="agGridStyle"
        :row-data="rowData"
        :column-defs="columnDefs"
        :auto-group-column-def="autoGroupColumnDef"
        :grid-options="detailGridOptions"
        :locale-text="AG_GRID_LOCALE_CN"
        @grid-ready="onGridReady"
      />
    </div>
  </div>
</template>
