import { Card, DBReader } from "./src/dbreader";
import _ from "lodash";
import { PackDbFetcher } from "./src/packdbfetcher";
import { Banlist, mergeBanlists, readLFList } from "./src/utility";
import moment from "moment";
import fs from 'fs';

const DATE = process.env.DATE;
const lflistPath = process.env.LFLIST_PATH || "./lflist.conf";

const parseEnvList = (envVar: string): number[] => { 
	return (process.env[envVar] || "").split(",").filter(i => i).map(i => parseInt(i.trim()));
}

const includes = parseEnvList("INCLUDES");
const excludes = parseEnvList("EXCLUDES");

const fileSymbol = process.env.FILE_SYMBOL || "cn";

async function getBanlist() {
	const lflistData = await fs.promises.readFile(lflistPath, 'utf-8');
	const lflists = (await readLFList(lflistData)).filter(l => !l.name.includes('TCG')).map(l => ({
		...l,
		date: moment(l.name.split(' ')[0], 'YYYY.MM')
	})).filter(l => l.date.isBefore(DATE));
	const lflist = _.maxBy(lflists, l => l.date.unix());
	const extraLflistPath = `./extras/${fileSymbol}/lflist.conf`;
	const extraLflistPath2 = process.env.EXTRA_LFLIST_PATH;
	const readExtraLflist = async (path?: string): Promise<Banlist | undefined> => {
		if (!path) return undefined;
		try {
			const content = await fs.promises.readFile(path, 'utf-8');
			return (await readLFList(content))[0];
		} catch (e) {
			return undefined;
		}
	};
	const mergeAvailable = (lists: Array<Banlist | undefined>): Banlist | undefined => {
		const valid = lists.filter(Boolean) as Banlist[];
		return valid.length ? mergeBanlists(valid) : undefined;
	};
	const [extraLflist, extraLflist2] = await Promise.all(
		[extraLflistPath, extraLflistPath2].map(readExtraLflist)
	);
	return mergeAvailable([lflist, extraLflist, extraLflist2]);
}

async function main() {
	const dbreader = new DBReader({
		name: "Database",
		//level: Logger.DEBUG
	});
	await dbreader.init();

	const readDbAndInject = async (dbPath: string, target: number[]) => {
		const codes = await dbreader.getAllCardsFromDatabase(dbPath);
		target.push(...codes);
	}

	await Promise.all([
		readDbAndInject(`./extras/${fileSymbol}/includes.cdb`, includes),
		readDbAndInject(`./extras/${fileSymbol}/excludes.cdb`, excludes),
		...(process.env.INCLUDES_DB ? process.env.INCLUDES_DB.split(",").map(dbPath =>
			readDbAndInject(dbPath.trim(), includes)
		) : []),
		...(process.env.EXCLUDES_DB ? process.env.EXCLUDES_DB.split(",").map(dbPath =>
			readDbAndInject(dbPath.trim(), excludes)
		) : []),
	])

	const excludesSet = new Set(excludes);
	const cards = (await PackDbFetcher.fetchOnce(dbreader, `date <= '${DATE}'`))
		.filter(c => !excludesSet.has(c.code));
	const existingIds = new Set(cards.map(c => c.code));
	for (const include of includes) { 
		if (!existingIds.has(include)) {
			cards.push(new Card(include));
		}
	}
	console.log(`Total cards to process: ${cards.length}`);
	
	const extraBanlist = await getBanlist();
	await dbreader.run(cards, {
		extraBanlists: extraBanlist ? [extraBanlist] : undefined,
	});
	process.exit();
}
main();
