import { isHoliday as isHolidaySweden } from 'se-bank-holidays';

export interface Config {
	dayOfMonth: number;
	isHoliday?: (date: Date) => boolean;
	resolveSaturday?: 'previous-work-day' | 'next-work-day';
	resolveSunday?: 'previous-work-day' | 'next-work-day';
}

const defaultConfig: Config = {
	dayOfMonth: 25,
	resolveSaturday: 'previous-work-day',
	resolveSunday: 'previous-work-day',
	isHoliday: isHolidaySweden,
};

export function nextSalaryDay(referenceDate: Date | number, config: Config = defaultConfig): Date {
	if (typeof referenceDate === 'number') {
		// eslint-disable-next-line no-param-reassign
		referenceDate = new Date(referenceDate);
	}

	let salaryDay = new Date(
		referenceDate.getFullYear(),
		referenceDate.getMonth(),
		config.dayOfMonth + 1,
	);
	salaryDay.setUTCMinutes(0);
	salaryDay.setUTCHours(0);

	if (referenceDate > salaryDay) {
		salaryDay.setMonth(salaryDay.getMonth() + 1);
		salaryDay.setUTCMinutes(0);
		salaryDay.setUTCHours(0);
	}

	salaryDay = setSalaryDay(salaryDay, config);

	return salaryDay;
}

export function previousSalaryDay(referenceDate: Date | number, config: Config = defaultConfig) {
	if (typeof referenceDate === 'number') {
		// eslint-disable-next-line no-param-reassign
		referenceDate = new Date(referenceDate);
	}

	let salaryDay = new Date(
		referenceDate.getFullYear(),
		referenceDate.getMonth(),
		config.dayOfMonth + 1,
	);
	salaryDay.setUTCMinutes(0);
	salaryDay.setUTCHours(0);

	if (referenceDate < salaryDay) {
		salaryDay.setMonth(salaryDay.getMonth() - 1);
		salaryDay.setUTCMinutes(0);
		salaryDay.setUTCHours(0);
	}

	salaryDay = setSalaryDay(salaryDay, config);

	return salaryDay;
}

const SATURDAY = 6;
const SUNDAY = 0;

function setSalaryDay(date: Date, config: Config) {
	const dayOfWeek = date.getDay();

	if (dayOfWeek === SATURDAY) {
		date.setDate(date.getDate() + (config.resolveSaturday === 'previous-work-day' ? -1 : 2));
	}

	if (dayOfWeek === SUNDAY) {
		date.setDate(date.getDate() + (config.resolveSunday === 'previous-work-day' ? -2 : 1));
	}

	if (config.isHoliday) {
		while (config.isHoliday(date)) {
			date.setDate(date.getDate() - 1);
		}
	}

	return date;
}
