import { createHash } from "node:crypto";
import { readFile, copyFile, mkdir, stat } from "node:fs/promises";
import { resolve, basename, relative } from "node:path";
import type { MediaType } from "../../types.js";
import { withTransaction, ensureInvestigation, now } from "../../db.js";

const REPO_ROOT = process.cwd();

async function sha256File(filePath: string): Promise<string> {
  const buf = await readFile(filePath);
  return createHash("sha256").update(buf).digest("hex");
}

export async function ingestImage(
  filePath: string,
  investigation: string,
  entityId?: string,
  contentId?: string,
  imgType: MediaType = "image",
  notes?: string,
): Promise<string | null> {
  const src = resolve(filePath);
  try {
    await stat(src);
  } catch {
    console.error(`File not found: ${filePath}`);
    return null;
  }

  const digest = await sha256File(src);

  return withTransaction(async (client) => {
    const dup = await client.query<{ id: string }>(
      "SELECT id FROM media WHERE sha256 = $1",
      [digest],
    );
    if (dup.rows.length > 0) {
      console.log(`Duplicate (sha256 match): ${dup.rows[0].id}`);
      return dup.rows[0].id;
    }

    const destDir = resolve(
      REPO_ROOT,
      imgType === "screenshot" ? "screenshots" : "media",
    );
    await mkdir(destDir, { recursive: true });
    const dest = resolve(destDir, basename(src));

    if (resolve(dest) !== resolve(src)) {
      await copyFile(src, dest);
    }

    const mediaId = `${imgType}_${digest.slice(0, 16)}`;

    await ensureInvestigation(client, investigation);
    await client.query(
      `INSERT INTO media(id, investigation_id, entity_id, content_id,
                         type, file_path, sha256, collected_at, notes)
       VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
       ON CONFLICT (id) DO NOTHING`,
      [
        mediaId,
        investigation,
        entityId ?? null,
        contentId ?? null,
        imgType,
        relative(REPO_ROOT, dest),
        digest,
        now(),
        notes ?? null,
      ],
    );

    console.log(`Media saved: ${mediaId} → ${relative(REPO_ROOT, dest)}`);
    return mediaId;
  });
}
