import { doltListBranches } from "./branch.js";
import { sql } from "drizzle-orm";

//#region src/dolt/commit.ts
/**
* Stage all changes for commit
* params: { tables?: string[] }
* tables: array of table names to stage
* if no tables are specified, all changes are staged
*/
const doltAdd = (db) => async (params = {}) => {
	if (!params.tables || params.tables.length === 0) await db.execute(sql`SELECT DOLT_ADD('-A')`);
	else {
		const tableParams = params.tables.map((t) => `'${t}'`).join(", ");
		console.log(tableParams);
		await db.execute(sql.raw(`SELECT DOLT_ADD(${tableParams})`));
	}
};
/**
* Commit staged changes
* params: { message: string; author?: { name: string; email: string } }
* message: commit message
* author: commit author
* author is optional, if not provided, the commit will be committed with the default author
*/
const doltCommit = (db) => async (params) => {
	const args = [];
	args.push("'-a'");
	args.push("'-m'", `'${params.message.replace(/'/g, "''")}'`);
	if (params.author) args.push("'--author'", `'${params.author.name} <${params.author.email}>'`);
	await db.execute(sql.raw(`SELECT DOLT_COMMIT(${args.join(", ")})`));
	return "Commit successful";
};
const doltAddAndCommit = (db) => async (params) => {
	await doltAdd(db)({});
	return doltCommit(db)(params);
};
/**
* Get commit log
*/
const doltLog = (db) => async (params) => {
	let query = sql`SELECT * FROM DOLT_LOG()`;
	if (params?.revision) query = sql.raw(`SELECT * FROM DOLT_LOG('${params.revision}')`);
	let rows = (await db.execute(query)).rows;
	if (params?.limit) rows = rows.slice(0, params.limit);
	return rows;
};
/**
* Reset staged or working changes
*/
const doltReset = (db) => async (params) => {
	if (params?.hard) await db.execute(sql`SELECT DOLT_RESET('--hard')`);
	else if (params?.tables && params.tables.length > 0) {
		const tableParams = params.tables.map((t) => `'${t}'`).join(", ");
		await db.execute(sql.raw(`SELECT DOLT_RESET(${tableParams})`));
	} else await db.execute(sql`SELECT DOLT_RESET()`);
};
/**
* Get status of working changes
*/
const doltStatus = (db) => async () => {
	return (await db.execute(sql`SELECT * FROM dolt_status`)).rows;
};
/**
* Get hash of a commit/branch
*/
const doltHashOf = (db) => async (params) => {
	if (/^[0-9a-v]{32}$/.test(params.revision)) return params.revision;
	if ((await doltListBranches(db)()).some((b) => b.name === params.revision)) {
		const commitHash = (await db.execute(sql.raw(`SELECT commit_hash FROM DOLT_LOG('${params.revision}') LIMIT 1`))).rows[0]?.commit_hash;
		if (!commitHash) throw new Error(`Could not find commit hash for branch '${params.revision}'`);
		return commitHash;
	}
	const tag = (await doltListTags(db)()).find((t) => t.tag_name === params.revision);
	if (tag) return tag.tag_hash;
	const hash = (await db.execute(sql.raw(`SELECT DOLT_HASHOF('${params.revision}') as hash`))).rows[0]?.hash;
	if (!hash) throw new Error(`Could not find commit hash for revision '${params.revision}'`);
	return hash;
};
/**
* Create a tag
*/
const doltTag = (db) => async (params) => {
	const args = [`'${params.name}'`];
	if (params.message) args.push("'-m'", `'${params.message.replace(/'/g, "''")}'`);
	if (params.revision) args.push(`'${params.revision}'`);
	await db.execute(sql.raw(`SELECT DOLT_TAG(${args.join(", ")})`));
};
/**
* Delete a tag
*/
const doltDeleteTag = (db) => async (params) => {
	await db.execute(sql.raw(`SELECT DOLT_TAG('-d', '${params.name}')`));
};
/**
* List all tags
*/
const doltListTags = (db) => async () => {
	return (await db.execute(sql`SELECT * FROM dolt_tags`)).rows;
};

//#endregion
export { doltAdd, doltAddAndCommit, doltCommit, doltDeleteTag, doltHashOf, doltListTags, doltLog, doltReset, doltStatus, doltTag };