/**
 * Roam Research JSON → rNotes converter.
 *
 * Import: Roam JSON export ([{ title, children: [{ string, children }] }])
 * Converts recursive tree → indented markdown bullets.
 * Handles Roam syntax: ((block-refs)), {{embed}}, ^^highlight^^, [[page refs]]
 */

import { markdownToTiptap, extractPlainTextFromTiptap } from './markdown-tiptap';
import { registerConverter, hashContent } from './index';
import type { ConvertedNote, ImportInput, ImportResult, ExportOptions, ExportResult, NoteConverter } from './index';
import type { NoteItem } from '../schemas';

interface RoamBlock {
	string?: string;
	uid?: string;
	children?: RoamBlock[];
	'create-time'?: number;
	'edit-time'?: number;
}

interface RoamPage {
	title: string;
	uid?: string;
	children?: RoamBlock[];
	'create-time'?: number;
	'edit-time'?: number;
}

/** Convert Roam block tree to indented markdown. */
function blocksToMarkdown(blocks: RoamBlock[], depth = 0): string {
	const lines: string[] = [];

	for (const block of blocks) {
		if (!block.string && (!block.children || block.children.length === 0)) continue;

		if (block.string) {
			const indent = '  '.repeat(depth);
			const text = convertRoamSyntax(block.string);
			lines.push(`${indent}- ${text}`);
		}

		if (block.children && block.children.length > 0) {
			lines.push(blocksToMarkdown(block.children, depth + 1));
		}
	}

	return lines.join('\n');
}

/** Convert Roam-specific syntax to standard markdown. */
function convertRoamSyntax(text: string): string {
	// [[page references]] → [page references](page references)
	text = text.replace(/\[\[([^\]]+)\]\]/g, '[$1]($1)');

	// ((block refs)) → (ref)
	text = text.replace(/\(\(([a-zA-Z0-9_-]+)\)\)/g, '(ref:$1)');

	// {{embed: ((ref))}} → (embedded ref)
	text = text.replace(/\{\{embed:\s*\(\(([^)]+)\)\)\}\}/g, '> (embedded: $1)');

	// {{[[TODO]]}} and {{[[DONE]]}}
	text = text.replace(/\{\{\[\[TODO\]\]\}\}/g, '- [ ]');
	text = text.replace(/\{\{\[\[DONE\]\]\}\}/g, '- [x]');

	// ^^highlight^^ → ==highlight== (or just **highlight**)
	text = text.replace(/\^\^([^^]+)\^\^/g, '**$1**');

	// **bold** already valid markdown
	// __italic__ → *italic*
	text = text.replace(/__([^_]+)__/g, '*$1*');

	return text;
}

/** Extract tags from Roam page content (inline [[refs]] and #tags). */
function extractRoamTags(blocks: RoamBlock[]): string[] {
	const tags = new Set<string>();

	function walk(items: RoamBlock[]) {
		for (const block of items) {
			if (block.string) {
				// [[page refs]]
				const pageRefs = block.string.match(/\[\[([^\]]+)\]\]/g);
				if (pageRefs) {
					for (const ref of pageRefs) {
						const tag = ref.slice(2, -2).toLowerCase().replace(/\s+/g, '-');
						if (tag.length <= 30) tags.add(tag); // Skip very long refs
					}
				}
				// #tags
				const hashTags = block.string.match(/#([a-zA-Z0-9_-]+)/g);
				if (hashTags) {
					for (const t of hashTags) tags.add(t.slice(1).toLowerCase());
				}
			}
			if (block.children) walk(block.children);
		}
	}

	walk(blocks);
	return Array.from(tags).slice(0, 20); // Cap tags
}

const roamConverter: NoteConverter = {
	id: 'roam',
	name: 'Roam Research',
	requiresAuth: false,

	async import(input: ImportInput): Promise<ImportResult> {
		if (!input.fileData) {
			throw new Error('Roam import requires a JSON file');
		}

		const jsonStr = new TextDecoder().decode(input.fileData);
		let pages: RoamPage[];
		try {
			pages = JSON.parse(jsonStr);
		} catch {
			throw new Error('Invalid Roam Research JSON format');
		}

		if (!Array.isArray(pages)) {
			throw new Error('Expected a JSON array of Roam pages');
		}

		const notes: ConvertedNote[] = [];
		const warnings: string[] = [];

		for (const page of pages) {
			try {
				if (!page.title) continue;

				const children = page.children || [];
				const markdown = children.length > 0
					? blocksToMarkdown(children)
					: '';

				if (!markdown.trim() && children.length === 0) continue; // Skip empty pages

				const tiptapJson = markdownToTiptap(markdown);
				const contentPlain = extractPlainTextFromTiptap(tiptapJson);
				const tags = extractRoamTags(children);

				notes.push({
					title: page.title,
					content: tiptapJson,
					contentPlain,
					markdown,
					tags,
					sourceRef: {
						source: 'roam',
						externalId: page.uid || page.title,
						lastSyncedAt: Date.now(),
						contentHash: hashContent(markdown),
					},
				});
			} catch (err) {
				warnings.push(`Failed to parse page "${page.title}": ${(err as Error).message}`);
			}
		}

		return { notes, notebookTitle: 'Roam Research Import', warnings };
	},

	async export(): Promise<ExportResult> {
		throw new Error('Roam Research export is not supported — use Roam\'s native import');
	},
};

registerConverter(roamConverter);
