import { listCars, listSites, listTracks } from '@/api/projection'
import { reflectionApi } from '@/api/reflection'
import { getWizardProfile } from '@/api/wizard'
import type { SetupCarParamRow, SetupStatus } from '@/types/setup'

const IP_KEYS = ['address', 'ip']
const PORT_KEYS = ['port', 'magport']

function pick(rows: Array<{ key: string; value: string }>, keys: string[]): string {
  const set = new Set(keys)
  const hit = rows.find((r) => set.has(r.key.toLowerCase()))
  return (hit?.value ?? '').trim()
}

function ipOk(v: string): boolean {
  return v.length > 0 && v !== '0.0.0.0'
}

function portOk(v: string): boolean {
  const n = Number(v)
  return Number.isFinite(n) && n > 0 && n <= 65535
}

async function inspectCarParams(rawId: number, name: string): Promise<SetupCarParamRow> {
  try {
    const fields = await reflectionApi.getFields('car', rawId)
    const address = pick(fields, IP_KEYS)
    const port = pick(fields, PORT_KEYS)
    return { id: rawId, name, address, port, paramsReady: ipOk(address) && portOk(port) }
  } catch {
    return { id: rawId, name, address: '', port: '', paramsReady: false }
  }
}

export async function loadSetupStatus(): Promise<SetupStatus> {
  const empty: SetupStatus = {
    carCount: 0,
    carsWithParams: 0,
    siteCount: 0,
    trackCount: 0,
    carsReady: false,
    mapsReady: false,
    incomplete: true,
    cars: [],
    navigationKinds: [],
    scenarios: [],
    modules: []
  }

  try {
    const [cars, sites, tracks, profile] = await Promise.all([
      listCars().catch(() => []),
      listSites().catch(() => []),
      listTracks().catch(() => []),
      getWizardProfile().catch(() => null)
    ])

    const inspected = await Promise.all(
      cars.slice(0, 40).map((c) => {
        const id = c.rawId ?? Number(String(c.id).replace(/^C/i, ''))
        if (!Number.isFinite(id) || id <= 0) {
          return Promise.resolve({
            id: 0,
            name: c.name,
            address: c.address ?? c.ip ?? '',
            port: '',
            paramsReady: ipOk(c.address ?? c.ip ?? '')
          } satisfies SetupCarParamRow)
        }
        return inspectCarParams(id, c.name)
      })
    )

    const carsWithParams = inspected.filter((c) => c.paramsReady).length
    const couldReadParams = inspected.some((c) => c.address || c.port || c.paramsReady)
    const carsReady = cars.length >= 1 && (!couldReadParams || carsWithParams >= 1)
    const mapsReady = sites.length >= 1 && tracks.length >= 1

    return {
      carCount: cars.length,
      carsWithParams,
      siteCount: sites.length,
      trackCount: tracks.length,
      carsReady,
      mapsReady,
      incomplete: !(carsReady && mapsReady),
      cars: inspected,
      navigationKinds: profile?.navigationKinds ?? [],
      scenarios: profile?.scenarios ?? [],
      modules: profile?.modules ?? []
    }
  } catch (e) {
    return {
      ...empty,
      error: e instanceof Error ? e.message : String(e)
    }
  }
}
