import type { TaskUpdateInput } from "../types/index.ts";
import type { TaskEditArgs } from "../types/task-edit-args.ts";
import { normalizeStringList } from "./task-builders.ts";

function sanitizeStringArray(values: string[] | undefined): string[] | undefined {
	if (!values) return undefined;
	const trimmed = values.map((value) => String(value).trim()).filter((value) => value.length > 0);
	return trimmed.length > 0 ? trimmed : undefined;
}

function sanitizeAppend(values: string[] | undefined): string[] | undefined {
	const sanitized = sanitizeStringArray(values);
	if (!sanitized) {
		return undefined;
	}
	return sanitized;
}

function toAcceptanceCriteriaEntries(values: string[] | undefined) {
	if (!values) return undefined;
	const trimmed = values.map((value) => String(value).trim()).filter((value) => value.length > 0);
	if (trimmed.length === 0) {
		return undefined;
	}
	return trimmed.map((text, index) => ({ text, checked: false, index: index + 1 }));
}

export function buildTaskUpdateInput(args: TaskEditArgs): TaskUpdateInput {
	const updateInput: TaskUpdateInput = {};

	if (typeof args.title === "string") {
		updateInput.title = args.title;
	}

	if (typeof args.description === "string") {
		updateInput.description = args.description;
	}

	if (typeof args.status === "string") {
		updateInput.status = args.status;
	}

	if (typeof args.priority === "string") {
		updateInput.priority = args.priority;
	}

	if (args.milestone === null) {
		updateInput.milestone = null;
	} else if (typeof args.milestone === "string") {
		const trimmed = args.milestone.trim();
		updateInput.milestone = trimmed.length > 0 ? trimmed : null;
	}

	if (typeof args.ordinal === "number") {
		updateInput.ordinal = args.ordinal;
	}

	if (args.labels !== undefined) {
		const labels = normalizeStringList(args.labels);
		if (labels) {
			updateInput.labels = labels;
		} else if (args.labels.length === 0) {
			updateInput.labels = [];
		}
	}

	const addLabels = normalizeStringList(args.addLabels);
	if (addLabels) {
		updateInput.addLabels = addLabels;
	}

	const removeLabels = normalizeStringList(args.removeLabels);
	if (removeLabels) {
		updateInput.removeLabels = removeLabels;
	}

	const assignee = normalizeStringList(args.assignee);
	if (assignee) {
		updateInput.assignee = assignee;
	}

	const dependencies = sanitizeStringArray(args.dependencies);
	if (dependencies) {
		updateInput.dependencies = dependencies;
	}

	const references = sanitizeStringArray(args.references);
	if (references) {
		updateInput.references = references;
	}

	const addReferences = sanitizeStringArray(args.addReferences);
	if (addReferences) {
		updateInput.addReferences = addReferences;
	}

	const removeReferences = sanitizeStringArray(args.removeReferences);
	if (removeReferences) {
		updateInput.removeReferences = removeReferences;
	}

	const documentation = sanitizeStringArray(args.documentation);
	if (documentation) {
		updateInput.documentation = documentation;
	}

	const addDocumentation = sanitizeStringArray(args.addDocumentation);
	if (addDocumentation) {
		updateInput.addDocumentation = addDocumentation;
	}

	const removeDocumentation = sanitizeStringArray(args.removeDocumentation);
	if (removeDocumentation) {
		updateInput.removeDocumentation = removeDocumentation;
	}

	const modifiedFiles = sanitizeStringArray(args.modifiedFiles);
	if (modifiedFiles) {
		updateInput.modifiedFiles = modifiedFiles;
	}

	const planSet = args.planSet ?? args.implementationPlan;
	if (typeof planSet === "string") {
		updateInput.implementationPlan = planSet;
	}

	const planAppends = sanitizeAppend(args.planAppend);
	if (planAppends) {
		updateInput.appendImplementationPlan = planAppends;
	}

	if (args.planClear) {
		updateInput.clearImplementationPlan = true;
	}

	const notesSet = args.notesSet ?? args.implementationNotes;
	if (typeof notesSet === "string") {
		updateInput.implementationNotes = notesSet;
	}

	const notesAppends = sanitizeAppend(args.notesAppend);
	if (notesAppends) {
		updateInput.appendImplementationNotes = notesAppends;
	}

	if (args.notesClear) {
		updateInput.clearImplementationNotes = true;
	}

	const commentsAppends = sanitizeAppend(args.commentsAppend);
	if (commentsAppends) {
		const author =
			typeof args.commentAuthor === "string" && args.commentAuthor.trim().length > 0
				? args.commentAuthor.trim()
				: undefined;
		updateInput.appendComments = commentsAppends.map((body) => ({
			body,
			...(author && { author }),
		}));
	}

	if (typeof args.finalSummary === "string") {
		updateInput.finalSummary = args.finalSummary;
	}

	const finalSummaryAppends = sanitizeAppend(args.finalSummaryAppend);
	if (finalSummaryAppends) {
		updateInput.appendFinalSummary = finalSummaryAppends;
	}

	if (args.finalSummaryClear) {
		updateInput.clearFinalSummary = true;
	}

	const criteriaSet = toAcceptanceCriteriaEntries(args.acceptanceCriteriaSet);
	if (criteriaSet) {
		updateInput.acceptanceCriteria = criteriaSet;
	}

	if (Array.isArray(args.acceptanceCriteriaAdd) && args.acceptanceCriteriaAdd.length > 0) {
		const additions = args.acceptanceCriteriaAdd
			.map((text) => String(text).trim())
			.filter((text) => text.length > 0)
			.map((text) => ({ text, checked: false }));
		if (additions.length > 0) {
			updateInput.addAcceptanceCriteria = additions;
		}
	}

	if (Array.isArray(args.acceptanceCriteriaRemove) && args.acceptanceCriteriaRemove.length > 0) {
		updateInput.removeAcceptanceCriteria = [...args.acceptanceCriteriaRemove];
	}

	if (Array.isArray(args.acceptanceCriteriaCheck) && args.acceptanceCriteriaCheck.length > 0) {
		updateInput.checkAcceptanceCriteria = [...args.acceptanceCriteriaCheck];
	}

	if (Array.isArray(args.acceptanceCriteriaUncheck) && args.acceptanceCriteriaUncheck.length > 0) {
		updateInput.uncheckAcceptanceCriteria = [...args.acceptanceCriteriaUncheck];
	}

	if (Array.isArray(args.definitionOfDoneAdd) && args.definitionOfDoneAdd.length > 0) {
		const additions = args.definitionOfDoneAdd
			.map((text) => String(text).trim())
			.filter((text) => text.length > 0)
			.map((text) => ({ text, checked: false }));
		if (additions.length > 0) {
			updateInput.addDefinitionOfDone = additions;
		}
	}

	if (Array.isArray(args.definitionOfDoneRemove) && args.definitionOfDoneRemove.length > 0) {
		updateInput.removeDefinitionOfDone = [...args.definitionOfDoneRemove];
	}

	if (Array.isArray(args.definitionOfDoneCheck) && args.definitionOfDoneCheck.length > 0) {
		updateInput.checkDefinitionOfDone = [...args.definitionOfDoneCheck];
	}

	if (Array.isArray(args.definitionOfDoneUncheck) && args.definitionOfDoneUncheck.length > 0) {
		updateInput.uncheckDefinitionOfDone = [...args.definitionOfDoneUncheck];
	}

	return updateInput;
}
