#!/usr/bin/env node
// Dumps a legacy mule-image Postgres into the snapshot JSON shape `run.mjs`
// consumes. Intended to run on the homecloud server where the legacy stack
// lives (since `DATABASE_URL` points at the in-network Postgres there).
//
//   DATABASE_URL=postgres://mulita:mulita@db:5432/mulita \
//   node migrate/legacy_export.mjs > snapshot.json
//
// Uses the `pg` npm package which the legacy mule-image already ships in
// its backend image; if you're running this from a separate workstation,
// `npm install pg` first.

import pg from 'pg';
import process from 'node:process';

const DATABASE_URL = process.env.DATABASE_URL;
if (!DATABASE_URL) {
	console.error('DATABASE_URL required');
	process.exit(2);
}

const client = new pg.Client({ connectionString: DATABASE_URL });
await client.connect();

// ── photos ───────────────────────────────────────────────────────────────────

// Mule-image's photos table is the source of all per-file metadata. The
// migrator only reads fields that have a clean PhotoPrism mapping; the
// rest (auto-tags, ML-derived fields, etc.) are skipped per the merge plan.
const photoRows = await client.query(`
	SELECT
	  p.filepath,
	  p.user_title,
	  p.user_notes,
	  p.rating,
	  p.is_picked,
	  p.is_discarded,
	  p.is_hidden,
	  p.taken_at,
	  COALESCE(
	    array_agg(t.name) FILTER (WHERE t.name IS NOT NULL),
	    '{}'
	  ) AS tags
	FROM photos p
	LEFT JOIN photo_tags pt ON pt.photo_id = p.id
	LEFT JOIN tags t ON t.id = pt.tag_id
	WHERE p.is_active IS NULL OR p.is_active = true
	GROUP BY p.id
`);

// ── heaps + memberships ─────────────────────────────────────────────────────

const heapRows = await client.query(`
	SELECT h.id, h.name FROM heaps h WHERE h.is_active = true
`);

const heapMembers = await client.query(`
	SELECT hp.heap_id, p.filepath
	FROM heap_photos hp
	JOIN photos p ON p.id = hp.photo_id
`);

const membersByHeap = new Map();
for (const r of heapMembers.rows) {
	if (!membersByHeap.has(r.heap_id)) membersByHeap.set(r.heap_id, []);
	membersByHeap.get(r.heap_id).push(r.filepath);
}

// ── assemble ─────────────────────────────────────────────────────────────────

const snapshot = {
	photos: photoRows.rows.map((r) => ({
		filepath: r.filepath,
		user_title: r.user_title,
		user_notes: r.user_notes,
		rating: r.rating,
		is_picked: Boolean(r.is_picked),
		is_discarded: Boolean(r.is_discarded),
		is_hidden: Boolean(r.is_hidden),
		taken_at: r.taken_at ? new Date(r.taken_at).toISOString() : null,
		tags: r.tags ?? []
	})),
	heaps: heapRows.rows.map((h) => ({
		name: h.name,
		photo_filepaths: membersByHeap.get(h.id) ?? []
	}))
};

process.stdout.write(JSON.stringify(snapshot, null, 2));
await client.end();
