import { Schema } from "effect"
import { BusEvent } from "@/bus/bus-event"
import { SessionID } from "@/session/schema"
import { ENV_FEATURE } from "@saeeol/gateway"

const CloseReasonSchema = Schema.Literals(["completed", "error", "interrupted"])

const Event = {
  TurnOpen: BusEvent.define(
    "session.turn.open",
    Schema.Struct({
      sessionID: SessionID,
    }),
  ),
  TurnClose: BusEvent.define(
    "session.turn.close",
    Schema.Struct({
      sessionID: SessionID,
      reason: CloseReasonSchema,
    }),
  ),
}

type CloseReason = Schema.Schema.Type<typeof CloseReasonSchema>

const overrides = new Map<string, string>()
const parents = new Map<string, string>()
const roots = new Map<string, string>()

function register(input: { id: string; parentID?: string; platform?: string }) {
  const root = input.parentID ? (roots.get(input.parentID) ?? input.parentID) : input.id
  const platform = input.platform ?? (input.parentID ? resolvePlatform(input.parentID) : undefined)

  roots.set(input.id, root)
  if (input.parentID) parents.set(input.id, input.parentID)
  if (platform) overrides.set(input.id, platform)
}

function setPlatformOverride(id: string, platform: string) {
  overrides.set(id, platform)
}

function getPlatformOverride(id: string): string | undefined {
  return overrides.get(id)
}

function resolvePlatform(id: string): string | undefined {
  const override = overrides.get(id)
  if (override) return override
  const parent = parents.get(id)
  if (!parent) return undefined
  return resolvePlatform(parent)
}

function resolveRoot(id: string): string {
  return roots.get(id) ?? id
}

function featureForPlatform(platform: string | undefined): string | undefined {
  switch (platform) {
    case "agent-manager":
      return "agent-manager"
    case "vscode":
      return "vscode-extension"
    case "cli":
      return "cli"
    default:
      return undefined
  }
}

function clearPlatformOverride(id: string) {
  overrides.delete(id)
  parents.delete(id)
  roots.delete(id)
}

function attribution(id: string): { rootID: string; feature?: string } {
  const rootID = resolveRoot(id)
  const platform = resolvePlatform(rootID) ?? process.env["SAEEOL_PLATFORM"]
  const feature = featureForPlatform(platform) ?? process.env[ENV_FEATURE]
  return { rootID, ...(feature ? { feature } : {}) }
}

export {
  Event,
  CloseReasonSchema,
  register,
  setPlatformOverride,
  getPlatformOverride,
  resolvePlatform,
  resolveRoot,
  featureForPlatform,
  clearPlatformOverride,
  attribution,
}
export type { CloseReason }
