import http from './http'
import { reflectionApi, type ReflectionObject } from './reflection'
import type { Site, Track } from '@/types/map'
import type { Car, CarState } from '@/types/car'
import type { Mission, MissionStatus } from '@/types/mission'
import { mockSites, mockTracks, mockCars, mockMissions } from '@/mock/server'
import { applyRuntimeEnrichment, deriveCarState } from '@/utils/carRuntime'

/** 设为 true 时使用本地 Mock；默认走 YARP → SimpleLite :8222。
 *  与 auth.ts / config.ts / ops.ts 统一走 VITE_USE_MOCK 开关（替代旧的 VITE_PROJECTION_MOCK）。 */
const MOCK = import.meta.env.VITE_USE_MOCK === 'true'

/** 车体 status 缓存：电量 + 告警信号，避免 3s 轮询打爆 reflection。 */
const STATUS_CACHE_TTL_MS = 4000
const statusCache = new Map<number, { at: number; rows: Array<{ key: string; value: string }> | null }>()

export async function listSites(): Promise<Site[]> {
  if (MOCK) return mockSites()
  const { data } = await http.get<Site[]>('/sl/projection/sites')
  return data
}

export async function listTracks(): Promise<Track[]> {
  if (MOCK) return mockTracks()
  const { data } = await http.get<Track[]>('/sl/projection/tracks')
  return data
}

function mapStatusToCarState(status?: string | null): CarState {
  return deriveCarState({ state: 'idle', lstatus: status ?? undefined }, null)
}

function mapStatusToMissionStatus(status?: string | null): MissionStatus {
  if (!status) return 'queued'
  const s = status.toLowerCase()
  if (/run|运行|执行/.test(s)) return 'running'
  if (/pause|暂停|挂起/.test(s)) return 'paused'
  if (/complete|done|完成|成功/.test(s)) return 'completed'
  if (/cancel|取消|中止/.test(s)) return 'cancelled'
  if (/fail|error|fault|失败|异常/.test(s)) return 'failed'
  if (/assign|分配/.test(s)) return 'assigned'
  return 'queued'
}

function carFromReflection(row: ReflectionObject): Car {
  return {
    id: `C${String(row.id).padStart(2, '0')}`,
    rawId: row.id,
    name: row.name,
    typeName: row.typeName,
    x: 0,
    y: 0,
    theta: 0,
    batterySoc: 0,
    state: mapStatusToCarState(row.status),
    lastUpdate: new Date().toISOString(),
    group: row.layer ?? undefined,
    lstatus: row.status ?? undefined
  }
}

function missionFromReflection(row: ReflectionObject): Mission {
  return {
    id: `M${String(row.id).padStart(2, '0')}`,
    name: row.name,
    typeName: row.typeName,
    priority: 50,
    status: mapStatusToMissionStatus(row.status),
    steps: [],
    createdAt: new Date().toISOString()
  }
}

async function listCarsFromReflection(): Promise<Car[]> {
  const rows = await reflectionApi.listObjects('car')
  return rows.map(carFromReflection)
}

async function listMissionsFromReflection(): Promise<Mission[]> {
  const rows = await reflectionApi.listObjects('mission')
  return rows.map(missionFromReflection)
}

async function loadCarStatus(carId: number): Promise<Array<{ key: string; value: string }> | null> {
  const cached = statusCache.get(carId)
  const now = Date.now()
  if (cached && now - cached.at < STATUS_CACHE_TTL_MS) return cached.rows
  try {
    const status = await reflectionApi.getStatus('car', carId)
    const rows = (status ?? []).map((r) => ({ key: r.key, value: r.value }))
    statusCache.set(carId, { at: now, rows })
    return rows
  } catch {
    statusCache.set(carId, { at: now, rows: cached?.rows ?? null })
    return cached?.rows ?? null
  }
}

/**
 * 纠正投影里写死的 batterySoc=0.8，以及把「正常但未初始化」误标成 fault 的 state。
 * 数据源：反射 status（车体_Soc / AlarmLevel / driveStatus）。
 */
async function enrichCarsRuntime(cars: Car[]): Promise<Car[]> {
  return Promise.all(
    cars.map(async (car) => {
      const id = car.rawId ?? Number(String(car.id).replace(/^C/i, ''))
      // 无车体 status 时也先按 lstatus 纠一次（「正常但未初始化」→ idle）
      if (!Number.isFinite(id) || id <= 0) {
        return applyRuntimeEnrichment(car, null)
      }
      const rows = await loadCarStatus(id)
      return applyRuntimeEnrichment(car, rows)
    })
  )
}

/** 优先走 SimpleLite /projection/cars；502 或空列表时回退 reflection 对象列表（与 3D 场景同源）。 */
export async function listCars(): Promise<Car[]> {
  if (MOCK) return mockCars()
  try {
    const { data } = await http.get<Car[]>('/sl/projection/cars')
    if (Array.isArray(data) && data.length > 0) {
      return enrichCarsRuntime(data)
    }
    const fallback = await listCarsFromReflection()
    if (fallback.length > 0) return enrichCarsRuntime(fallback)
    return Array.isArray(data) ? enrichCarsRuntime(data) : []
  } catch {
    return enrichCarsRuntime(await listCarsFromReflection())
  }
}

export async function listMissions(): Promise<Mission[]> {
  if (MOCK) return mockMissions()
  try {
    const { data } = await http.get<Mission[]>('/sl/projection/missions')
    if (Array.isArray(data) && data.length > 0) return data
    const fallback = await listMissionsFromReflection()
    if (fallback.length > 0) return fallback
    return Array.isArray(data) ? data : []
  } catch {
    return listMissionsFromReflection()
  }
}
