import request from '@/config/axios'

export interface RecipeConfigVO {
  id: number
  recipeCode: string
  recipeName?: string
  name?: string
  recipeType?: string | number
  recipeTypeId?: string | number
  productCategoryId?: number
  productId?: number
  productName?: string
  machineName?: string
  machineId?: number
  deviceId?: number
  deviceName?: string
  recipeDesc?: string
  remark?: string
  isEnable?: string | number
  dataUnit?: string
  createTime?: string
}

export interface RecipePointDetailVO {
  id: number
  recipeId: string | number
  attributeId?: number
  pointName?: string
  pointType?: string
  dataType?: string
  dataUnit?: string
  attributeName?: string
  attributeType?: string
}

export interface RecipePointCandidateVO {
  id: number
  pointName: string
  pointType: string
  dataType: string
  dataUnit: string
}

type PageResult<T> = { list: T[]; total: number }

const STORAGE_KEYS = {
  pointCandidates: 'mock:recipeConfig:pointCandidates',
  recipePointRelation: 'mock:recipeConfig:recipePointRelation'
} as const

const safeParseJson = <T>(value: string | null): T | undefined => {
  if (!value) return undefined
  try {
    return JSON.parse(value) as T
  } catch {
    return undefined
  }
}

const loadFromStorage = <T>(key: string, fallback: T): T => {
  const parsed = safeParseJson<T>(window.localStorage.getItem(key))
  return parsed ?? fallback
}

const saveToStorage = (key: string, value: any) => {
  window.localStorage.setItem(key, JSON.stringify(value))
}

const buildMockPointCandidates = (): RecipePointCandidateVO[] => {
  const pointTypes = ['模拟量', '开关量', '计算量']
  const dataTypes = ['int', 'float', 'string', 'bool']
  const units = ['kg', 'm³', '℃', 'A', 'V', '']
  return Array.from({ length: 60 }).map((_, idx) => {
    const no = String(idx + 1).padStart(3, '0')
    return {
      id: idx + 1,
      pointName: `点位-${no}`,
      pointType: pointTypes[idx % pointTypes.length],
      dataType: dataTypes[idx % dataTypes.length],
      dataUnit: units[idx % units.length]
    }
  })
}

const ensureMockSeeded = () => {
  const pointCandidates = loadFromStorage<RecipePointCandidateVO[]>(STORAGE_KEYS.pointCandidates, [])
  if (!pointCandidates.length) saveToStorage(STORAGE_KEYS.pointCandidates, buildMockPointCandidates())

  const relation = loadFromStorage<Record<string, number[]>>(STORAGE_KEYS.recipePointRelation, {})
  if (!Object.keys(relation).length) saveToStorage(STORAGE_KEYS.recipePointRelation, {})
}

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))

const paginate = <T>(items: T[], pageNo: number, pageSize: number): PageResult<T> => {
  const safePageNo = Math.max(1, Number(pageNo) || 1)
  const safePageSize = Math.max(1, Number(pageSize) || 10)
  const start = (safePageNo - 1) * safePageSize
  return {
    total: items.length,
    list: items.slice(start, start + safePageSize)
  }
}

const contains = (value: string | undefined, keyword: string | undefined) => {
  const v = (value ?? '').toLowerCase()
  const k = (keyword ?? '').trim().toLowerCase()
  if (!k) return true
  return v.includes(k)
}

export const RecipeConfigApi = {
  getRecipeConfigPage: async (params: any) => {
    const finalParams = {
      ...(params ?? {}),
      name: params?.name ?? params?.recipeName
    }
    return await request.get({ url: `/iot/recipe/page`, params: finalParams })
  },

  createRecipeConfig: async (data: Partial<RecipeConfigVO>) => {
    const finalData = {
      id: data.id,
      name: data.name ?? data.recipeName,
      recipeCode: data.recipeCode,
      recipeTypeId: (data as any).recipeTypeId ?? data.recipeType,
      productCategoryId: (data as any).productCategoryId,
      productId: data.productId,
      machineId: (data as any).machineId ?? data.deviceId,
      recipeDesc: data.recipeDesc ?? data.remark,
      isEnable: data.isEnable,
      dataUnit: data.dataUnit
    }
    return await request.post({ url: `/iot/recipe/create`, data: finalData })
  },

  updateRecipeConfig: async (data: Partial<RecipeConfigVO>) => {
    const finalData = {
      id: data.id,
      name: data.name ?? data.recipeName,
      recipeCode: data.recipeCode,
      recipeTypeId: (data as any).recipeTypeId ?? data.recipeType,
      productCategoryId: (data as any).productCategoryId,
      productId: data.productId,
      machineId: (data as any).machineId ?? data.deviceId,
      recipeDesc: data.recipeDesc ?? data.remark,
      isEnable: data.isEnable,
      dataUnit: data.dataUnit
    }
    return await request.put({ url: `/iot/recipe/update`, data: finalData })
  },

  deleteRecipeConfig: async (id: number) => {
    return await request.delete({ url: `/iot/recipe/delete?id=` + id })
  },

  exportRecipeConfig: async (params: any) => {
    const finalParams = {
      ...(params ?? {}),
      name: params?.name ?? params?.recipeName
    }
    return await request.download({ url: `/iot/recipe/export-excel`, params: finalParams })
  },

  getPointCandidatePage: async (params: any): Promise<PageResult<RecipePointCandidateVO>> => {
    ensureMockSeeded()
    await sleep(80)
    const keyword = params?.keyword
    const pageNo = params?.pageNo
    const pageSize = params?.pageSize
    const list = loadFromStorage<RecipePointCandidateVO[]>(
      STORAGE_KEYS.pointCandidates,
      buildMockPointCandidates()
    )
    const filtered = keyword
      ? list.filter((item) => contains(item.pointName, keyword))
      : list
    return paginate(filtered, pageNo, pageSize)
  },

  getRecipePointDetailPage: async (params: any) => {
    return await request.get({ url: `/iot/recipe-device-attribute/getList`, params })
  },
  updateRecipeDeviceAttribute: async (data: { recipeId: string | number; ids: number[] }) => {
    return await request.put({ url: `/iot/recipe-device-attribute/update`, data })
  },

  saveRecipePointConfig: async (data: { recipeId: string | number; attributeIds: number[] }) => {
    ensureMockSeeded()
    await sleep(120)
    const relation = loadFromStorage<Record<string, number[]>>(STORAGE_KEYS.recipePointRelation, {})
    relation[String(data.recipeId)] = Array.from(new Set(data.attributeIds ?? [])).filter((v) => {
      return typeof v === 'number' && !Number.isNaN(v)
    })
    saveToStorage(STORAGE_KEYS.recipePointRelation, relation)
    return true
  }
}
