export default class BulkOperations {
	constructor({ pagetype }) {
		if (!pagetype) jingrow.throw(__("Pagetype required"));
		this.pagetype = pagetype;
	}

	print(pgs) {
		const print_settings = jingrow.model.get_pg(":Print Settings", "Print Settings");
		const allow_print_for_draft = cint(print_settings.allow_print_for_draft);
		const is_submittable = jingrow.model.is_submittable(this.pagetype);
		const allow_print_for_cancelled = cint(print_settings.allow_print_for_cancelled);
		const letterheads = this.get_letterhead_options();
		const MAX_PRINT_LIMIT = 500;
		const BACKGROUND_PRINT_THRESHOLD = 25;

		const valid_pgs = pgs
			.filter((pg) => {
				return (
					!is_submittable ||
					pg.pagestatus === 1 ||
					(allow_print_for_cancelled && pg.pagestatus == 2) ||
					(allow_print_for_draft && pg.pagestatus == 0) ||
					jingrow.user.has_role("Administrator")
				);
			})
			.map((pg) => pg.name);

		const invalid_pgs = pgs.filter((pg) => !valid_pgs.includes(pg.name));

		if (invalid_pgs.length > 0) {
			jingrow.msgprint(__("You selected Draft or Cancelled documents"));
			return;
		}

		if (valid_pgs.length === 0) {
			jingrow.msgprint(__("Select atleast 1 record for printing"));
			return;
		}

		if (valid_pgs.length > MAX_PRINT_LIMIT) {
			jingrow.msgprint(
				__("You can only print upto {0} documents at a time", [MAX_PRINT_LIMIT])
			);
			return;
		}

		const dialog = new jingrow.ui.Dialog({
			title: __("Print Documents"),
			fields: [
				{
					fieldtype: "Select",
					label: __("Letter Head"),
					fieldname: "letter_sel",
					options: letterheads,
					default: letterheads[0],
				},
				{
					fieldtype: "Select",
					label: __("Print Format"),
					fieldname: "print_sel",
					options: jingrow.meta.get_print_formats(this.pagetype),
					default: jingrow.get_meta(this.pagetype).default_print_format,
				},
				{
					fieldtype: "Select",
					label: __("Page Size"),
					fieldname: "page_size",
					options: jingrow.meta.get_print_sizes(),
					default: print_settings.pdf_page_size,
				},
				{
					fieldtype: "Float",
					label: __("Page Height (in mm)"),
					fieldname: "page_height",
					depends_on: 'eval:pg.page_size == "Custom"',
					default: print_settings.pdf_page_height,
				},
				{
					fieldtype: "Float",
					label: __("Page Width (in mm)"),
					fieldname: "page_width",
					depends_on: 'eval:pg.page_size == "Custom"',
					default: print_settings.pdf_page_width,
				},
				{
					fieldtype: "Check",
					label: __("Background Print (required for >25 documents)"),
					fieldname: "background_print",
					default: valid_pgs.length > BACKGROUND_PRINT_THRESHOLD,
					read_only: valid_pgs.length > BACKGROUND_PRINT_THRESHOLD,
				},
			],
		});

		dialog.set_primary_action(__("Print"), (args) => {
			if (!args) return;
			const default_print_format = jingrow.get_meta(this.pagetype).default_print_format;
			const with_letterhead = args.letter_sel == __("No Letterhead") ? 0 : 1;
			const print_format = args.print_sel ? args.print_sel : default_print_format;
			const json_string = JSON.stringify(valid_pgs);
			const letterhead = args.letter_sel;

			let pdf_options;
			if (args.page_size === "Custom") {
				if (args.page_height === 0 || args.page_width === 0) {
					jingrow.throw(__("Page height and width cannot be zero"));
				}
				pdf_options = JSON.stringify({
					"page-height": args.page_height,
					"page-width": args.page_width,
				});
			} else {
				pdf_options = JSON.stringify({ "page-size": args.page_size });
			}

			if (args.background_print) {
				jingrow
					.call("jingrow.utils.print_format.download_multi_pdf_async", {
						pagetype: this.pagetype,
						name: json_string,
						format: print_format,
						no_letterhead: with_letterhead ? "0" : "1",
						letterhead: letterhead,
						options: pdf_options,
					})
					.then((response) => {
						let task_id = response.message.task_id;
						jingrow.realtime.task_subscribe(task_id);
						jingrow.realtime.on(`task_complete:${task_id}`, (data) => {
							jingrow.msgprint({
								title: __("Bulk PDF Export"),
								message: __("Your PDF is ready for download"),
								primary_action: {
									label: __("Download PDF"),
									client_action: "window.open",
									args: data.file_url,
								},
							});
							jingrow.realtime.task_unsubscribe(task_id);
							jingrow.realtime.off(`task_complete:${task_id}`);
						});
					});
			} else {
				const w = window.open(
					"/api/action/jingrow.utils.print_format.download_multi_pdf?" +
						"pagetype=" +
						encodeURIComponent(this.pagetype) +
						"&name=" +
						encodeURIComponent(json_string) +
						"&format=" +
						encodeURIComponent(print_format) +
						"&no_letterhead=" +
						(with_letterhead ? "0" : "1") +
						"&letterhead=" +
						encodeURIComponent(letterhead) +
						"&options=" +
						encodeURIComponent(pdf_options)
				);

				if (!w) {
					jingrow.msgprint(__("Please enable pop-ups"));
				}
			}
			dialog.hide();
		});
		dialog.show();
	}

