<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { AgGridVue } from 'ag-grid-vue3'
import type { ColDef, GridOptions } from 'ag-grid-community'
import 'ag-grid-enterprise'
	import {

  themeQuartz
} from "ag-grid-community"
import { AG_GRID_LOCALE_CN } from '@ag-grid-community/locale';
// 精简的边框配置（细线条+浅灰色，弱化分割线视觉）
const borderConfig = {
  style: "solid", // 虚线改实线更简洁，也可保留 dotted 但建议用 solid
  width: 0.5,     // 更细的边框，减少视觉干扰
  color: "#e5e7eb" // 浅灰色边框，清新不刺眼
};

// 简洁清新风格的主题配置
const myTheme = themeQuartz.withParams({
  // 核心：移除外边框，减少视觉包裹感
  wrapperBorder: false,
  
  // 表头样式（柔和浅蓝，无加粗，更轻盈）
  headerBackgroundColor: "#f9fafb", // 极浅的背景色，替代深一点的 #e7f3fc
  headerTextColor: "#374151",      // 深灰色文字，比纯黑更柔和
  headerFontSize: 15,              // 字体稍大一点，更易读
  headerFontWeight: "normal",      // 取消加粗，降低视觉重量

  // 行/列/表头边框（统一浅灰细边框）
  rowBorder: borderConfig,
  columnBorder: borderConfig,
  headerRowBorder: borderConfig,
  
  
  // 可选：偶数行背景色（轻微区分，更清新）
  dataBackgroundColor: "#fefefe"
});
interface DictLeaf {
  code: string
  name: string
}

interface DictGroup {
  code: string
  name: string
  children: DictLeaf[]
}

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

interface XmInfoState {
  projectName: string
  detailRows: DetailRow[]
}

const DB_NAME = 'jgjs-pricing-db'
const DB_STORE = 'form-state'
const DB_KEY = 'xm-info-v3'
const DEFAULT_PROJECT_NAME = 'xxx造价咨询服务'

const projectName = ref(DEFAULT_PROJECT_NAME)
const detailRows = ref<DetailRow[]>([])

const detailDict: DictGroup[] = [
  {
    code: 'E1',
    name: '交通运输工程通用专业',
    children: [
      { code: 'E1-1', name: '征地（用海）补偿' },
      { code: 'E1-2', name: '拆迁补偿' },
      { code: 'E1-3', name: '迁改工程' },
      { code: 'E1-4', name: '工程建设其他费' }
    ]
  },
  {
    code: 'E2',
    name: '公路工程专业',
    children: [
      { code: 'E2-1', name: '临时工程' },
      { code: 'E2-2', name: '路基工程' },
      { code: 'E2-3', name: '路面工程' },
      { code: 'E2-4', name: '桥涵工程' },
      { code: 'E2-5', name: '隧道工程' },
      { code: 'E2-6', name: '交叉工程' },
      { code: 'E2-7', name: '机电工程' },
      { code: 'E2-8', name: '交通安全设施工程' },
      { code: 'E2-9', name: '绿化及环境保护工程' },
      { code: 'E2-10', name: '房建工程' }
    ]
  },
  {
    code: 'E3',
    name: '铁路工程专业',
    children: [
      { code: 'E3-1', name: '大型临时设施和过渡工程' },
      { code: 'E3-2', name: '路基工程' },
      { code: 'E3-3', name: '桥涵工程' },
      { code: 'E3-4', name: '隧道及明洞工程' },
      { code: 'E3-5', name: '轨道工程' },
      { code: 'E3-6', name: '通信、信号、信息及灾害监测工程' },
      { code: 'E3-7', name: '电力及电力牵引供电工程' },
      { code: 'E3-8', name: '房建工程（房屋建筑及附属工程）' },
      { code: 'E3-9', name: '装饰装修工程' }
    ]
  },
  {
    code: 'E4',
    name: '水运工程专业',
    children: [
      { code: 'E4-1', name: '临时工程' },
      { code: 'E4-2', name: '土建工程' },
      { code: 'E4-3', name: '机电与金属结构工程' },
      { code: 'E4-4', name: '设备工程' },
      { code: 'E4-5', name: '附属房建工程（房屋建筑及附属工程）' }
    ]
  }
]

const codeNameMap = new Map<string, string>()
for (const group of detailDict) {
  codeNameMap.set(group.code, group.name)
  for (const child of group.children) {
    codeNameMap.set(child.code, child.name)
  }
}

const buildDefaultRows = (): DetailRow[] => {
  const rows: DetailRow[] = []
  for (const group of detailDict) {
    for (const child of group.children) {
      rows.push({
        id: `row-${child.code}`,
        groupCode: group.code,
        groupName: group.name,
        majorCode: child.code,
        majorName: child.name,
        amount: null,
        landArea: null,
        path: [group.code, child.code]
      })
    }
  }
  return rows
}

