import { writable } from 'svelte/store';
import { getSupabase } from '$lib/supabase';
import type { Note, NoteColor } from '@colectivo/types';

export const notes = writable<Note[]>([]);
export const notesLoading = writable(false);

// ── Active board (not archived, not in trash) ────────────────────────────────

export async function loadNotes(collectiveId: string) {
	notesLoading.set(true);
	const { data, error } = await getSupabase()
		.from('notes')
		.select('*')
		.eq('collective_id', collectiveId)
		.eq('is_archived', false)
		.is('deleted_at', null)
		.order('is_pinned', { ascending: false })
		.order('updated_at', { ascending: false });

	if (!error && data) {
		notes.set(data as Note[]);
	}
	notesLoading.set(false);
}

export async function loadArchivedNotes(collectiveId: string): Promise<Note[]> {
	const { data } = await getSupabase()
		.from('notes')
		.select('*')
		.eq('collective_id', collectiveId)
		.eq('is_archived', true)
		.is('deleted_at', null)
		.order('updated_at', { ascending: false });
	return (data as Note[]) ?? [];
}

export async function loadTrashedNotes(collectiveId: string): Promise<Note[]> {
	const { data } = await getSupabase()
		.from('notes')
		.select('*')
		.eq('collective_id', collectiveId)
		.not('deleted_at', 'is', null)
		.order('deleted_at', { ascending: false });
	return (data as Note[]) ?? [];
}

export async function loadNote(id: string): Promise<Note | null> {
	const { data } = await getSupabase().from('notes').select('*').eq('id', id).single();
	return (data as Note) ?? null;
}

// ── Mutations ────────────────────────────────────────────────────────────────

export async function createNote(
	collectiveId: string,
	userId: string
): Promise<Note | null> {
	const { data, error } = await getSupabase()
		.from('notes')
		.insert({
			collective_id: collectiveId,
			content: '',
			created_by: userId,
			updated_by: userId
		})
		.select()
		.single();

	if (error || !data) return null;
	notes.update((ns) => [data as Note, ...ns]);
	return data as Note;
}

export async function patchNote(
	id: string,
	userId: string,
	patch: Partial<Pick<Note, 'title' | 'content' | 'color' | 'is_pinned' | 'is_archived' | 'deleted_at'>>
) {
	const fullPatch = { ...patch, updated_by: userId };
	await getSupabase().from('notes').update(fullPatch).eq('id', id);
	notes.update((ns) =>
		ns.map((n) =>
			n.id === id ? { ...n, ...patch, updated_by: userId, updated_at: new Date().toISOString() } : n
		)
	);
}

export async function pinNote(id: string, userId: string) {
	// Pinning forces archive=false (CHECK constraint forbids both true)
	await patchNote(id, userId, { is_pinned: true, is_archived: false });
}

export async function unpinNote(id: string, userId: string) {
	await patchNote(id, userId, { is_pinned: false });
}

export async function archiveNote(id: string, userId: string) {
	await patchNote(id, userId, { is_archived: true, is_pinned: false });
	notes.update((ns) => ns.filter((n) => n.id !== id));
}

export async function unarchiveNote(id: string, userId: string) {
	await patchNote(id, userId, { is_archived: false });
}

export async function trashNote(id: string, userId: string) {
	await patchNote(id, userId, { deleted_at: new Date().toISOString() });
	notes.update((ns) => ns.filter((n) => n.id !== id));
}

export async function restoreNote(id: string, userId: string) {
	await patchNote(id, userId, { deleted_at: null });
}

export async function permanentDeleteNote(id: string) {
	await getSupabase().from('notes').delete().eq('id', id);
}

export async function duplicateNote(note: Note, userId: string): Promise<Note | null> {
	const { data, error } = await getSupabase()
		.from('notes')
		.insert({
			collective_id: note.collective_id,
			title: note.title,
			content: note.content,
			color: note.color,
			created_by: userId,
			updated_by: userId
		})
		.select()
		.single();
	if (error || !data) return null;
	notes.update((ns) => [data as Note, ...ns]);
	return data as Note;
}

export const NOTE_COLORS: NoteColor[] = [
	'yellow',
	'green',
	'blue',
	'pink',
	'purple',
	'orange',
	'gray',
	'red'
];
