<script setup lang="ts">
import { computed, onActivated, onBeforeUnmount, onMounted, ref } from 'vue'
import { AgGridVue } from 'ag-grid-vue3'
import type { CellValueChangedEvent, ColDef } from 'ag-grid-community'
import { AG_GRID_LOCALE_CN } from '@ag-grid-community/locale'
import { myTheme, gridOptions } from '@/lib/diyAgGridOptions'
import localforage from 'localforage'
import { decimalAggSum, roundTo, sumByNumber } from '@/lib/decimal'
import { formatThousands } from '@/lib/numberFormat'
import { industryTypeList } from '@/sql'

interface DetailRow {
  id: string
  groupCode: string
  groupName: string
  majorCode: string
  majorName: string
  hasCost: boolean
  hasArea: boolean
  amount: number | null
  landArea: number | null
  path: string[]
}

interface XmBaseInfoState {
  projectIndustry?: string
}

const props = defineProps<{
  title: string
  rowData: DetailRow[]
  dbKey: string
}>()

const BASE_INFO_KEY = 'xm-base-info-v1'
let persistTimer: ReturnType<typeof setTimeout> | null = null
const activeIndustryId = ref('')
const industryNameMap = new Map(
  industryTypeList.flatMap(item => [
    [String(item.id).trim(), item.name],
    [String(item.type).trim(), item.name]
  ])
)
const totalLabel = computed(() => {
  const industryName = industryNameMap.get(activeIndustryId.value.trim()) || ''
  return industryName ? `${industryName}总投资` : '总投资'
})

const columnDefs: ColDef<DetailRow>[] = [
  {
    headerName: '造价金额(万元)',
    field: 'amount',
    headerClass: 'ag-right-aligned-header',
    minWidth: 100,
    flex: 1,
    editable: params => !params.node?.group && !params.node?.rowPinned && Boolean(params.data?.hasCost),
    cellClass: params =>
      !params.node?.group && !params.node?.rowPinned && params.data?.hasCost
        ? 'ag-right-aligned-cell editable-cell-line'
        : 'ag-right-aligned-cell',
    cellClassRules: {
      'editable-cell-empty': params =>
        !params.node?.group && !params.node?.rowPinned && Boolean(params.data?.hasCost) && (params.value == null || params.value === '')
    },
    aggFunc: decimalAggSum,
    valueParser: params => {
      if (params.newValue === '' || params.newValue == null) return null
      const v = Number(params.newValue)
      return Number.isFinite(v) ? roundTo(v, 2) : null
    },
    valueFormatter: params => {
      if (!params.node?.group && !params.node?.rowPinned && !params.data?.hasCost) {
        return ''
      }
      if (!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')) {
        return '点击输入'
      }
      if (params.value == null) return ''
      return formatThousands(params.value)
    }
  },
  {
    headerName: '用地面积(亩)',
    field: 'landArea',
    headerClass: 'ag-right-aligned-header',
    minWidth: 100,
    flex: 1,
    editable: params => !params.node?.group && !params.node?.rowPinned && Boolean(params.data?.hasArea),
    cellClass: params =>
      !params.node?.group && !params.node?.rowPinned && params.data?.hasArea
        ? 'ag-right-aligned-cell editable-cell-line'
        : 'ag-right-aligned-cell',
    cellClassRules: {
      'editable-cell-empty': params =>
        !params.node?.group && !params.node?.rowPinned && Boolean(params.data?.hasArea) && (params.value == null || params.value === '')
    },
    valueParser: params => {
      if (params.newValue === '' || params.newValue == null) return null
      const v = Number(params.newValue)
      return Number.isFinite(v) ? roundTo(v, 3) : null
    },
    valueFormatter: params => {
      if (!params.node?.group && !params.node?.rowPinned && !params.data?.hasArea) {
        return ''
      }
      if (!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')) {
        return '点击输入'
      }
      if (params.value == null) return ''
      return formatThousands(params.value, 3)
    }
  }
]