const mergeWithDictRows = (rowsFromDb: DetailRow[] | undefined): DetailRow[] => {
  const dbValueMap = new Map<string, DetailRow>()
  for (const row of rowsFromDb || []) {
    dbValueMap.set(row.majorCode, row)
  }

  return buildDefaultRows().map(row => {
    const fromDb = dbValueMap.get(row.majorCode)
    if (!fromDb) return row

    return {
      ...row,
      amount: typeof fromDb.amount === 'number' ? fromDb.amount : null,
      landArea: typeof fromDb.landArea === 'number' ? fromDb.landArea : null
    }
  })
}

const columnDefs: ColDef<DetailRow>[] = [
 
  {
    headerName: '造价金额(万元)',
    field: 'amount',
    minWidth: 170,
      flex: 1, // 核心：开启弹性布局，自动占满剩余空间

    editable: params => !params.node?.group && !params.node?.rowPinned,
    cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line' : ''),
    cellClassRules: {
      'editable-cell-empty': params =>
        !params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
    },
    aggFunc: 'sum',
    valueParser: params => {
      if (params.newValue === '' || params.newValue == null) return null
      const v = Number(params.newValue)
      return Number.isFinite(v) ? v : null
    },
    valueFormatter: params => {
      if (!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')) {
        return '点击输入'
      }
      if (params.value == null) return ''
      return Number(params.value).toFixed(2)
    }
  },
  {
    headerName: '用地面积(亩)',
    field: 'landArea',
    minWidth: 170,
      flex: 1, // 核心：开启弹性布局，自动占满剩余空间

    editable: params => !params.node?.group && !params.node?.rowPinned,
    cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line' : ''),
    cellClassRules: {
      'editable-cell-empty': params =>
        !params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
    },
    aggFunc: 'sum',
    valueParser: params => {
      if (params.newValue === '' || params.newValue == null) return null
      const v = Number(params.newValue)
      return Number.isFinite(v) ? v : null
    },
    valueFormatter: params => {
      if (!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')) {
        return '点击输入'
      }
      if (params.value == null) return ''
      return Number(params.value).toFixed(2)
    }
  }
]

const autoGroupColumnDef: ColDef = {
  headerName: '专业编码以及工程专业名称',
  minWidth: 320,
  pinned: 'left',
    flex:2, // 核心：开启弹性布局，自动占满剩余空间

  cellRendererParams: {
    suppressCount: true
  },
  valueFormatter: params => {
    if (params.node?.rowPinned) {
      return '总合计'
    }
    const code = String(params.value || '')
    const name = codeNameMap.get(code) || ''
    return name ? `${code} ${name}` : code
  }
}

const gridOptions: GridOptions<DetailRow> = {
  treeData: true,
  animateRows: true,
  singleClickEdit: true,
  suppressClickEdit: false,
  suppressContextMenu: false,
  groupDefaultExpanded: -1,
  suppressFieldDotNotation: true,
  getDataPath: data => data.path,
  getContextMenuItems: () => ['copy', 'paste', 'separator', 'export'],
  defaultColDef: {
    resizable: true,
    sortable: false,
    filter: false
  }
}

const totalAmount = computed(() =>
  detailRows.value.reduce((sum, row) => sum + (row.amount || 0), 0)
)

const totalLandArea = computed(() =>
  detailRows.value.reduce((sum, row) => sum + (row.landArea || 0), 0)
)
const pinnedTopRowData = computed(() => [
  {
    id: 'pinned-total-row',
    groupCode: '',
    groupName: '',
    majorCode: '',
    majorName: '',
    amount: totalAmount.value,
    landArea: totalLandArea.value,
    path: ['TOTAL']
  }
])

const openDB = () =>
  new Promise<IDBDatabase>((resolve, reject) => {
    const request = window.indexedDB.open(DB_NAME, 1)

    request.onupgradeneeded = () => {
      const db = request.result
      if (!db.objectStoreNames.contains(DB_STORE)) {
        db.createObjectStore(DB_STORE)
      }
    }

    request.onsuccess = () => resolve(request.result)
    request.onerror = () => reject(request.error)
  })

const saveToIndexedDB = async () => {
  try {
    const db = await openDB()
    const tx = db.transaction(DB_STORE, 'readwrite')
    const store = tx.objectStore(DB_STORE)

    const payload: XmInfoState = {
      projectName: projectName.value,
      detailRows: detailRows.value
    }

    store.put(payload, DB_KEY)

    await new Promise<void>((resolve, reject) => {
      tx.oncomplete = () => resolve()
      tx.onerror = () => reject(tx.error)
      tx.onabort = () => reject(tx.error)
    })

    db.close()
  } catch (error) {
    console.error('saveToIndexedDB failed:', error)
  }
}

