import type {
  ReflectionAssembly,
  ReflectionKind,
  ReflectionKindMeta,
  ReflectionKv,
  ReflectionMethod,
  ReflectionObject,
  ReflectionTypeMethods
} from '@/api/reflection'
import { CARS } from './cars'
import { MISSIONS } from './missions'
import { SITES } from './sites'
import { TRACKS } from './tracks'

const baseMethods = (typeName: string): ReflectionMethod[] => [
  {
    methodName: 'Reset',
    label: '复位',
    description: `重置 ${typeName} 内部状态`,
    returnType: 'void',
    hasParams: false,
    params: []
  },
  {
    methodName: 'SetEnabled',
    label: '启用 / 禁用',
    returnType: 'void',
    hasParams: true,
    params: [
      { name: 'enabled', typeName: 'Boolean', hasDefault: true, defaultValue: 'true' }
    ]
  }
]

const carMethods: ReflectionMethod[] = [
  ...baseMethods('Car'),
  {
    methodName: 'GoToCharge',
    label: '前往充电',
    returnType: 'void',
    hasParams: true,
    params: [
      { name: 'siteId', typeName: 'Int32', hasDefault: false, defaultValue: null }
    ]
  },
  {
    methodName: 'ForceStop',
    label: '强制停止',
    description: '紧急停车，挂起当前任务',
    returnType: 'void',
    hasParams: false,
    params: []
  }
]

const missionMethods: ReflectionMethod[] = [
  ...baseMethods('Mission'),
  {
    methodName: 'Cancel',
    label: '取消任务',
    returnType: 'void',
    hasParams: false,
    params: []
  },
  {
    methodName: 'Reassign',
    label: '重新分配',
    returnType: 'void',
    hasParams: true,
    params: [
      { name: 'carId', typeName: 'Int32', hasDefault: false, defaultValue: null }
    ]
  }
]

function objectsFor(kind: ReflectionKind): ReflectionObject[] {
  switch (kind) {
    case 'car':
    case 'vehicle':
    case 'script':
      return CARS.map((c, i) => ({
        id: i + 1,
        name: c.name,
        typeName: c.typeName.split('.').pop() ?? c.typeName,
        layer: c.group ?? 'g',
        status: c.state,
        summary: `(${c.x}, ${c.y})`
      }))
    case 'mission':
    case 'process':
      return MISSIONS.map((m, i) => ({
        id: i + 1,
        name: m.name,
        typeName: m.typeName.split('.').pop() ?? m.typeName,
        status: m.status,
        summary: `priority=${m.priority}`
      }))
    case 'site':
      return SITES.map((s, i) => ({
        id: i + 1,
        name: s.name,
        typeName: 'UISite',
        layer: s.layerId ?? 'g',
        summary: `(${s.x}, ${s.y})`
      }))
    case 'track':
      return TRACKS.map((t, i) => ({
        id: i + 1,
        name: `${t.fromSiteId} → ${t.toSiteId}`,
        typeName: 'UITrack',
        layer: 'g',
        summary: t.kind
      }))
    case 'map':
      return [
        { id: 1, name: 'factory_floor', typeName: 'Map', layer: 'g' },
        { id: 2, name: 'grid_overlay', typeName: 'Map', layer: 'overlay' }
      ]
    case 'special':
      return [
        { id: 11, name: 'UIHelper #11', typeName: 'UIHelper', layer: 'helper' }
      ]
    case 'scene':
      // 合成 kind：site + track + special 三者合并，每行带 subKind 字段。
      return [
        ...objectsFor('site').map<ReflectionObject>((o) => ({ ...o, subKind: 'site' })),
        ...objectsFor('track').map<ReflectionObject>((o) => ({ ...o, subKind: 'track' })),
        ...objectsFor('special').map<ReflectionObject>((o) => ({ ...o, subKind: 'special' }))
      ]
    default:
      return []
  }
}

function methodsFor(kind: ReflectionKind): ReflectionMethod[] {
  if (kind === 'car' || kind === 'vehicle' || kind === 'script') return carMethods
  if (kind === 'mission' || kind === 'process') return missionMethods
  return baseMethods(kind)
}

function statusFor(kind: ReflectionKind, id: number): ReflectionKv[] {
  if (kind === 'car' || kind === 'vehicle') {
    const car = CARS[id - 1]
    if (!car) return []
    return [
      { key: '车体_state', value: car.state },
      { key: '车体_batterySoc', value: `${Math.round(car.batterySoc * 100)}%` },
      { key: 'address', value: car.ip ?? '-' },
      { key: 'speed', value: '0.00' }
    ]
  }
  if (kind === 'mission' || kind === 'process') {
    const m = MISSIONS[id - 1]
    if (!m) return []
    return [
      { key: 'status', value: m.status },
      { key: 'priority', value: `${m.priority}` },
      { key: 'carId', value: m.carId ?? '—' }
    ]
  }
  return []
}

function baseFieldsFor(kind: ReflectionKind, id: number): ReflectionKv[] {
  if (kind === 'car' || kind === 'vehicle') {
    const car = CARS[id - 1]
    if (!car) return []
    return [
      { key: 'name', value: car.name, locked: false },
      { key: 'group', value: car.group ?? '', locked: false },
      { key: 'batterySoc', value: `${car.batterySoc}`, locked: false }
    ]
  }
  return [{ key: 'createdAt', value: new Date().toISOString(), locked: true }]
}

// (kind, id) -> { field: value | null（null 表示被删除） }
// 用于演示 mock 模式下 setField / deleteField / execute 的可见效果，避免页面看起来没反应。
const overrideStore = new Map<string, Map<string, string | null>>()
const executionLog = new Map<string, Array<{ method: string; params: Record<string, string>; at: string }>>()

