import type { ChatMessageAttachment, UploadedFile } from "../../infrastructure/ai/types";

export const TERMINAL_SELECTION_ATTACHMENT_MEDIA_TYPE = "text/plain";

const MAX_PREVIEW_CHARS = 80;

function bytesToBase64(bytes: Uint8Array): string {
  let binary = "";
  const chunkSize = 0x8000;

  for (let i = 0; i < bytes.length; i += chunkSize) {
    const chunk = bytes.subarray(i, i + chunkSize);
    binary += String.fromCharCode(...chunk);
  }

  return btoa(binary);
}

function base64ToText(base64Data: string): string {
  const binary = atob(base64Data);
  const bytes = new Uint8Array(binary.length);

  for (let i = 0; i < binary.length; i += 1) {
    bytes[i] = binary.charCodeAt(i);
  }

  return new TextDecoder().decode(bytes);
}

function buildTimestamp(date: Date): string {
  const pad = (value: number) => String(value).padStart(2, "0");
  return [
    date.getFullYear(),
    pad(date.getMonth() + 1),
    pad(date.getDate()),
    pad(date.getHours()),
    pad(date.getMinutes()),
    pad(date.getSeconds()),
  ].join("-");
}

function getPreviewText(text: string): string {
  const firstLine = text.split(/\r?\n/).find((line) => line.trim().length > 0) ?? "";
  return firstLine.length > MAX_PREVIEW_CHARS
    ? `${firstLine.slice(0, MAX_PREVIEW_CHARS - 1)}...`
    : firstLine;
}

export function createTerminalSelectionAttachment(
  selection: string,
  now: Date = new Date(),
): UploadedFile | null {
  const text = selection.trim();
  if (!text) return null;

  const base64Data = bytesToBase64(new TextEncoder().encode(text));
  const filename = `terminal-selection-${buildTimestamp(now)}.log`;

  return {
    id: crypto.randomUUID(),
    filename,
    dataUrl: `data:${TERMINAL_SELECTION_ATTACHMENT_MEDIA_TYPE};base64,${base64Data}`,
    base64Data,
    mediaType: TERMINAL_SELECTION_ATTACHMENT_MEDIA_TYPE,
    terminalSelection: true,
    previewText: getPreviewText(text),
    lineCount: text.split(/\r?\n/).length,
  };
}

export function decodeTerminalSelectionAttachment(
  attachment: Pick<UploadedFile | ChatMessageAttachment, "base64Data" | "terminalSelection">,
): string | null {
  if (!attachment.terminalSelection) return null;
  return base64ToText(attachment.base64Data);
}

export function isTerminalSelectionAttachment(
  attachment: Pick<UploadedFile | ChatMessageAttachment, "terminalSelection">,
): boolean {
  return attachment.terminalSelection === true;
}

export function buildPromptWithTerminalSelectionAttachments(
  prompt: string,
  attachments: Array<ChatMessageAttachment | UploadedFile>,
): string {
  const terminalBlocks = attachments
    .filter(isTerminalSelectionAttachment)
    .map((attachment, index) => {
      const text = decodeTerminalSelectionAttachment(attachment);
      if (!text) return null;
      const label = attachment.filename || `terminal-selection-${index + 1}.log`;
      return `\n\n[Terminal selection: ${label}]\n${text}`;
    })
    .filter((block): block is string => block !== null);

  if (terminalBlocks.length === 0) return prompt;
  if (!prompt.trim()) return terminalBlocks.join("").trimStart();
  return `${prompt}${terminalBlocks.join("")}`;
}
