import Widget from "./base_widget.js";

jingrow.provide("jingrow.utils");

export default class NumberCardWidget extends Widget {
	constructor(opts) {
		opts.shadow = true;
		super(opts);
	}

	get_config() {
		return {
			name: this.name,
			number_card_name: this.number_card_name,
			label: this.label,
			color: this.color,
			hidden: this.hidden,
		};
	}

	refresh() {
		this.set_body();
	}

	set_body() {
		this.widget.addClass("number-widget-box");
		this.make_card();
	}

	make_card() {
		jingrow.model.with_pg("Number Card", this.number_card_name || this.name).then((card) => {
			if (!card) {
				if (this.document_type) {
					jingrow.run_serially([
						() => this.create_number_card(),
						() => this.render_card(),
					]);
				} else {
					// widget doesn't exist so delete
					this.delete(false);
					return;
				}
			} else {
				this.card_pg = card;
				this.render_card();
			}

			this.set_events();
		});
	}

	create_number_card() {
		this.set_pg_args();
		return jingrow
			.xcall("jingrow.desk.pagetype.number_card.number_card.create_number_card", {
				args: this.card_pg,
			})
			.then((pg) => {
				this.name = pg.name;
				this.card_pg = pg;
				this.widget.attr("data-widget-name", this.name);
			});
	}

	set_events() {
		$(this.body).click(() => {
			if (this.in_customize_mode) return;
			this.set_route();
		});
	}

	set_route() {
		if (this.card_pg.type === "Custom") {
			this.set_route_for_custom_card();
			return;
		}

		const is_document_type = this.card_pg.type !== "Report";
		const name = is_document_type ? this.card_pg.document_type : this.card_pg.report_name;
		const route = jingrow.utils.generate_route({
			name: name,
			type: is_document_type ? "pagetype" : "report",
			is_query_report: !is_document_type,
		});

		if (is_document_type) {
			const filters = JSON.parse(this.card_pg.filters_json);
			jingrow.route_options = filters.reduce((acc, filter) => {
				return Object.assign(acc, {
					[`${filter[0]}.${filter[1]}`]: [filter[2], filter[3]],
				});
			}, {});
		}

		jingrow.set_route(route);
	}

	set_route_for_custom_card() {
		if (!this.data?.route) return;

		if (this.data.route_options) {
			jingrow.route_options = this.data.route_options;
		}

		jingrow.set_route(this.data.route);
	}

	set_pg_args() {
		this.card_pg = Object.assign(
			{},
			{
				document_type: this.document_type,
				label: this.label,
				function: this.function,
				aggregate_function_based_on: this.aggregate_function_based_on,
				color: this.color,
				filters_json: this.stats_filter,
			}
		);
	}

	get_settings(type) {
		this.filters = this.get_filters();
		const settings_map = {
			Custom: {
				method: this.card_pg.method,
				args: {
					filters: this.filters,
				},
				get_number: (res) => this.get_number_for_custom_card(res),
			},
			Report: {
				method: "jingrow.desk.query_report.run",
				args: {
					report_name: this.card_pg.report_name,
					filters: this.filters,
					ignore_prepared_report: 1,
				},
				get_number: (res) => this.get_number_for_report_card(res),
			},
			"Document Type": {
				method: "jingrow.desk.pagetype.number_card.number_card.get_result",
				args: {
					pg: this.card_pg,
					filters: this.filters,
				},
				get_number: (res) => this.get_number_for_pagetype_card(res),
			},
		};
		return settings_map[type];
	}

	get_filters() {
		return jingrow.dashboard_utils.get_all_filters(this.card_pg);
	}

	async render_card() {
		this.prepare_actions();
		this.set_title();
		this.set_loading_state();

		if (!this.card_pg.type) {
			this.card_pg.type = "Document Type";
		}

		this.settings = this.get_settings(this.card_pg.type);
		await this.get_data();

		this.render_number();
		this.render_stats();
	}

	set_loading_state() {
		$(this.body).html(`<div class="number-card-loading text-muted">
			${__("Loading...")}
		</div>`);
	}

	async get_data() {
		this.data = await jingrow.xcall(this.settings.method, this.settings.args);
		return this.settings.get_number(this.data);
	}

	get_number_for_custom_card(res) {
		if (typeof res === "object") {
			this.number = res.value;
			this.set_formatted_number(res);
		} else {
			this.formatted_number = res;
		}
	}

	get_number_for_pagetype_card(res) {
		this.number = res;
		if (this.card_pg.function !== "Count") {
			return jingrow.model.with_pagetype(this.card_pg.document_type, () => {
				const based_on_df = jingrow.meta.get_pagefield(
					this.card_pg.document_type,
					this.card_pg.aggregate_function_based_on
				);
				this.set_formatted_number(based_on_df);
			});
		} else {
			this.formatted_number = res;
		}
	}