	get_letterhead_options() {
		const letterhead_options = [__("No Letterhead")];
		jingrow.call({
			method: "jingrow.client.get_list",
			args: {
				pagetype: "Letter Head",
				fields: ["name", "is_default"],
				filters: { disabled: 0 },
				limit_page_length: 0,
			},
			async: false,
			callback(r) {
				if (r.message) {
					r.message.forEach((letterhead) => {
						if (letterhead.is_default) {
							letterhead_options.unshift(letterhead.name);
						} else {
							letterhead_options.push(letterhead.name);
						}
					});
				}
			},
		});
		return letterhead_options;
	}

	delete(pagenames, done = null) {
		jingrow
			.call({
				method: "jingrow.desk.reportview.delete_items",
				freeze: true,
				freeze_message:
					pagenames.length <= 10
						? __("Deleting {0} records...", [pagenames.length])
						: null,
				args: {
					items: pagenames,
					pagetype: this.pagetype,
				},
			})
			.then((r) => {
				let failed = r.message;
				if (!failed) failed = [];

				if (failed.length && !r._server_messages) {
					jingrow.throw(
						__("Cannot delete {0}", [failed.map((f) => f.bold()).join(", ")])
					);
				}
				if (failed.length < pagenames.length) {
					jingrow.utils.play_sound("delete");
					if (done) done();
				}
			});
	}

	assign(pagenames, done) {
		if (pagenames.length > 0) {
			const assign_to = new jingrow.ui.form.AssignToDialog({
				obj: this,
				method: "jingrow.desk.form.assign_to.add_multiple",
				pagetype: this.pagetype,
				pagename: pagenames,
				bulk_assign: true,
				re_assign: true,
				callback: done,
			});
			assign_to.dialog.clear();
			assign_to.dialog.show();
		} else {
			jingrow.msgprint(__("Select records for assignment"));
		}
	}

	clear_assignment(pagenames, done) {
		if (pagenames.length > 0) {
			jingrow
				.call({
					method: "jingrow.desk.form.assign_to.remove_multiple",
					args: {
						pagetype: this.pagetype,
						names: pagenames,
						ignore_permissions: true,
					},
					freeze: true,
					freeze_message: "Removing assignments...",
				})
				.then(() => {
					done();
				});
		} else {
			jingrow.msgprint(__("Select records for removing assignment"));
		}
	}

	apply_assignment_rule(pagenames, done) {
		if (pagenames.length > 0) {
			jingrow
				.call("jingrow.automation.pagetype.assignment_rule.assignment_rule.bulk_apply", {
					pagetype: this.pagetype,
					pagenames: pagenames,
				})
				.then(() => done());
		}
	}

	submit_or_cancel(pagenames, action = "submit", done = null) {
		action = action.toLowerCase();
		const task_id = Math.random().toString(36).slice(-5);
		jingrow.realtime.task_subscribe(task_id);
		return jingrow
			.xcall("jingrow.desk.pagetype.bulk_update.bulk_update.submit_cancel_or_update_pgs", {
				pagetype: this.pagetype,
				action: action,
				pagenames: pagenames,
				task_id: task_id,
			})
			.then((failed_pagenames) => {
				if (failed_pagenames?.length) {
					const comma_separated_records = jingrow.utils.comma_and(failed_pagenames);
					switch (action) {
						case "submit":
							jingrow.throw(__("Cannot submit {0}.", [comma_separated_records]));
							break;
						case "cancel":
							jingrow.throw(__("Cannot cancel {0}.", [comma_separated_records]));
							break;
						default:
							jingrow.throw(__("Cannot {0} {1}.", [action, comma_separated_records]));
					}
				}
				if (failed_pagenames?.length < pagenames.length) {
					jingrow.utils.play_sound(action);
					if (done) done();
				}
			})
			.finally(() => {
				jingrow.realtime.task_unsubscribe(task_id);
			});
	}

