var Azure = {
	params: {},
	token: null,

	setParams: function (params) {
		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
				throw 'Required param is not set: ' + field + '.';
			}
		});

		Azure.params = params;
	},

	login: function () {
		var response, login = new HttpRequest();

		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
			login.setProxy(Azure.params.proxy);
		}

		login.addHeader('Content-Type: application/x-www-form-urlencoded');
		response = login.post(
			'https://login.microsoftonline.com/' + encodeURIComponent(Azure.params.tenant_id) + '/oauth2/token',
			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(Azure.params.app_id) + '&client_secret=' + encodeURIComponent(Azure.params.password)
		);

		if (login.getStatus() !== 200) {
			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
		}

		try {
			response = JSON.parse(response);
		}
		catch (error) {
			throw 'Failed to parse login session response.';
		}

		if (!response.hasOwnProperty('access_token')) {
			throw 'Authentication response does not contain access token.';
		}

		Azure.token = response['access_token'];
	},

	request: function (url) {
		var response, request = new HttpRequest();

		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
			request.setProxy(Azure.params.proxy);
		}

		if (!Azure.token) {
			throw 'Request does not contain access token.';
		}

		request.addHeader('Content-Type: application/json');
		request.addHeader('Authorization: Bearer ' + Azure.token);
		Zabbix.log(4, '[ Azure SQL instance ] request url: ' + url);

		response = request.get(url);

		if (request.getStatus() !== 200) {
			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
		}

		try {
			return JSON.parse(response);
		}
		catch (error) {
			throw 'Failed to parse response received from API.';
		}
	},

	getField: function (data, path) {
		var steps = path.split('.');

		for (var i = 0; i < steps.length; i++) {
			var step = steps[i];
			if (typeof data !== 'object' || typeof data[step] === 'undefined') {
				throw 'Required field was not found: ' + path;
			}
			data = data[step];
		}

		return data;
	},

	getMetricsData: function () {
		var data = {},
			metric_endpoints = {
				'main_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('virtual_core_count,avg_cpu_percent,reserved_storage_mb,storage_space_used_mb,io_requests,io_bytes_read,io_bytes_written') + '&api-version=2021-05-01&timespan=PT5M',
			};

		data.metrics = {};

		Object.keys(metric_endpoints).forEach(function (field) {
			metrics = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + metric_endpoints[field]), 'value');
			for (k in metrics) {
				key = Azure.getField(metrics[k], 'name.value').replace(/(\s|\/)+/g, '');
				if (metrics[k].timeseries.length === 0) {
					metrics[k].timeseries.push({ 'data': ['nodata'] })
				}
				values = Azure.getField(metrics[k], 'timeseries.0.data');
				for (var i = values.length - 1; i >= 0; i--) {
					if (typeof (values[i].average) !== 'undefined') {
						data.metrics[key] = values[i];
						break;
					}
				}
			}
		});

		data.health = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01'), 'value.0.properties');
		data.instance = Azure.request('https://management.azure.com' + Azure.params.resource_id + '?api-version=2024-05-01-preview');

		return data
	}
};

try {
	Azure.setParams(JSON.parse(value));
	Azure.login();
	return JSON.stringify(Azure.getMetricsData());
}
catch (error) {
	error += (String(error).endsWith('.')) ? '' : '.';
	Zabbix.log(3, '[ Azure SQL instance ] ERROR: ' + error);
	return JSON.stringify({ 'error': error });
}