/**
 * SC-INT series: sync_conflicts wiring (Fase 9.3).
 *
 * The unit tests in apps/web/src/lib/sync/queue.test.ts cover the
 * conflict-detection logic in isolation. This file exercises the live
 * PostgREST path so we know:
 *
 *   SC-INT-01: a user can insert a row attributed to themselves and read
 *              it back.
 *   SC-INT-02: a user cannot read another user's conflict rows (RLS).
 *   SC-INT-03: UPDATE / DELETE are rejected silently (no policy) so the
 *              table stays append-only at the API surface, not just at
 *              the schema level.
 *
 * The combination of these three is what makes the offline-queue's
 * best-effort logging safe to enable in production.
 */
import { describe, it, expect, afterAll } from 'vitest';
import { createClientAs, createAdminClient } from '../src/supabase-clients.js';
import { closePool } from '../src/db-helpers.js';
import { ANA_ID, BORJA_ID, COLLECTIVE_ID } from '../src/seed-constants.js';

const admin = createAdminClient();
const insertedConflictIds: string[] = [];

afterAll(async () => {
	if (insertedConflictIds.length > 0) {
		await admin.from('sync_conflicts').delete().in('id', insertedConflictIds);
	}
	await closePool();
});

describe('sync_conflicts — RLS + PostgREST contract', () => {
	it('SC-INT-01: a user can insert their own conflict row and read it back', async () => {
		const ana = await createClientAs(ANA_ID);
		const entityId = '00000000-0000-0000-0000-0000000000a1';
		const { data, error } = await ana
			.from('sync_conflicts')
			.insert({
				user_id: ANA_ID,
				collective_id: COLLECTIVE_ID,
				entity_type: 'shopping_item',
				entity_id: entityId,
				local_version: { name: 'ana-local' },
				remote_version: { name: 'ana-remote' },
				resolution: 'remote_won'
			})
			.select('id')
			.single();
		expect(error).toBeNull();
		expect(data?.id).toBeTruthy();
		insertedConflictIds.push(data!.id);

		const { data: rows } = await ana
			.from('sync_conflicts')
			.select('user_id, entity_type, resolution')
			.eq('id', data!.id);
		expect(rows ?? []).toHaveLength(1);
		expect(rows![0].user_id).toBe(ANA_ID);
		expect(rows![0].resolution).toBe('remote_won');
	});

	it('SC-INT-02: a user cannot read another user\'s conflict rows', async () => {
		// Insert as Borja (RLS still has to allow the self-insert).
		const borja = await createClientAs(BORJA_ID);
		const { data, error } = await borja
			.from('sync_conflicts')
			.insert({
				user_id: BORJA_ID,
				collective_id: COLLECTIVE_ID,
				entity_type: 'shopping_item',
				entity_id: '00000000-0000-0000-0000-0000000000b1',
				local_version: { name: 'borja-only' },
				remote_version: { name: 'remote' },
				resolution: 'remote_won'
			})
			.select('id')
			.single();
		expect(error).toBeNull();
		insertedConflictIds.push(data!.id);

		// Ana cannot see it.
		const ana = await createClientAs(ANA_ID);
		const { data: visibleToAna } = await ana
			.from('sync_conflicts')
			.select('id')
			.eq('id', data!.id);
		expect(visibleToAna ?? []).toHaveLength(0);
	});

	it('SC-INT-03: a user cannot impersonate another via user_id at insert time', async () => {
		const ana = await createClientAs(ANA_ID);
		const { data, error } = await ana
			.from('sync_conflicts')
			.insert({
				user_id: BORJA_ID, // not me
				entity_type: 'shopping_item',
				entity_id: '00000000-0000-0000-0000-0000000000a2',
				local_version: {},
				remote_version: {},
				resolution: 'remote_won'
			})
			.select('id')
			.single();
		expect(data).toBeNull();
		expect(error).not.toBeNull();
	});

	it('SC-INT-04: UPDATE / DELETE are denied silently (append-only)', async () => {
		// Insert a row as Ana, then try to update + delete it as Ana.
		const ana = await createClientAs(ANA_ID);
		const { data: inserted, error } = await ana
			.from('sync_conflicts')
			.insert({
				user_id: ANA_ID,
				entity_type: 'shopping_item',
				entity_id: '00000000-0000-0000-0000-0000000000a3',
				local_version: { v: 1 },
				remote_version: { v: 2 },
				resolution: 'remote_won'
			})
			.select('id')
			.single();
		expect(error).toBeNull();
		insertedConflictIds.push(inserted!.id);

		const { data: updated } = await ana
			.from('sync_conflicts')
			.update({ resolution: 'local_won' })
			.eq('id', inserted!.id)
			.select('id');
		expect(updated ?? []).toHaveLength(0); // RLS returns 0 rows updated

		const { data: deleted } = await ana
			.from('sync_conflicts')
			.delete()
			.eq('id', inserted!.id)
			.select('id');
		expect(deleted ?? []).toHaveLength(0);

		// Row is still there.
		const { data: stillThere } = await ana
			.from('sync_conflicts')
			.select('id, resolution')
			.eq('id', inserted!.id)
			.single();
		expect(stillThere?.resolution).toBe('remote_won');
	});
});
