import dayjs from 'dayjs';
import customParse from '../../../../_virtual/customParseFormat.js';
import StartEndDatetUtils from '../start-end-date/utils.js';
import { QuickFilters, Granularity } from './types.js';

dayjs.extend(customParse);
const hasPartialStartEnd = (granularity, startDate, endDate) => {
    let partialStart;
    let partialEnd;
    switch (granularity) {
        case Granularity.DAILY:
            partialStart = false;
            partialEnd = false;
            break;
        case Granularity.MONTHLY:
            {
                const startOfMonth = dayjs(startDate).startOf('month');
                const endOfMonth = dayjs(endDate).endOf('month');
                partialStart = !startOfMonth.isSame(startDate, 'day');
                partialEnd = !endOfMonth.isSame(endDate, 'day');
            }
            break;
        case Granularity.ANNUALLY:
            {
                const startOfYear = dayjs(startDate).startOf('year');
                const endOfYear = dayjs(endDate).endOf('year');
                partialStart = !startOfYear.isSame(startDate, 'day');
                partialEnd = !endOfYear.isSame(endDate, 'day');
            }
            break;
        default:
            partialStart = false;
            partialEnd = false;
            break;
    }
    return {
        start: partialStart,
        end: partialEnd,
    };
};
const getQuickFilterOptions = () => {
    const options = [
        { value: QuickFilters.NONE, text: 'None' },
        { value: QuickFilters.TODAY, text: 'Today' },
        { value: QuickFilters.PAST, text: 'Past:', disabled: true },
        { value: QuickFilters.YESTERDAY, text: 'Yesterday' },
        { value: QuickFilters.LAST_SEVEN_DAYS, text: 'Last 7 days' },
        { value: QuickFilters.LAST_THIRTY_DAYS, text: 'Last 30 days' },
        { value: QuickFilters.LAST_MONTH, text: 'Last month' },
        { value: QuickFilters.LAST_FULL_MONTH, text: 'Last full month' },
        { value: QuickFilters.LAST_NINETY_DAYS, text: 'Last 90 days' },
        { value: QuickFilters.LAST_THREE_MONTHS, text: 'Last 3 months' },
        { value: QuickFilters.LAST_FULL_THREE_MONTHS, text: 'Last full 3 months' },
        { value: QuickFilters.LAST_SIX_MONTHS, text: 'Last 6 months' },
        { value: QuickFilters.LAST_FULL_SIX_MONTHS, text: 'Last full 6 months' },
        { value: QuickFilters.LAST_YEAR, text: 'Last year' },
        { value: QuickFilters.LAST_FULL_YEAR, text: 'Last full year' },
        { value: QuickFilters.FUTURE, text: 'Future:', disabled: true },
        { value: QuickFilters.TOMORROW, text: 'Tomorrow' },
        { value: QuickFilters.NEXT_SEVEN_DAYS, text: 'Next 7 days' },
        { value: QuickFilters.NEXT_THIRTY_DAYS, text: 'Next 30 days' },
        { value: QuickFilters.NEXT_MONTH, text: 'Next month' },
        { value: QuickFilters.NEXT_FULL_MONTH, text: 'Next full month' },
        { value: QuickFilters.NEXT_NINETY_DAYS, text: 'Next 90 days' },
        { value: QuickFilters.NEXT_THREE_MONTHS, text: 'Next 3 months' },
        { value: QuickFilters.NEXT_FULL_THREE_MONTHS, text: 'Next full 3 months' },
        { value: QuickFilters.NEXT_SIX_MONTHS, text: 'Next 6 months' },
        { value: QuickFilters.NEXT_FULL_SIX_MONTHS, text: 'Next full 6 months' },
        { value: QuickFilters.NEXT_YEAR, text: 'Next year' },
        { value: QuickFilters.NEXT_FULL_YEAR, text: 'Next full year' },
    ];
    return options;
};
const getGranularityOptions = () => {
    const options = [
        { value: Granularity.HOURLY, text: 'Hourly' },
        { value: Granularity.DAILY, text: 'Daily' },
        // { value: Granularity.WEEKLY, text: 'Weekly' },
        { value: Granularity.MONTHLY, text: 'Monthly' },
        // { value: Granularity.QUARTERLY, text: 'Quarterly' },
        { value: Granularity.ANNUALLY, text: 'Annually' },
    ];
    return options;
};
const setGranularityValue = (quickFilterValue, granularityValue) => {
    let granularity = granularityValue;
    const invalidDailyValues = ['annually', 'monthly'];
    const invalidMonthlyValues = ['annually'];
    if (quickFilterValue.includes('month') && invalidMonthlyValues.includes(quickFilterValue)) {
        granularity = Granularity.MONTHLY;
    }
    if (quickFilterValue.includes('day') && invalidDailyValues.includes(quickFilterValue)) {
        granularity = Granularity.DAILY;
    }
    return granularity;
};
const setDateRangeFromQuickFilterValue = (value) => {
    let startDate;
    let endDate;
    let granularity;
    switch (value) {
        case QuickFilters.TODAY:
            endDate = dayjs();
            startDate = dayjs();
            granularity = Granularity.DAILY;
            break;
        case QuickFilters.YESTERDAY:
            endDate = dayjs().subtract(1, 'day');
            startDate = dayjs().subtract(1, 'day');
            granularity = Granularity.DAILY;
            break;
        case QuickFilters.LAST_SEVEN_DAYS:
            endDate = dayjs();
            startDate = endDate.subtract(7, 'day').add(1, 'day');
            granularity = Granularity.DAILY;
            break;
        case QuickFilters.LAST_THIRTY_DAYS:
            endDate = dayjs();
            startDate = endDate.subtract(30, 'day').add(1, 'day');
            granularity = Granularity.DAILY;
            break;
        case QuickFilters.LAST_MONTH:
            endDate = dayjs();
            startDate = endDate.subtract(1, 'month').add(1, 'day');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.LAST_FULL_MONTH:
            endDate = dayjs().subtract(1, 'month').endOf('month');
            startDate = endDate.startOf('month');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.LAST_NINETY_DAYS:
            endDate = dayjs();
            startDate = endDate.subtract(90, 'day').add(1, 'day');
            granularity = Granularity.DAILY;
            break;
        case QuickFilters.LAST_THREE_MONTHS:
            endDate = dayjs();
            startDate = endDate.subtract(3, 'month').add(1, 'day');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.LAST_FULL_THREE_MONTHS:
            endDate = dayjs().subtract(1, 'month').endOf('month');
            startDate = endDate.subtract(2, 'month').startOf('month');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.LAST_SIX_MONTHS:
            endDate = dayjs();
            startDate = endDate.subtract(6, 'month').add(1, 'day');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.LAST_FULL_SIX_MONTHS:
            endDate = dayjs().subtract(1, 'month').endOf('month');
            startDate = endDate.subtract(6, 'month').startOf('month');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.LAST_YEAR:
            endDate = dayjs();
            startDate = endDate.subtract(1, 'year').add(1, 'day');
            granularity = Granularity.ANNUALLY;
            break;
        case QuickFilters.LAST_FULL_YEAR:
            endDate = dayjs().subtract(1, 'year').endOf('year');
            startDate = endDate.startOf('year');
            granularity = Granularity.ANNUALLY;
            break;
        case QuickFilters.TOMORROW:
            endDate = dayjs().add(1, 'day');
            startDate = dayjs().add(1, 'day');
            granularity = Granularity.DAILY;
            break;
        case QuickFilters.NEXT_SEVEN_DAYS:
            startDate = dayjs();
            endDate = dayjs().add(7, 'day').subtract(1, 'day');
            granularity = Granularity.DAILY;
            break;
        case QuickFilters.NEXT_THIRTY_DAYS:
            startDate = dayjs();
            endDate = dayjs().add(30, 'day').subtract(1, 'day');
            granularity = Granularity.DAILY;
            break;
        case QuickFilters.NEXT_MONTH:
            startDate = dayjs();
            endDate = dayjs().add(1, 'month').subtract(1, 'day');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.NEXT_FULL_MONTH:
            startDate = dayjs().add(1, 'month').startOf('month');
            endDate = startDate.endOf('month');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.NEXT_NINETY_DAYS:
            startDate = dayjs();
            endDate = dayjs().add(90, 'day').subtract(1, 'day');
            granularity = Granularity.DAILY;
            break;
        case QuickFilters.NEXT_THREE_MONTHS:
            startDate = dayjs();
            endDate = dayjs().add(3, 'month').subtract(1, 'day');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.NEXT_FULL_THREE_MONTHS:
            startDate = dayjs().add(1, 'month').startOf('month');
            endDate = startDate.add(2, 'month').endOf('month');
            granularity = Granularity.MONTHLY;
            break;
        case QuickFilters.NEXT_YEAR:
            startDate = dayjs();
            endDate = dayjs().add(1, 'year').subtract(1, 'day');
            granularity = Granularity.ANNUALLY;
            break;
        case QuickFilters.NEXT_FULL_YEAR:
            startDate = dayjs().add(1, 'year').startOf('year');
            endDate = startDate.endOf('year');
            granularity = Granularity.ANNUALLY;
            break;
        default:
            endDate = dayjs();
            startDate = dayjs();
            granularity = Granularity.DAILY;
            break;
    }
    return {
        start: startDate.format('YYYY-MM-DD').toString(),
        end: endDate.format('YYYY-MM-DD').toString(),
        granularity,
    };
};
const getOptionDisplayValue = (value, options) => {
    const item = options.find((opt) => {
        return opt.value === value;
    });
    return item?.text || value;
};
const setValueFromRequest = (filter, req, prefix) => {
    const { preventDefault } = req.query;
    const quickFilter = req.query[`${prefix}${filter.name}.quick-filter`];
    let granularity = req.query[`${prefix}${filter.name}.granularity`];
    let start;
    let end;
    if (quickFilter && quickFilter !== QuickFilters.NONE) {
        ({ start, end } = setDateRangeFromQuickFilterValue(quickFilter));
        granularity = setGranularityValue(quickFilter, granularity);
    }
    else {
        granularity = req.query[`${prefix}${filter.name}.granularity`];
        start = req.query[`${prefix}${filter.name}.start`];
        end = req.query[`${prefix}${filter.name}.end`];
    }
    const defaultStart = preventDefault ? null : filter.value?.start;
    const defaultEnd = preventDefault ? null : filter.value?.end;
    const defaultGranularity = preventDefault ? Granularity.DAILY : filter.value?.granularity.value;
    const defaultQuickFilter = preventDefault ? 'none' : filter.value?.quickFilter?.value;
    const granularityOptions = getGranularityOptions();
    const quickFilterOptions = getQuickFilterOptions();
    const startDate = start || defaultStart || filter.min || '';
    const endDate = end || defaultEnd || filter.max || '';
    const granularityValue = granularity || defaultGranularity || Granularity.NONE;
    const quickFilterValue = quickFilter || defaultQuickFilter || QuickFilters.NONE;
    const value = {
        start: startDate,
        end: endDate,
        granularity: {
            value: granularityValue,
            display: getOptionDisplayValue(granularityValue, granularityOptions),
        },
        quickFilter: {
            value: quickFilterValue,
            display: getOptionDisplayValue(quickFilterValue, quickFilterOptions),
        },
        partialDate: {
            ...hasPartialStartEnd(granularityValue, startDate, endDate),
        },
    };
    return value;
};
const setDefaultValue = (req, name) => {
    const dateRangeName = name.split('.')[0];
    const granularDateRangeDefaults = Object.keys(req.body)
        .filter((key) => key.includes(dateRangeName))
        .map((key) => {
        return { name: key, value: req.body[key] };
    });
    let granularDateRangeValue = {
        start: '',
        end: '',
        granularity: Granularity.NONE,
        quickFilter: QuickFilters.NONE,
    };
    granularDateRangeDefaults.forEach((dateRangeDefault) => {
        if (dateRangeDefault.name.includes('start')) {
            granularDateRangeValue.start = dateRangeDefault.value;
        }
        if (dateRangeDefault.name.includes('end')) {
            granularDateRangeValue.end = dateRangeDefault.value;
        }
        if (dateRangeDefault.name.includes('granularity')) {
            granularDateRangeValue.granularity = dateRangeDefault.value;
        }
        if (dateRangeDefault.name.includes('granularity')) {
            granularDateRangeValue.quickFilter = dateRangeDefault.value;
        }
    });
    granularDateRangeValue =
        granularDateRangeValue.start !== '' &&
            granularDateRangeValue.end !== '' &&
            granularDateRangeValue.granularity &&
            granularDateRangeValue.quickFilter
            ? granularDateRangeValue
            : '';
    return { value: granularDateRangeValue, name: dateRangeName };
};
const setFilterValueFromDefault = (defaultValue, filter) => {
    const { granularityOptions, quickFilterOptions } = filter;
    const { granularity, quickFilter, start, end } = defaultValue.value;
    const value = {
        start: start ? dayjs(start, 'D/M/YYYY').format('YYYY-MM-DD').toString() : '',
        end: end ? dayjs(end, 'D/M/YYYY').format('YYYY-MM-DD').toString() : '',
        granularity: {
            value: granularity,
            display: granularityOptions?.find((o) => o.value === granularity)?.text || granularity,
        },
        quickFilter: {
            value: quickFilter,
            display: quickFilterOptions?.find((o) => o.value === quickFilter)?.text || quickFilter,
        },
    };
    return {
        ...filter,
        value,
    };
};
const getFilterFromDefinition = (filter, filterData) => {
    let value;
    const quickFilterValue = filter.defaultQuickFilterValue;
    const granularityOptions = getGranularityOptions();
    const quickFilterOptions = getQuickFilterOptions();
    if (quickFilterValue) {
        const { start, end, granularity } = setDateRangeFromQuickFilterValue(quickFilterValue);
        value = {
            start,
            end,
            granularity: {
                value: granularity,
                display: getOptionDisplayValue(granularity, granularityOptions),
            },
            quickFilter: {
                value: quickFilterValue,
                display: getOptionDisplayValue(quickFilterValue, quickFilterOptions),
            },
            partialDate: {
                ...hasPartialStartEnd(granularity, start, end),
            },
        };
    }
    else {
        value = StartEndDatetUtils.getStartAndEndValueFromDefinition(filter);
        const granularityValue = value.granularity
            ? value.granularity.value
            : filter.defaultGranularity || Granularity.DAILY;
        value = {
            ...value,
            granularity: {
                value: granularityValue,
                display: getOptionDisplayValue(granularityValue, granularityOptions),
            },
            quickFilter: {
                value: QuickFilters.NONE,
                display: 'None',
            },
            partialDate: {
                ...hasPartialStartEnd(granularityValue, value.start, value.end),
            },
        };
    }
    return {
        ...filterData,
        min: filter.min,
        max: filter.max,
        value,
        quickFilterOptions: getQuickFilterOptions(),
        granularityOptions: getGranularityOptions(),
    };
};
/**
 * Creates and appends the granular daterange query string
 * to an existing URLSearchParams
 *
 * @param {URLSearchParams} params
 * @param {string} fieldName
 * @param {string} defaultValue
 */
