import { ref } from 'vue'
import {
  IntercategoryTree,
  ProductSku,
  ProcessTypeData,
} from '@/types/api/product'
export const processType = ref<ProcessTypeData[]>([
  { label: '烫画', value: 'TH' },
  { label: '直喷', value: 'ZP' },
  { label: '刺绣', value: 'CX' },
  { label: '雕刻', value: 'DK' },
  { label: '白胚', value: 'BP' },
  { label: '其他', value: 'QT' },
])

export const clearNonEmptyChildren = (
  nodes: IntercategoryTree[],
): IntercategoryTree[] => {
  return nodes.map((node) => {
    if (node.children && node.children.length > 0) {
      // 有值的 children 置为空数组
      return { ...node, children: [] }
    }
    // 原本就是 [] 或没有 children 的保持不变
    return node
  })
}
import { computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useOptionsStore } from '@/store/product'
export function useOptions() {
  const store = useOptionsStore()
  const { dataMap } = storeToRefs(store)

  // 获取选项数据（单个或批量统一接口）
  const getOptions = async (
    names: string | string[],
    params?: Record<string, unknown>,
  ) => {
    return store.getOptions(names, params)
  }
  // 清除缓存
  const clearCache = (name?: string) => {
    store.clearCache(name)
  }

  // 直接访问某个选项的响应式数据（用法类似 mapState）
  const useOption = (name: string) => {
    return computed(() => dataMap.value[name] ?? [])
  }

  // 批量获取响应式数据对象（解构使用）
  const useOptionsData = (names: string[]) => {
    return Object.fromEntries(
      names.map((name) => [name, computed(() => dataMap.value[name] ?? [])]),
    )
  }

  return {
    getOptions,
    clearCache,
    useOption,
    useOptionsData,
    dataMap,
  }
}
export function getImageUrl(imgUrl: string, width?: number, height?: number) {
  const patt = new RegExp('http')
  if (patt.test(imgUrl)) {
    if (!width) return imgUrl
    if (/oss/.test(imgUrl)) {
      return imgUrl + '?x-oss-process=image/resize,l_' + width
    }
    if (width && !height) {
      return imgUrl + '?imageView2/2/w/' + width
    } else if (!width && height) {
      return imgUrl + '?imageView2/2/h/' + height
    } else if (width && height) {
      return imgUrl + '?imageView2/1/w/' + width + '/h/' + height
    } else {
      return imgUrl
    }
  }
}
export function cartesianProduct<T>(spec: T[][]): T[][] {
  return spec.reduce(
    (acc, cur) => acc.flatMap((x) => cur.map((y) => [...x, y])),
    [[]] as T[][],
  )
}
export function emptyArray<T>(arr: T[], message?: string): boolean {
  const isEmpty = arr.length === 0
  if (isEmpty) {
    ElMessage({
      message: message || '请至少选择一条记录',
      type: 'warning',
      duration: 1000,
    })
  }
  return isEmpty
}
export function cloneDeep<T>(value: T): T {
  return JSON.parse(JSON.stringify(value))
}

/** 校验所有 SKU 项，返回错误信息数组 */
export function validateSkuItems(skuList: ProductSku[]): string[] {
  const errors: string[] = []
  skuList.forEach((item, index) => {
    const rowErrors: string[] = []
    if (!item.image) rowErrors.push('SKU图片不能为空')
    if (!item.sku_weight) rowErrors.push('商品克重不能为空')
    if (!item.reg_count) rowErrors.push('注册件数不能为空')
    if (!item.factory_price || !item.sales_price)
      rowErrors.push('对外报价不能为空')
    if (rowErrors.length) {
      errors.push(`第${index + 1}行的${rowErrors.join('、')}`)
    }
  })
  return errors
}

/** 生成 color_images 字符串（去重） */
export function generateColorImages(colorMap: Record<string, string>): string {
  const urls = Object.values(colorMap).filter(Boolean)
  return [...new Set(urls)].join(',')
}

/** 最终处理 SKU 列表：排序、补充默认值、清除vxe-table内部字段 */
export function finalizeSkuItems(skuList: ProductSku[]) {
  skuList.forEach((item, idx) => {
    // 排序字段
    item.sort = idx + 1
    // 补充 custom_value
    if (!item.custom_value1 && item.option_enname1) {
      item.custom_value1 = item.option_enname1
    }
    if (!item.custom_value2 && item.option_enname2) {
      item.custom_value2 = item.option_enname2
    }
    // 清除 vxe-table 内部字段
    delete item._X_ROW_KEY
  })
}

/** 计算最小重量 */
export function calculateMinWeight(skuList: ProductSku[]): number {
  if (!skuList.length) return 0
  const weights = skuList
    .map((item) => item.sku_weight)
    .filter((w): w is number => w !== null && w !== undefined)
  return weights.length ? Math.min(...weights) : 0
}
// 比较大对象的异同，并将addList|updateList|deleteList返回

/* ---------- 类型声明 ---------- */
export type IdKey = string | number
export interface HasId {
  id: IdKey
}

/** 数组元素可以是任意对象，但必须包含 id */
export type ArrayItem = { id: IdKey; [key: string]: unknown }

/** 新旧值对比结果 */
export type PatchResult<T extends ArrayItem> = {
  addList?: T[]
  updateList?: (Partial<T> & HasId)[]
  removeList?: IdKey[]
}

