import { oklabDeltaE, oklchToHex } from './oklch'

const WHEEL_STEPS = 12
const HUE_STEP_DEG = 360 / WHEEL_STEPS

/** Visiting order over the 12 wheel positions that maximizes hue distance between
 * consecutively-assigned projects (min circular gap = 3 steps / 90°). */
export const ASSIGNMENT_ORDER: readonly number[] = [0, 4, 8, 2, 6, 10, 1, 5, 9, 3, 7, 11]

/** Lightness/chroma per rotation. Rotation 0 = first pass around the wheel; each
 * further rotation reuses the same 12 hues at a shifted L/C so it reads distinct
 * (ΔE ≥ 20 vs the same hue's rotation-0 color). */
const ROTATIONS: ReadonlyArray<{ l: number; c: number }> = [
  { l: 0.72, c: 0.16 },
  { l: 0.46, c: 0.2 },
]

export type ProjectColor =
  | { source: 'wheel'; hex: string; hue: number; rotation: number; wheelIndex: number }
  | { source: 'override'; hex: string }

export type ProjectColorOverrides = Record<string, string>

function rotationFor(index: number): { l: number; c: number } {
  const rotation = Math.floor(index / WHEEL_STEPS)
  return ROTATIONS[rotation % ROTATIONS.length]!
}

/**
 * Assigns an OKLCH color to the Nth project (0-based `assignmentIndex`), or returns
 * the manual override from collector config if `projectId` has one.
 */
export function assignProjectColor(
  assignmentIndex: number,
  overrides: ProjectColorOverrides = {},
  projectId?: string,
): ProjectColor {
  if (projectId && overrides[projectId]) {
    return { source: 'override', hex: overrides[projectId] }
  }
  const rotation = Math.floor(assignmentIndex / WHEEL_STEPS)
  const wheelIndex = ASSIGNMENT_ORDER[assignmentIndex % WHEEL_STEPS]!
  const hue = wheelIndex * HUE_STEP_DEG
  const { l, c } = rotationFor(assignmentIndex)
  return { source: 'wheel', hex: oklchToHex(l, c, hue), hue, rotation, wheelIndex }
}

/** Assigns colors to an ordered list of project ids, applying any manual overrides. */
export function assignProjectColors(
  projectIds: readonly string[],
  overrides: ProjectColorOverrides = {},
): Record<string, ProjectColor> {
  const out: Record<string, ProjectColor> = {}
  projectIds.forEach((id, i) => {
    out[id] = assignProjectColor(i, overrides, id)
  })
  return out
}

export { oklabDeltaE }
