/**
 * Generic file import for rNotes.
 *
 * Handles direct import of individual files:
 * - .md / .txt → parse as markdown/text
 * - .html → convert via Turndown
 * - .jpg / .png / .webp / .gif → create IMAGE note with stored file
 *
 * All produce ConvertedNote with sourceRef.source = 'manual'.
 */

import TurndownService from 'turndown';
import { markdownToTiptap, extractPlainTextFromTiptap } from './markdown-tiptap';
import { hashContent } from './index';
import type { ConvertedNote } from './index';
import { isMarkitdownFormat, convertWithMarkitdown } from './markitdown';

const turndown = new TurndownService({ headingStyle: 'atx', codeBlockStyle: 'fenced' });

/** Dispatch file import by extension / MIME type. */
export async function importFile(
	filename: string,
	data: Uint8Array,
	mimeType?: string,
): Promise<ConvertedNote> {
	const ext = filename.substring(filename.lastIndexOf('.')).toLowerCase();
	const textContent = () => new TextDecoder().decode(data);

	if (ext === '.md' || ext === '.markdown') {
		return importMarkdownFile(filename, textContent());
	}
	if (ext === '.txt') {
		return importTextFile(filename, textContent());
	}
	if (ext === '.html' || ext === '.htm') {
		return importHtmlFile(filename, textContent());
	}
	if (['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp'].includes(ext)) {
		return importImageFile(filename, data, mimeType || guessMime(ext));
	}
	if (isMarkitdownFormat(filename)) {
		return importOfficeFile(filename, data, mimeType);
	}

	// Default: treat as text
	try {
		return importTextFile(filename, textContent());
	} catch {
		// Binary file — store as FILE note
		return importBinaryFile(filename, data, mimeType || 'application/octet-stream');
	}
}

/** Import an office file (PDF/DOCX/PPTX/XLSX) via markitdown conversion. */
async function importOfficeFile(
	filename: string,
	data: Uint8Array,
	mimeType?: string,
): Promise<ConvertedNote> {
	const markdown = await convertWithMarkitdown(filename, data);
	const note = importMarkdownFile(filename, markdown);
	// Keep original file as attachment alongside the converted content
	note.attachments = [{ filename, data, mimeType: mimeType || 'application/octet-stream' }];
	return note;
}

/** Import a markdown file. */
export function importMarkdownFile(filename: string, content: string): ConvertedNote {
	const title = titleFromFilename(filename);
	const tiptapJson = markdownToTiptap(content);
	const contentPlain = extractPlainTextFromTiptap(tiptapJson);

	return {
		title,
		content: tiptapJson,
		contentPlain,
		markdown: content,
		tags: [],
		sourceRef: {
			source: 'manual',
			externalId: `file:${filename}`,
			lastSyncedAt: Date.now(),
			contentHash: hashContent(content),
		},
	};
}

/** Import a plain text file — wrap as simple note. */
export function importTextFile(filename: string, content: string): ConvertedNote {
	const title = titleFromFilename(filename);
	const tiptapJson = markdownToTiptap(content);
	const contentPlain = content;

	return {
		title,
		content: tiptapJson,
		contentPlain,
		markdown: content,
		tags: [],
		sourceRef: {
			source: 'manual',
			externalId: `file:${filename}`,
			lastSyncedAt: Date.now(),
			contentHash: hashContent(content),
		},
	};
}

/** Import an HTML file — convert via Turndown. */
export function importHtmlFile(filename: string, html: string): ConvertedNote {
	const title = titleFromFilename(filename);
	const markdown = turndown.turndown(html);
	const tiptapJson = markdownToTiptap(markdown);
	const contentPlain = extractPlainTextFromTiptap(tiptapJson);

	return {
		title,
		content: tiptapJson,
		contentPlain,
		markdown,
		tags: [],
		sourceRef: {
			source: 'manual',
			externalId: `file:${filename}`,
			lastSyncedAt: Date.now(),
			contentHash: hashContent(markdown),
		},
	};
}

/** Import an image file — create IMAGE note with stored file reference. */
export function importImageFile(filename: string, data: Uint8Array, mimeType: string): ConvertedNote {
	const title = titleFromFilename(filename);
	const md = `![${title}](/data/files/uploads/${filename})`;
	const tiptapJson = markdownToTiptap(md);

	return {
		title,
		content: tiptapJson,
		contentPlain: title,
		markdown: md,
		tags: [],
		type: 'IMAGE',
		attachments: [{ filename, data, mimeType }],
		sourceRef: {
			source: 'manual',
			externalId: `file:${filename}`,
			lastSyncedAt: Date.now(),
			contentHash: hashContent(String(data.length)),
		},
	};
}

/** Import a binary/unknown file as a FILE note. */
function importBinaryFile(filename: string, data: Uint8Array, mimeType: string): ConvertedNote {
	const title = titleFromFilename(filename);
	const md = `[${filename}](/data/files/uploads/${filename})`;
	const tiptapJson = markdownToTiptap(md);

	return {
		title,
		content: tiptapJson,
		contentPlain: title,
		markdown: md,
		tags: [],
		type: 'FILE',
		attachments: [{ filename, data, mimeType }],
		sourceRef: {
			source: 'manual',
			externalId: `file:${filename}`,
			lastSyncedAt: Date.now(),
			contentHash: hashContent(String(data.length)),
		},
	};
}

function titleFromFilename(filename: string): string {
	return filename.replace(/\.[^.]+$/, '').replace(/[-_]/g, ' ');
}

function guessMime(ext: string): string {
	const mimes: Record<string, string> = {
		'.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png',
		'.gif': 'image/gif', '.webp': 'image/webp', '.svg': 'image/svg+xml',
		'.bmp': 'image/bmp',
	};
	return mimes[ext] || 'application/octet-stream';
}