const loadFromIndexedDB = async () => {
  try {
    const db = await openDB()
    const tx = db.transaction(DB_STORE, 'readonly')
    const store = tx.objectStore(DB_STORE)
    const request = store.get(DB_KEY)

    const data = await new Promise<XmInfoState | undefined>((resolve, reject) => {
      request.onsuccess = () => resolve(request.result as XmInfoState | undefined)
      request.onerror = () => reject(request.error)
    })

    await new Promise<void>((resolve, reject) => {
      tx.oncomplete = () => resolve()
      tx.onerror = () => reject(tx.error)
      tx.onabort = () => reject(tx.error)
    })

    db.close()

    if (data) {
      projectName.value = data.projectName || DEFAULT_PROJECT_NAME
      detailRows.value = mergeWithDictRows(data.detailRows)
      return
    }

    detailRows.value = buildDefaultRows()
  } catch (error) {
    console.error('loadFromIndexedDB failed:', error)
    detailRows.value = buildDefaultRows()
  }
}

let persistTimer: ReturnType<typeof setTimeout> | null = null
const schedulePersist = () => {
  if (persistTimer) clearTimeout(persistTimer)
  persistTimer = setTimeout(() => {
    void saveToIndexedDB()
  }, 250)
}

const handleBeforeUnload = () => {
  void saveToIndexedDB()
}

const handleCellValueChanged = () => {
  schedulePersist()
}

watch(projectName, schedulePersist)

onMounted(async () => {
  await loadFromIndexedDB()
  window.addEventListener('beforeunload', handleBeforeUnload)
})

onBeforeUnmount(() => {
  window.removeEventListener('beforeunload', handleBeforeUnload)
  if (persistTimer) clearTimeout(persistTimer)
  void saveToIndexedDB()
})
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 (e) {
    // 解析失败时返回原始值，无需额外处理
  }
  return params.value;
};
</script>

<template>
  <div class="space-y-6">
    <div class="rounded-lg border bg-card p-4 shadow-sm">
      <label class="mb-2 block text-sm font-medium text-foreground">项目名称</label>
      <input
        v-model="projectName"
        type="text"
        placeholder="请输入项目名称"
        class="h-10 w-full max-w-xl rounded-md border bg-background px-3 text-sm outline-none ring-offset-background transition focus-visible:ring-2 focus-visible:ring-ring"
      />
    </div>

    <div class="rounded-lg border bg-card xmMx">
      <div class="flex items-center justify-between border-b px-4 py-3">
        <h3 class="text-sm font-semibold text-foreground">项目明细</h3>
        <div class="text-xs text-muted-foreground">导入导出</div>
      </div>

      <div class="ag-theme-quartz h-[580px] w-full">
         <AgGridVue
    :style="{ height: '100%' }"
    :rowData="detailRows"
    :pinnedTopRowData="pinnedTopRowData"
    :columnDefs="columnDefs"
    :autoGroupColumnDef="autoGroupColumnDef"
    :gridOptions="gridOptions"
    :theme="myTheme"
    @cell-value-changed="handleCellValueChanged"
    :suppressColumnVirtualisation="true"
    :suppressRowVirtualisation="true"
    :cellSelection="{ handle: { mode: 'range' } }"
    :enableClipboard="true"
    :localeText="AG_GRID_LOCALE_CN"
    :tooltipShowDelay="500"
        :headerHeight="50"
    :processCellForClipboard="processCellForClipboard"
    :processCellFromClipboard="processCellFromClipboard"
    :undoRedoCellEditing="true"
    :undoRedoCellEditingLimit="20"

  />
      </div>
    </div>
  </div>
</template>

<style >
.ag-floating-top{
  overflow-y:auto !important
}

.xmMx .editable-cell-line .ag-cell-value {
  display: inline-block;
  min-width: 84%;
  padding: 2px 4px;
  border-bottom: 1px solid #cbd5e1;
}

.xmMx .editable-cell-line.ag-cell-focus .ag-cell-value,
.xmMx .editable-cell-line:hover .ag-cell-value {
  border-bottom-color: #2563eb;
}

.xmMx .editable-cell-empty .ag-cell-value {
  color: #94a3b8 !important;
  font-style: italic;
  opacity: 1 !important;
}

.xmMx .ag-cell.editable-cell-empty,
.xmMx .ag-cell.editable-cell-empty .ag-cell-value {
  color: #94a3b8 !important;
}
</style>
