import { existsSync } from "node:fs";
import { join } from "node:path";
import { ATTACHMENTS } from "@/core/constants.js";
import type { JiraAttachment } from "@/types/index.js";

/** Matches on-disk names when Jira attachments are saved under `.hu-bot/`. */
export function sanitizeJiraAttachmentFilename(filename: string): string {
  return filename.replace(/[^a-zA-Z0-9._-]/g, "_");
}

/**
 * Slug for a video's per-attachment subdirectory under `.hu-bot/<job>/assets/videos/`.
 * Strips the extension before sanitizing so the slug is filename-friendly.
 */
export function buildVideoAttachmentSlug(filename: string): string {
  const dot = filename.lastIndexOf(".");
  const stem = dot > 0 ? filename.slice(0, dot) : filename;
  const slug = sanitizeJiraAttachmentFilename(stem);
  return slug.length > 0 ? slug : "video";
}

/**
 * Returns a slug guaranteed not to collide with an existing subdirectory under `baseDir`.
 * Two Jira attachments can share the same stem (e.g. `demo.mp4` on the issue and
 * `demo.mp4` on the parent), which would otherwise cause the second video's frames
 * to overwrite the first's. Appends `_2`, `_3`, … up to a small cap; final fallback
 * is a millisecond timestamp suffix (effectively unique).
 */
export function ensureUniqueVideoSlug(baseDir: string, slug: string): string {
  if (!existsSync(join(baseDir, slug))) return slug;
  for (let i = 2; i < 100; i++) {
    const candidate = `${slug}_${i}`;
    if (!existsSync(join(baseDir, candidate))) return candidate;
  }
  return `${slug}_${Date.now()}`;
}

/**
 * Image attachments from issue + parent, size-filtered and capped. Callers pass `maxImages`
 * (e.g. {@link ATTACHMENTS.MAX_IMAGES} for fix/triage, {@link ATTACHMENTS.MAX_JIRA_ISSUE_IMAGES} for card readiness).
 * Use the same `maxImages` when saving to `.hu-bot/` so prompts match files on disk.
 */
export function selectJiraIssueImageAttachments(
  issueAttachments: JiraAttachment[],
  parentAttachments: JiraAttachment[],
  maxImages: number,
): JiraAttachment[] {
  return [...issueAttachments, ...parentAttachments]
    .filter((a) => a.mimeType.startsWith("image/"))
    .filter((a) => a.size <= ATTACHMENTS.MAX_SIZE_BYTES)
    .slice(0, maxImages);
}

/**
 * Video attachments from issue + parent, mime/size-filtered and capped. Mirrors the image variant.
 * Callers pass `maxVideos` (e.g. {@link ATTACHMENTS.VIDEO.MAX_VIDEOS_PER_TICKET} for fix/triage,
 * {@link ATTACHMENTS.VIDEO.MAX_VIDEOS_READINESS} for card readiness).
 */
export function selectJiraIssueVideoAttachments(
  issueAttachments: JiraAttachment[],
  parentAttachments: JiraAttachment[],
  maxVideos: number,
): JiraAttachment[] {
  const allowed = ATTACHMENTS.VIDEO.MIME_TYPES as readonly string[];
  return [...issueAttachments, ...parentAttachments]
    .filter((a) => allowed.includes(a.mimeType))
    .filter((a) => a.size <= ATTACHMENTS.VIDEO.MAX_SIZE_BYTES)
    .slice(0, maxVideos);
}
