import { formatOntologyId, type OntologyKind, type OrganizationModel } from '..'
import { getSystem, listAllSystems } from '../helpers'
import type { OmScaffoldPlan } from './types'

export function slugify(input: string): string {
  return input
    .trim()
    .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '')
}

export function titleize(input: string): string {
  return input
    .split(/[-._\s]+/)
    .filter(Boolean)
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ')
}

export function assertSystemPathAvailable(model: OrganizationModel, path: string): void {
  if (getSystem(model, path) !== undefined) {
    throw new Error(`system already exists: ${path}`)
  }

  const parent = parentPathOf(path)
  if (parent !== undefined && getSystem(model, parent) === undefined) {
    throw new Error(`parent system does not exist: ${parent}`)
  }
}

export function assertSystemExists(model: OrganizationModel, path: string): void {
  if (getSystem(model, path) === undefined) {
    throw new Error(`system does not exist: ${path}`)
  }
}

export function parentPathOf(path: string): string | undefined {
  const index = path.lastIndexOf('.')
  return index === -1 ? undefined : path.slice(0, index)
}

export function localIdOf(path: string): string {
  return path.split('.').at(-1) ?? path
}

export function nextSystemOrder(model: OrganizationModel, parentPath?: string): number {
  const siblings =
    parentPath === undefined
      ? listAllSystems(model).filter(({ path }) => !path.includes('.'))
      : listAllSystems(model).filter(({ path }) => parentPathOf(path) === parentPath)
  const maxOrder = siblings.reduce((max, { system }) => Math.max(max, system.order), 0)
  return Math.ceil((maxOrder + 10) / 10) * 10
}

export function ontologyMapName(kind: OntologyKind): string {
  const map: Record<OntologyKind, string> = {
    object: 'objectTypes',
    link: 'linkTypes',
    action: 'actionTypes',
    catalog: 'catalogTypes',
    event: 'eventTypes',
    interface: 'interfaceTypes',
    'value-type': 'valueTypes',
    property: 'sharedProperties',
    group: 'groups',
    endpoint: 'endpoints'
  }
  return map[kind]
}

export function makeOntologyId(systemPath: string, kind: OntologyKind, localId: string): string {
  return formatOntologyId({ scope: systemPath, kind, localId: slugify(localId) })
}

export function addProjectNextStep(plan: OmScaffoldPlan, enabled: boolean, command: string): OmScaffoldPlan {
  if (!enabled) return plan
  return {
    ...plan,
    projectCommand: command,
    nextSteps: [...plan.nextSteps, `Run project handoff: ${command}`]
  }
}
