/**
 * Minimal host finalize fixture — NOT @platform-modules/uploads module conformance.
 *
 * Demonstrates a host CAN wire upload adoption with authz.md A1/A3/A4/A5 using an
 * in-memory ownership store (no DB, no real R2). Real hosts own bucket/key flow,
 * quota counters, and post-upload magic-byte validation.
 */

export type ParentType = 'a' | 'b'

export interface FinalizeUploadInput {
  actor: string
  parentType: ParentType
  parentId: string
  uploadKey: string
}

export interface OwnershipStore {
  getParentOwner(parentType: ParentType, parentId: string): string | null
  getPendingUploader(uploadKey: string): string | null
  bindUpload(parentType: ParentType, parentId: string, uploadKey: string, actor: string): void
}

export class FinalizeNotFoundError extends Error {
  readonly name = 'FinalizeNotFoundError'
  readonly status = 404

  constructor() {
    super('Not found')
  }
}

export interface MemoryUploadStoreState {
  parents: Map<string, string>
  pending: Map<string, string>
  bindings: Map<string, { parentType: ParentType; parentId: string; actor: string }>
}

export function createMemoryUploadStore(seed?: Partial<MemoryUploadStoreState>): OwnershipStore {
  const parents = seed?.parents ?? new Map<string, string>()
  const pending = seed?.pending ?? new Map<string, string>()
  const bindings = seed?.bindings ?? new Map()

  const parentKey = (parentType: ParentType, parentId: string) => `${parentType}:${parentId}`

  return {
    getParentOwner(parentType, parentId) {
      return parents.get(parentKey(parentType, parentId)) ?? null
    },
    getPendingUploader(uploadKey) {
      return pending.get(uploadKey) ?? null
    },
    bindUpload(parentType, parentId, uploadKey, actor) {
      bindings.set(uploadKey, { parentType, parentId, actor })
      pending.delete(uploadKey)
    },
  }
}

/** Host-owned finalize — authz before any store mutation (A4). */
export function finalizeUpload(store: OwnershipStore, input: FinalizeUploadInput): { ok: true } {
  const { actor, parentType, parentId, uploadKey } = input

  // A3: adoption filters on actor, not the upload key / session id alone.
  const uploader = store.getPendingUploader(uploadKey)
  if (uploader !== actor) {
    throw new FinalizeNotFoundError()
  }

  // A1 + A5: every parentType branch re-checks ownership; absent / foreign-owner → uniform 404.
  const owner = store.getParentOwner(parentType, parentId)
  if (owner !== actor) {
    throw new FinalizeNotFoundError()
  }

  store.bindUpload(parentType, parentId, uploadKey, actor)
  return { ok: true }
}