const autoGroupColumnDef: ColDef = {
  headerName: '专业编码以及工程专业名称',
  minWidth: 200,
  flex: 2,
  cellRendererParams: {
    suppressCount: true
  },
  valueFormatter: params => {
    if (params.node?.rowPinned) return totalLabel.value
    return String(params.value || '')
  },
  tooltipValueGetter: params => {
    if (params.node?.rowPinned) return totalLabel.value
    return String(params.value || '')
  }
}

const totalAmount = computed(() => sumByNumber(props.rowData, row => row.amount))

const pinnedTopRowData = computed<DetailRow[]>(() => [
  {
    id: 'pinned-total-row',
    groupCode: '',
    groupName: '',
    majorCode: '',
    majorName: totalLabel.value,
    hasCost: false,
    hasArea: false,
    amount: totalAmount.value,
    landArea: null,
    path: ['TOTAL']
  }
])

const saveToIndexedDB = async () => {
  try {
    await localforage.setItem(props.dbKey, {
      detailRows: JSON.parse(JSON.stringify(props.rowData))
    })
  } catch (error) {
    console.error('saveToIndexedDB failed:', error)
  }
}

const onCellValueChanged = (_event: CellValueChangedEvent) => {
  if (persistTimer) clearTimeout(persistTimer)
  persistTimer = setTimeout(() => {
    void saveToIndexedDB()
  }, 1000)
}

const processCellForClipboard = (params: any) => {
  if (Array.isArray(params.value)) {
    return JSON.stringify(params.value)
  }
  return params.value
}

const processCellFromClipboard = (params: any) => {
  try {
    const parsed = JSON.parse(params.value)
    if (Array.isArray(parsed)) return parsed
  } catch (error) {
    // no-op
  }
  return params.value
}

const loadIndustryFromBaseInfo = async () => {
  try {
    const baseInfo = await localforage.getItem<XmBaseInfoState>(BASE_INFO_KEY)
    activeIndustryId.value =
      typeof baseInfo?.projectIndustry === 'string' ? baseInfo.projectIndustry.trim() : ''
  } catch (error) {
    console.error('loadIndustryFromBaseInfo failed:', error)
    activeIndustryId.value = ''
  }
}

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

onActivated(() => {
  void loadIndustryFromBaseInfo()
})

onBeforeUnmount(() => {
  if (persistTimer) clearTimeout(persistTimer)
  void saveToIndexedDB()
})
</script>

<template>
  <div class="h-full">
    <div class="rounded-lg border bg-card xmMx scroll-mt-3 flex flex-col overflow-hidden h-full">
      <div class="flex items-center justify-between border-b px-4 py-3">
        <h3 class="text-sm font-semibold text-foreground cursor-pointer select-none transition-colors hover:text-primary">
          {{ props.title }}
        </h3>
        <div class="text-xs text-muted-foreground"></div>
      </div>

      <div class="ag-theme-quartz w-full flex-1 min-h-0 h-full">
        <AgGridVue
          :style="{ height: '100%' }"
          :rowData="props.rowData"
          :pinnedTopRowData="pinnedTopRowData"
          :columnDefs="columnDefs"
          :autoGroupColumnDef="autoGroupColumnDef"
          :gridOptions="gridOptions"
          :theme="myTheme"
          @cell-value-changed="onCellValueChanged"
          :suppressColumnVirtualisation="true"
          :suppressRowVirtualisation="true"
          :cellSelection="{ handle: { mode: 'range' } }"
          :enableClipboard="true"
          :localeText="AG_GRID_LOCALE_CN"
          :tooltipShowDelay="500"
          :headerHeight="50"
          :suppressHorizontalScroll="true"
          :processCellForClipboard="processCellForClipboard"
          :processCellFromClipboard="processCellFromClipboard"
          :undoRedoCellEditing="true"
          :undoRedoCellEditingLimit="20"
        />
      </div>
    </div>
  </div>
</template>
