import {execSync} from 'child_process';
import fs from 'fs';
import os from 'os';
import path from 'path';
import {bundle} from '@remotion/bundler';
import {getCompositions, renderStill} from '@remotion/renderer';
import {readDir} from './get-pages.mjs';

const data: {
	id: string;
	title: string;
	relativePath: string;
	compId: string;
	crumb: string | null;
	noAi: boolean;
	slug: string;
}[] = [];
const root = path.join(process.cwd(), 'docs');

const findId = (split, page) => {
	const found = split.find((s) => s.startsWith('id: '));
	if (found) {
		return found.substr('id: '.length);
	}

	return page
		.replace(process.cwd() + path.sep + 'docs' + path.sep, '')
		.replace(/.md$/, '')
		.replace(/.mdx$/, '');
};

const findTitle = (split) => {
	const found = split.find((s) => s.startsWith('title: '));
	if (!found) {
		return null;
	}
	const title = found.replace(/^title:\s/, '');
	if (title.startsWith('"') || title.startsWith("'")) {
		return title.substr(1, title.length - 2);
	}

	return title;
};

const findSlug = (split) => {
	const slugSearch = split.find((s) => s.startsWith('slug: '));
	if (!slugSearch) {
		return null;
	}

	const slug = slugSearch.replace(/^slug:\s/, '');
	if (slug.startsWith('"') || slug.startsWith("'")) {
		return slug.substr(1, slug.length - 2);
	}

	return slug;
};

const findNoAi = (split) => {
	const slugSearch = split.find((s) => s.startsWith('no_ai: true'));
	if (slugSearch) {
		return true;
	}
	return false;
};

const findCrumb = (split) => {
	const crumb = split
		.find((s) => s.startsWith('crumb: '))
		?.replace(/^crumb:\s/, '');
	if (crumb?.startsWith('"') || crumb?.startsWith("'")) {
		return crumb.substr(1, crumb.length - 2);
	}

	return crumb ?? null;
};

const pages = readDir(root);

for (const page of pages) {
	if (page.endsWith('.DS_Store')) {
		continue;
	}

	if (page.endsWith('.tsx')) {
		continue;
	}

	const opened = fs.readFileSync(page, 'utf8');
	const frontmatter =
		opened.match(/---\n((.|\n)*?)---\n/) ??
		opened.match(/---\r\n((.|\r\n)*?)---\r\n/);
	if (!frontmatter) {
		if (page.endsWith('.ts')) {
			continue;
		}
		console.log('No frontmatter for', page);
		continue;
	}

	const split = frontmatter[1].split(os.EOL);
	const id = findId(split, page).replaceAll(path.sep, path.posix.sep);
	const title = findTitle(split);
	const slug = findSlug(split);
	const noAi = findNoAi(split);
	const crumb = findCrumb(split);

	if (!title) {
		console.log('No title for', page, '- skipping');
		continue;
	}

	const relativePath = page
		.replace(process.cwd() + path.sep, '')
		.replaceAll(path.sep, path.posix.sep);

	const compId =
		'articles-' +
		relativePath
			.replaceAll(path.posix.sep, '-')
			.replace(/.md$/, '')
			.replace(/^\//, '')
			.replace(/.mdx$/, '');
	data.push({
		id,
		title,
		relativePath,
		compId,
		crumb,
		noAi,
		slug: (slug && slug.startsWith('/')
			? slug
			: path.join(
					path.dirname(
						relativePath
							.replace(/^docs\//, '')
							.replace(/.md$/, '')
							.replace(/.mdx$/, ''),
					),
					path.basename(slug ?? id),
				)
		).replace(/^\//, ''),
	});
}

data.push(
	{
		id: 'prompts-gallery',
		title: 'Prompt Gallery',
		relativePath: 'src/pages/prompts/index.tsx',
		compId: 'articles-prompts-gallery',
		crumb: null,
		noAi: false,
		slug: 'prompts',
	},
	{
		id: 'prompts-submit',
		title: 'Submit a Prompt',
		relativePath: 'src/pages/prompts/submit.tsx',
		compId: 'articles-prompts-submit',
		crumb: 'Prompts',
		noAi: false,
		slug: 'prompts/submit',
	},
);

fs.writeFileSync(
	path.join(process.cwd(), 'src', 'data', 'articles.ts'),
	`export const articles = ` + JSON.stringify(data, null, 2),
);

execSync('bun x prettier src/data/articles.ts --write');

// render cards
const serveUrl = await bundle({
	entryPoint: path.join(process.cwd(), './src/remotion/entry.ts'),
	publicDir: path.join(process.cwd(), 'static'),
});
const compositions = await getCompositions(serveUrl);

for (const composition of compositions.filter(
	(c) => c.id.startsWith('expert') || c.id.startsWith('template'),
)) {
	const output = `static/generated/${composition.id}.png`;
	if (fs.existsSync(output)) {
		console.log('Existed', composition.id);
		continue;
	} else {
		await renderStill({
			composition,
			output,
			serveUrl,
		});
		console.log('Rendered', composition.id);
	}
}

for (const entry of data) {
	const composition = compositions.find((c) => c.id === entry.compId);
	if (!composition) {
		continue;
	}
	const output = `static/generated/${composition.id}.png`;
	if (fs.existsSync(output)) {
		continue;
	}

	await renderStill({
		composition,
		output,
		serveUrl,
	});
	console.log('Rendered', composition.id);

	if (entry.relativePath.endsWith('.tsx')) {
		continue;
	}

	const out = path.join(process.cwd(), entry.relativePath);
	const fileContents = fs.readFileSync(out, 'utf-8');
	const lines = fileContents
		.split(os.EOL)
		.filter((l) => !l.startsWith('image: '));
	const frontmatterLine = lines.findIndex((l) => l === '---');
	if (frontmatterLine === -1) {
		throw new Error('could not find frontmatter for ' + composition.id);
	}

	const newLines = [
		...lines.slice(0, frontmatterLine + 1),
		`image: /${output.substring('/static'.length)}`,
		...lines.slice(frontmatterLine + 1),
	].join(os.EOL);

	fs.writeFileSync(out, newLines);
}