/** 整个表单的对比结果 */
export type FormPatch<T extends Record<string, unknown>> = {
  id: IdKey
} & {
  [K in keyof T]?: T[K] extends ArrayItem[] ? PatchResult<T[K][number]> : T[K]
}

/* ---------- 工具函数 ---------- */
/** 判断对象中是否至少有一个属性是数组 */
function itemIsArray(obj: Record<string, unknown>): boolean {
  return Object.values(obj).some(Array.isArray)
}

/** 比较两个数组是否发生变化（长度、id 对应关系） */
function isChange(arr: HasId[] = [], arr1: HasId[] = []): boolean {
  if (arr.length !== arr1.length) return true
  const ids = new Set(arr.map((i) => i.id))
  return arr1.some((i) => !ids.has(i.id))
}

/* ---------- 核心逻辑 ---------- */
export function checkUpdateParams<T extends Record<string, unknown>>(
  newParams: T,
  oldParams: T | null | undefined,
  id: string = 'id',
  other: Record<string, string> = {},
  bool: boolean = false,
): FormPatch<T> | null {
  if (!oldParams)
    return { id: newParams[id as keyof T] } as unknown as FormPatch<T>
  if (newParams[id as keyof T] !== oldParams[id as keyof T])
    return { id: newParams[id as keyof T] } as unknown as FormPatch<T>

  const cloneOld = JSON.parse(JSON.stringify(oldParams)) as T
  const params = { id: newParams[id as keyof T] } as unknown as FormPatch<T>

  for (const key in newParams) {
    const newVal = newParams[key]
    const oldVal = cloneOld[key as keyof T]

    /* ---------- 数组字段 ---------- */
    if (Array.isArray(newVal)) {
      /* 1.没指定主键 → 原样保留 */
      if (!(key in other)) {
        ;(params as Record<string, unknown>)[key] = newVal // ← 直接写回
        continue
      }

      const arr = newVal as ArrayItem[]
      const arr1 = (oldVal as ArrayItem[]) || []
      const addList: ArrayItem[] = []
      const updateList: (ArrayItem & HasId)[] = []
      let removeList: IdKey[] = []

      const keyName = other[key] || id
      const list: ArrayItem[] = []

      for (const iterator of arr) {
        const index = arr1.findIndex(
          (item) => item[keyName] === iterator[keyName],
        )
        const isArr = itemIsArray(iterator)
        if (index !== -1) {
          const item = arr1[index]
          arr1.splice(index, 1) // 从旧数组中移除，剩下的就是要删除的
          const obj: Record<string, unknown> = {}
          for (const k in iterator) {
            if (k === keyName) continue
            if (Array.isArray(iterator[k])) {
              if (isChange(iterator[k] as HasId[], item[k] as HasId[]))
                obj[k] = iterator[k]
            } else if (iterator[k] !== item[k]) {
              obj[k] = iterator[k]
            }
          }
          if (Object.keys(obj).length) {
            const patch = { [keyName]: iterator[keyName], id: item.id, ...obj }
            isArr && !bool ? list.push(patch) : updateList.push(patch)
          }
        } else {
          isArr && !bool ? list.push(iterator) : addList.push(iterator)
        }
      }
      if (arr1.length) removeList = arr1.map((item) => item.id)

      const changeKey = (key as string).replace(/List$/, 'Change') as keyof T
      const res: PatchResult<ArrayItem> = {
        addList: [],
        updateList: [],
        removeList: [],
      }
      // 下面原来逻辑不变，有值就覆盖空数组
      if (addList.length) res.addList = addList
      if (updateList.length) res.updateList = updateList
      if (removeList.length) res.removeList = removeList
      if (list.length)
        (res as unknown as Record<string, unknown>).list = list
        // 不管有没有变化，始终写回 xxChange
      ;(params as Record<string, unknown>)[changeKey as string] = res
    } else {
      /* ---------- 普通字段 ---------- */
      ;(params as Record<string, unknown>)[key] = newVal
    }
  }
  /* ========== 追加：检测非数组字段差异 ========== */
  let basicChanged = false
  for (const key in newParams) {
    const newVal = newParams[key]
    const oldVal = cloneOld[key as keyof T]
    // 只比对非数组、非对象、非函数的基础字段
    if (
      !Array.isArray(newVal) &&
      (typeof newVal !== 'object' || newVal === null) &&
      newVal !== oldVal
    ) {
      basicChanged = true
      break
    }
  }
  if (basicChanged) {
    ;(params as Record<string, unknown>).__dirty = 'isChanged'
  }
  /* 仅 id 相同，无其他变动 */
  if (Object.keys(params).length === 1) return null
  return params
}
export function checkDataChange(
  customChanges: Record<string, unknown> | null | undefined,
): boolean {
  // 如果 customChanges 为 null 或 undefined，直接返回 false
  if (!customChanges) return false
  // 检查 __dirty 字段
  const isDirty = customChanges.__dirty === 'isChanged'
  // 检查是否有包含 "Change" 的键
  const hasChangeKey = Object.keys(customChanges).some(
    (k) => typeof k === 'string' && k.includes('Change'),
  )
  return isDirty || hasChangeKey
}
// 递归查找节点
export function findNodeById(
  nodes: IntercategoryTree[],
  targetId: number,
): IntercategoryTree | null {
  for (const node of nodes) {
    if (node.status === targetId) {
      return node
    }
    if (node.children && node.children.length > 0) {
      const found = findNodeById(node.children, targetId)
      if (found) return found
    }
  }
  return null
}