const appendGranularDateRangeValue = (params, fieldName, options) => {
    const { start, end, granularity, quickFilter } = options;
    if (quickFilter) {
        params.append(`filters.${fieldName}.quick-filter`, quickFilter);
    }
    if (granularity) {
        params.append(`filters.${fieldName}.granularity`, granularity);
    }
    if (start) {
        params.append(`filters.${fieldName}.start`, start);
    }
    if (end) {
        params.append(`filters.${fieldName}.end`, end);
    }
};
/**
 * Resolves default values for a `granulardaterange` filter definition.
 *
 * Applies precedence rules:
 * 1. `defaultQuickFilterValue` (derives start, end, and granularity)
 * 2. `defaultGranularity` combined with `defaultValue` (explicit range)
 * 3. `defaultGranularity` only
 *
 * Returns plain resolved values suitable for query construction, or
 * `undefined` if the definition does not specify any usable defaults.
 *
 * @param {components['schemas']['FilterDefinition']} filter
 * @return {*}  {(GranularDateRangeDefaults | undefined)}
 */
const resolveGranularDateRangeDefaults = (filter) => {
    // Case 1: quick filter wins
    if (filter.defaultQuickFilterValue) {
        const { start, end, granularity } = setDateRangeFromQuickFilterValue(filter.defaultQuickFilterValue);
        return {
            quickFilter: filter.defaultQuickFilterValue,
            granularity,
            ...(start !== undefined ? { start } : {}),
            ...(end !== undefined ? { end } : {}),
        };
    }
    // Case 2: granularity + explicit default range
    if (filter.defaultGranularity && filter.defaultValue) {
        const [start, end] = filter.defaultValue
            .split(' - ')
            .map((v) => v.trim())
            .filter(Boolean);
        return {
            granularity: filter.defaultGranularity,
            ...(start !== undefined ? { start } : {}),
            ...(end !== undefined ? { end } : {}),
        };
    }
    // Case 3: granularity only
    if (filter.defaultGranularity) {
        return {
            granularity: filter.defaultGranularity,
        };
    }
    return undefined;
};
var GranularDateRangeInputUtils = {
    getFilterFromDefinition,
    setValueFromRequest,
    setDefaultValue,
    setFilterValueFromDefault,
    appendGranularDateRangeValue,
    resolveGranularDateRangeDefaults,
};

export { appendGranularDateRangeValue, GranularDateRangeInputUtils as default, getFilterFromDefinition, resolveGranularDateRangeDefaults, setDefaultValue, setFilterValueFromDefault, setValueFromRequest };
//# sourceMappingURL=utils.js.map
