/*
	GoToSocial
	Copyright (C) GoToSocial Authors admin@gotosocial.org
	SPDX-License-Identifier: AGPL-3.0-or-later
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.
	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see .
*/
import { replaceCacheOnMutation } from "../../query-modifiers";
import { gtsApi } from "../../gts-api";
import {
	type DomainPerm,
	type ImportDomainPermsParams,
	type MappedDomainPerms,
	isDomainPermInternalKey,
} from "../../../types/domain-permission";
import { listToKeyedObject } from "../../transforms";
/**
 * Builds up a map function that can be applied to a
 * list of DomainPermission entries in order to normalize
 * them before submission to the API.
 * @param formData 
 * @returns 
 */
function importEntriesProcessor(formData: ImportDomainPermsParams): (_entry: DomainPerm) => DomainPerm {
	let processingFuncs: { (_entry: DomainPerm): void; }[] = [];
	// Override each obfuscate entry if necessary.
	if (formData.obfuscate !== undefined) {
		const obfuscateEntry = (entry: DomainPerm) => {
			entry.obfuscate = formData.obfuscate;
		};
		processingFuncs.push(obfuscateEntry);
	}
	// Check whether we need to append or replace
	// private_comment and public_comment.
	["private_comment","public_comment"].forEach((commentType) => {
		let text = formData.commentType?.trim();
		if (!text) {
			return;
		}
		switch(formData[`${commentType}_behavior`]) {
			case "append":
				const appendComment = (entry: DomainPerm) => {
					if (entry.commentType == undefined) {
						entry.commentType = text;
					} else {
						entry.commentType = [entry.commentType, text].join("\n");
					}
				};
				processingFuncs.push(appendComment);
				break;
			case "replace":
				const replaceComment = (entry: DomainPerm) => {
					entry.commentType = text;
				};
				processingFuncs.push(replaceComment);
				break;
		}
	});
	return function process(entry) {
		// Call all the assembled processing functions.
		processingFuncs.forEach((f) => f(entry));
		// Unset all internal processing keys
		// and any undefined keys on this entry.
		Object.entries(entry).forEach(([key, val]: [keyof DomainPerm, any]) => {			
			if (val == undefined || isDomainPermInternalKey(key)) {
				delete entry[key];
			}
		});
		return entry;
	};
}
const extended = gtsApi.injectEndpoints({
	endpoints: (build) => ({		
		importDomainPerms: build.mutation({
			query: (formData) => {
				// Add/replace comments, remove internal keys.
				const process = importEntriesProcessor(formData);
				const domains = formData.domains.map(process);
				return {
					method: "POST",
					url: `/api/v1/admin/domain_${formData.permType}s?import=true`,
					asForm: true,
					discardEmpty: true,
					body: {
						import: true,
						domains: new Blob(
							[JSON.stringify(domains)],
							{ type: "application/json" },
						),
					}
				};
			},
			transformResponse: listToKeyedObject("domain"),
			...replaceCacheOnMutation((formData: ImportDomainPermsParams) => {
				// Query names for blocks and allows are like
				// `domainBlocks` and `domainAllows`, so we need
				// to convert `block` -> `Block` or `allow` -> `Allow`
				// to do proper cache invalidation.
				const permType =
					formData.permType.charAt(0).toUpperCase() +
					formData.permType.slice(1); 
				return `domain${permType}s`;
			}),
		})
	})
});
/**
 * POST domain permissions to /api/v1/admin/domain_{permType}s.
 * Returns the newly created permissions.
 */
const useImportDomainPermsMutation = extended.useImportDomainPermsMutation;
export {
	useImportDomainPermsMutation,
};