function keyOf(kind: ReflectionKind, id: number) { return `${kind}#${id}` }

function fieldsFor(kind: ReflectionKind, id: number): ReflectionKv[] {
  const base = baseFieldsFor(kind, id)
  const overrides = overrideStore.get(keyOf(kind, id))
  if (!overrides) return base

  const merged: ReflectionKv[] = []
  const seen = new Set<string>()
  for (const b of base) {
    seen.add(b.key)
    if (overrides.has(b.key)) {
      const v = overrides.get(b.key)
      if (v === null) continue
      merged.push({ key: b.key, value: v ?? '', locked: b.locked })
    } else {
      merged.push(b)
    }
  }
  for (const [k, v] of overrides) {
    if (seen.has(k)) continue
    if (v === null) continue
    merged.push({ key: k, value: v ?? '', locked: false })
  }
  return merged
}

export function mockReflectionSetField(kind: ReflectionKind, id: number, field: string, value: string) {
  const k = keyOf(kind, id)
  let m = overrideStore.get(k)
  if (!m) { m = new Map(); overrideStore.set(k, m) }
  m.set(field, value)
  return { kind, id, field, value }
}

export function mockReflectionDeleteField(kind: ReflectionKind, id: number, field: string) {
  const k = keyOf(kind, id)
  let m = overrideStore.get(k)
  if (!m) { m = new Map(); overrideStore.set(k, m) }
  m.set(field, null)
  return { kind, id, field }
}

export function mockReflectionExecute(kind: ReflectionKind, id: number, method: string, params: Record<string, string>) {
  const k = keyOf(kind, id)
  const log = executionLog.get(k) ?? []
  log.unshift({ method, params, at: new Date().toISOString() })
  if (log.length > 20) log.length = 20
  executionLog.set(k, log)

  const ps = Object.keys(params).length ? ` ${JSON.stringify(params)}` : ''
  return { returnValue: `mock(${method})${ps} ok` }
}

export function mockReflectionKinds(): { kinds: ReflectionKindMeta[]; subKinds: Array<ReflectionKindMeta & { parent: string }> } {
  return {
    kinds: [
      { kind: 'map',     count: 2,                                              label: '地图', group: 'primary' },
      { kind: 'car',     count: CARS.length,                                    label: '车辆', group: 'primary' },
      { kind: 'process', count: MISSIONS.length,                                label: '进程', group: 'primary' },
      { kind: 'scene',   count: SITES.length + TRACKS.length + 1,              label: '场景', group: 'primary' },
      { kind: 'script',  count: CARS.length,                                    label: '脚本', group: 'primary' }
    ],
    subKinds: [
      { kind: 'site',    count: SITES.length,  label: '站点',   parent: 'scene' },
      { kind: 'track',   count: TRACKS.length, label: '路径',   parent: 'scene' },
      { kind: 'special', count: 1,             label: '装饰物', parent: 'scene' },
      { kind: 'mission', count: MISSIONS.length, label: '任务', parent: 'process' }
    ]
  }
}

export function mockReflectionAssemblies(): ReflectionAssembly[] {
  return [
    { name: 'SimpleCore', version: '1.0.0' },
    { name: 'SimpleLite', version: '1.0.0' },
    { name: 'StandardScene', version: '1.4.0', location: 'plugins/StandardScene.dll' },
    { name: 'CustomFlightDeck', version: '0.1.0', location: 'plugins/CustomFlightDeck.dll' }
  ]
}

export function mockReflectionObjects(kind: ReflectionKind) {
  return objectsFor(kind)
}

export function mockReflectionMethods(kind: ReflectionKind) {
  return methodsFor(kind)
}

export function mockReflectionMethodsByType(kind: ReflectionKind): ReflectionTypeMethods[] {
  const ms = methodsFor(kind)
  if (kind === 'car' || kind === 'vehicle' || kind === 'script') {
    return [
      { typeName: 'GhostCar', assemblyName: 'StandardScene', methods: ms },
      { typeName: 'DummyCar', assemblyName: 'SimpleLite', methods: ms.slice(0, 2) }
    ]
  }
  if (kind === 'mission' || kind === 'process') {
    return [
      { typeName: 'DeliveryMission', assemblyName: 'StandardScene', methods: ms },
      { typeName: 'PatrolMission', assemblyName: 'CustomFlightDeck', methods: ms.slice(0, 2) }
    ]
  }
  return [{ typeName: kind, assemblyName: 'SimpleLite', methods: ms }]
}

export function mockReflectionStatus(kind: ReflectionKind, id: number) {
  return statusFor(kind, id)
}

export function mockReflectionFields(kind: ReflectionKind, id: number) {
  return fieldsFor(kind, id)
}

export function mockReflectionBundle(kind: ReflectionKind, id: number) {
  const obj = objectsFor(kind).find((o) => o.id === id) ?? {
    id,
    name: `${kind}#${id}`,
    typeName: kind
  }
  const kvs = fieldsFor(kind, id)
  return {
    kind,
    id,
    typeName: obj.typeName,
    assembly: 'mock',
    summary: obj,
    methods: methodsFor(kind),
    status: statusFor(kind, id),
    fields: Object.fromEntries(kvs.map((f) => [f.key, f.value])),
    // Mock 数据全部当 dynamic（mock 模式下没有真实 [FieldMember]）。新版面板期望这个字段。
    fieldList: kvs.map<ReflectionKv>((f) => ({
      key: f.key, value: f.value, source: 'dynamic', typeName: 'String'
    }))
  }
}