	get_number_for_report_card(res) {
		const field = this.card_pg.report_field;
		const vals = res.result.reduce((acc, col) => {
			col[field] && acc.push(col[field]);
			return acc;
		}, []);
		const col = res.columns.find((col) => col.fieldname == field);
		this.number = jingrow.report_utils.get_result_of_fn(this.card_pg.report_function, vals);
		this.set_formatted_number(col, this._generate_common_pg(res.result));
	}

	set_formatted_number(df, pg) {
		const default_country = jingrow.sys_defaults.country;
		const shortened_number = jingrow.utils.shorten_number(this.number, default_country, 5);
		let number_parts = shortened_number.split(" ");
		// done to add multicurrency support in number card
		if (this.card_pg.currency) {
			this.formatted_number = format_currency(number_parts[0], this.card_pg.currency);
			return;
		}
		const symbol = number_parts[1] || "";
		number_parts[0] = window.convert_old_to_new_number_format(number_parts[0]);
		const formatted_number = jingrow.format(number_parts[0], df, null, pg);
		this.formatted_number =
			($(formatted_number).text() || formatted_number) + " " + __(symbol);
	}

	_generate_common_pg(rows) {
		if (!rows || !rows.length) return {};
		// init with first pg, for each other pg if values are common then keep else discard
		// Whatever is left should be same in all objects
		const common_pg = Object.assign({}, rows[0]);
		rows.forEach((row) => {
			if (Array.isArray(row)) return; // totals row

			for (const [key, value] of Object.entries(common_pg)) {
				if (value !== row[key]) {
					delete common_pg[key];
				}
			}
		});
		return common_pg;
	}

	render_number() {
		const style_attr = this.card_pg.color ? `style="color: ${this.card_pg.color};"` : "";

		$(this.body).html(`<div class="widget-content">
			<div class="number" ${style_attr}>${this.formatted_number}</div>
			</div>`);
	}

	render_stats() {
		if (this.card_pg.type !== "Document Type" || !this.card_pg.show_percentage_stats) {
			return;
		}

		let caret_html = "";
		let color_class = "";

		return this.get_percentage_stats().then(() => {
			if (this.percentage_stat == 0 || this.percentage_stat == undefined) {
				color_class = "grey-stat";
			} else if (this.percentage_stat > 0) {
				caret_html = `<span class="indicator-pill-round green">
						${jingrow.utils.icon("es-line-arrow-up-right", "xs")}
					</span>`;
				color_class = "green-stat";
			} else {
				caret_html = `<span class="indicator-pill-round red">
						${jingrow.utils.icon("arrow-down-right", "xs")}
					</span>`;
				color_class = "red-stat";
			}

			const stats_qualifier_map = {
				Daily: __("since yesterday"),
				Weekly: __("since last week"),
				Monthly: __("since last month"),
				Yearly: __("since last year"),
			};
			const stats_qualifier = stats_qualifier_map[this.card_pg.stats_time_interval];

			let stat = (() => {
				if (this.percentage_stat == undefined) return NaN;
				const parts = this.percentage_stat.split(" ");
				const symbol = parts[1] || "";
				return Math.abs(parts[0]) + " " + symbol;
			})();

			// don't show stats if not valid number - skip showing `NaN %` in card
			if (isNaN(stat)) return;

			$(this.body).find(".widget-content").append(`<div class="card-stats ${color_class}">
				<span class="percentage-stat-area">
					${caret_html} ${stat} % ${stats_qualifier}
				</span>
			</div>`);
		});
	}

	get_percentage_stats() {
		return jingrow
			.xcall("jingrow.desk.pagetype.number_card.number_card.get_percentage_difference", {
				pg: this.card_pg,
				filters: this.filters,
				result: this.number,
			})
			.then((res) => {
				if (res !== undefined) {
					this.percentage_stat = jingrow.utils.shorten_number(res);
				}
			});
	}

	prepare_actions() {
		if (this.in_customize_mode) return;

		let actions = [
			{
				label: __("Refresh"),
				action: "action-refresh",
				handler: () => {
					this.render_card();
				},
			},
			{
				label: __("Edit"),
				action: "action-edit",
				handler: () => {
					let number_card = this.number_card_name || this.name;
					jingrow.set_route("Form", "Number Card", number_card);
				},
			},
		];

		this.set_card_actions(actions);
	}

	set_card_actions(actions) {
		this.card_actions = $(`<div class="card-actions dropdown pull-right">
				<a data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
				...
				</a>
				<ul class="dropdown-menu" style="max-height: 300px; overflow-y: auto;">
					${actions
						.map(
							(action) =>
								`<li class="dropdown-item">
									<a data-action="${action.action}">${action.label}</a>
								</li>`
						)
						.join("")}
				</ul>
			</div>`);

		this.card_actions.find("a[data-action]").each((i, o) => {
			const action = o.dataset.action;
			$(o).click(actions.find((a) => a.action === action));
		});

		this.action_area.html(this.card_actions);
	}
}
