export interface Attachment {
  id: string
  type: AttachmentType
  display: string
  url: string
  filename: string
  mediaType: string
  source: AttachmentSource
}

export type AttachmentType = "file" | "text" | "symbol" | "agent"

export type AttachmentSource = FileSource | TextSource | SymbolSource | AgentSource

export interface FileSource {
  type: "file"
  path: string
  mime: string
  data?: Uint8Array
}

export interface TextSource {
  type: "text"
  value: string
}

export interface SymbolSource {
  type: "symbol"
  path: string
  name: string
  kind: number
  range: SymbolRange
}

export interface SymbolRange {
  start: Position
  end: Position
}

export interface Position {
  line: number
  char: number
}

export interface AgentSource {
  type: "agent"
  name: string
}

// Generate UUID with fallback for browsers without crypto.randomUUID
function generateUUID(): string {
  if (typeof crypto !== "undefined" && crypto.randomUUID) {
    return crypto.randomUUID()
  }
  // Fallback: generate a simple UUID v4
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0
    const v = c === "x" ? r : (r & 0x3) | 0x8
    return v.toString(16)
  })
}

export function createFileAttachment(
  path: string,
  filename: string,
  mime: string = "text/plain",
  data?: Uint8Array,
  workspaceRoot?: string,
): Attachment {
  let fileUrl = path
  if (workspaceRoot && !path.startsWith("file://")) {
    const absolutePath = path.startsWith("/") ? path : `${workspaceRoot}/${path}`
    fileUrl = `file://${absolutePath}`
  } else if (!path.startsWith("file://") && path.startsWith("/")) {
    fileUrl = `file://${path}`
  }

  return {
    id: generateUUID(),
    type: "file",
    display: `@${filename}`,
    url: fileUrl,
    filename,
    mediaType: mime,
    source: {
      type: "file",
      path: path,
      mime,
      data,
    },
  }
}

export function createTextAttachment(value: string, display: string, filename: string): Attachment {
  const base64 = encodeTextAsBase64(value)
  return {
    id: generateUUID(),
    type: "text",
    display,
    url: `data:text/plain;base64,${base64}`,
    filename,
    mediaType: "text/plain",
    source: {
      type: "text",
      value,
    },
  }
}

function encodeTextAsBase64(value: string): string {
  if (typeof TextEncoder !== "undefined") {
    const encoder = new TextEncoder()
    const bytes = encoder.encode(value)
    let binary = ""
    const chunkSize = 0x8000
    for (let index = 0; index < bytes.length; index += chunkSize) {
      const chunk = bytes.subarray(index, Math.min(index + chunkSize, bytes.length))
      binary += String.fromCharCode(...chunk)
    }
    return btoa(binary)
  }

  return btoa(
    encodeURIComponent(value).replace(/%([0-9A-F]{2})/g, (_, hex) => String.fromCharCode(Number.parseInt(hex, 16))),
  )
}

export function createAgentAttachment(agentName: string): Attachment {
  return {
    id: generateUUID(),
    type: "agent",
    display: `@${agentName}`,
    url: "",
    filename: agentName,
    mediaType: "text/plain",
    source: {
      type: "agent",
      name: agentName,
    },
  }
}