	edit(pagenames, field_mappings, done) {
		let field_options = Object.keys(field_mappings).sort(function (a, b) {
			return __(cstr(field_mappings[a].label)).localeCompare(
				cstr(__(field_mappings[b].label))
			);
		});
		const status_regex = /status/i;

		const default_field = field_options.find((value) => status_regex.test(value));

		const dialog = new jingrow.ui.Dialog({
			title: __("Bulk Edit"),
			fields: [
				{
					fieldtype: "Select",
					options: field_options,
					default: default_field,
					label: __("Field"),
					fieldname: "field",
					reqd: 1,
					onchange: () => {
						set_value_field(dialog);
					},
				},
				{
					fieldtype: "Data",
					label: __("Value"),
					fieldname: "value",
					onchange() {
						show_help_text();
					},
				},
			],
			primary_action: ({ value }) => {
				const fieldname = field_mappings[dialog.get_value("field")].fieldname;
				dialog.disable_primary_action();
				jingrow
					.call({
						method: "jingrow.desk.pagetype.bulk_update.bulk_update.submit_cancel_or_update_pgs",
						args: {
							pagetype: this.pagetype,
							freeze: true,
							pagenames: pagenames,
							action: "update",
							data: {
								[fieldname]: value || null,
							},
						},
					})
					.then((r) => {
						let failed = r.message || [];

						if (failed.length && !r._server_messages) {
							dialog.enable_primary_action();
							jingrow.throw(
								__("Cannot update {0}", [
									failed.map((f) => (f.bold ? f.bold() : f)).join(", "),
								])
							);
						}
						done();
						dialog.hide();
						jingrow.show_alert(__("Updated successfully"));
					});
			},
			primary_action_label: __("Update {0} records", [pagenames.length]),
		});

		if (default_field) set_value_field(dialog); // to set `Value` df based on default `Field`
		show_help_text();

		function set_value_field(dialogObj) {
			const new_df = Object.assign({}, field_mappings[dialogObj.get_value("field")]);
			/* if the field label has status in it and
			if it has select fieldtype with no default value then
			set a default value from the available option. */
			if (
				new_df.label.match(status_regex) &&
				new_df.fieldtype === "Select" &&
				!new_df.default
			) {
				let options = [];
				if (typeof new_df.options === "string") {
					options = new_df.options.split("\n");
				}
				//set second option as default if first option is an empty string
				new_df.default = options[0] || options[1];
			}
			new_df.label = __("Value");
			new_df.onchange = show_help_text;

			delete new_df.depends_on;
			dialogObj.replace_field("value", new_df);
			show_help_text();
		}

		function show_help_text() {
			let value = dialog.get_value("value");
			if (value == null || value === "") {
				dialog.set_df_property(
					"value",
					"description",
					__("You have not entered a value. The field will be set to empty.")
				);
			} else {
				dialog.set_df_property("value", "description", "");
			}
		}

		dialog.refresh();
		dialog.show();
	}

	add_tags(pagenames, done) {
		const dialog = new jingrow.ui.Dialog({
			title: __("Add Tags"),
			fields: [
				{
					fieldtype: "MultiSelectPills",
					fieldname: "tags",
					label: __("Tags"),
					reqd: true,
					get_data: function (txt) {
						return jingrow.db.get_link_options("Tag", txt);
					},
				},
			],
			primary_action_label: __("Add"),
			primary_action: () => {
				let args = dialog.get_values();
				if (args && args.tags) {
					dialog.set_message("Adding Tags...");

					jingrow.call({
						method: "jingrow.desk.pagetype.tag.tag.add_tags",
						args: {
							tags: args.tags,
							dt: this.pagetype,
							pgs: pagenames,
						},
						callback: () => {
							dialog.hide();
							done();
						},
					});
				}
			},
		});
		dialog.show();
	}

	export(pagetype, pagenames) {
		jingrow.require("data_import_tools.bundle.js", () => {
			const data_exporter = new jingrow.data_import.DataExporter(
				pagetype,
				"Insert New Records"
			);
			data_exporter.dialog.set_value("export_records", "by_filter");
			data_exporter.filter_group.add_filters_to_filter_group([
				[pagetype, "name", "in", pagenames, false],
			]);
		});
	}
}
