import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { UdpCalendar } from '../../../UI/templates/calendar/UdpCalendar';
import { useTransactionEngine } from '../../../utilities/transactions/useTransactionEngine';
import { useAxiosMutate } from '../../../utilities';
import { ConfigService } from '../../../configService';
import { AmbientCard } from '../../../UI/surfaces/cards/AmbientCard';
import { UdpSearchEnums } from '../../../enums';
import { UdpFlexbox } from '../../../UI/fluent-web-components/UdpFlexbox';
import { UdpBadge } from '../../../UI/fluent-web-components/UdpBadge';
import { UdpPrimaryActionHeader } from '../../../UI/fluent-web-components/UdpPrimaryActionHeader';
const CALENDAR_VIEW_OPTIONS = ['day', 'week', 'month'];
const normalizeCalendarView = (value) => {
    const normalized = (value || '').toString().toLowerCase();
    return CALENDAR_VIEW_OPTIONS.includes(normalized) ? normalized : 'week';
};
const buildDomainSearchField = (domainName, propertyName) => `${UdpSearchEnums.UdpBusinessDomainPrefix}.${domainName}.${propertyName}`;
function format12HourTime(date) {
    if (!date) {
        return '';
    }
    const hours = date.getHours();
    const minutes = date.getMinutes();
    const ampm = hours >= 12 ? 'PM' : 'AM';
    const hour12 = hours % 12 || 12; // Convert hours to 12-hour format
    return `${hour12}:${minutes.toString().padStart(2, '0')} ${ampm}`;
}
const formatDate = d => d.toISOString().split('T')[0];
const STATUS_BG_COLORS = {
    warning: '#fff4ce',
    success: '#bdedbd',
    info: '#a9d3f2',
    gray: '#f5f5f5'
};
const DEFAULT_STATUS_BG = '#f5f5f5';
const UdpTransactionCalendar = (props) => {
    var _a, _b;
    const { transactionTypeId, domainName, searchMethodObject, calendarViewConfiguration, openWorkflowActionTransaction, handleCalendarApiCallback, openAddTransaction, gridTitle, hideCreateTransaction = false, onShowGridView } = props;
    const domainStartDateProperty = (_a = calendarViewConfiguration === null || calendarViewConfiguration === void 0 ? void 0 : calendarViewConfiguration.domainStartDateProperty) !== null && _a !== void 0 ? _a : '';
    const domainEndDateProperty = (_b = calendarViewConfiguration === null || calendarViewConfiguration === void 0 ? void 0 : calendarViewConfiguration.domainEndDateProperty) !== null && _b !== void 0 ? _b : '';
    const { t } = useTranslation();
    const { getTransactionTypeLabel, transactionTypeStatusColorsMap, transactionTypePageConfiguration } = useTransactionEngine(transactionTypeId);
    const headerConfig = useMemo(() => {
        const title = gridTitle || (transactionTypePageConfiguration === null || transactionTypePageConfiguration === void 0 ? void 0 : transactionTypePageConfiguration.gridTitle) || domainName;
        const hideCreate = hideCreateTransaction ||
            (transactionTypePageConfiguration === null || transactionTypePageConfiguration === void 0 ? void 0 : transactionTypePageConfiguration.hideCreateTransaction);
        return {
            title,
            primaryAction: hideCreate
                ? undefined
                : {
                    label: (transactionTypePageConfiguration === null || transactionTypePageConfiguration === void 0 ? void 0 : transactionTypePageConfiguration.createTransactionButtonLabel) ||
                        `${domainName} Entry`,
                    iconName: 'add',
                    onClick: () => openAddTransaction === null || openAddTransaction === void 0 ? void 0 : openAddTransaction()
                },
            secondaryActions: [
                {
                    iconOnly: true,
                    iconName: 'table',
                    label: t('Grid View'),
                    onClick: () => onShowGridView === null || onShowGridView === void 0 ? void 0 : onShowGridView()
                }
            ]
        };
    }, [
        gridTitle,
        domainName,
        hideCreateTransaction,
        transactionTypePageConfiguration,
        openAddTransaction,
        onShowGridView,
        t
    ]);
    const [initialCalendarView] = useState(normalizeCalendarView(calendarViewConfiguration === null || calendarViewConfiguration === void 0 ? void 0 : calendarViewConfiguration.defaultCalendarViewType));
    const [calendarRange, setCalendarRange] = useState(null);
    const [calendarEvents, setCalendarEvents] = useState([]);
    const handleCalendarDatesSet = useCallback((rangeInfo) => {
        setCalendarRange({
            start: new Date(rangeInfo.start),
            end: new Date(rangeInfo.end),
        });
    }, []);
    const hasDomainDateConfig = Boolean(domainName && domainStartDateProperty && domainEndDateProperty);
    const searchObject = useMemo(() => {
        const baseFilters = [
            {
                searchField: 'transactionTypeId',
                searchOperator: '=',
                searchValue: transactionTypeId
            },
            {
                searchField: 'isDeleted',
                searchOperator: '=',
                searchValue: false
            }
        ];
        const dateRangeFilters = [];
        if (domainName &&
            domainStartDateProperty &&
            domainEndDateProperty &&
            (calendarRange === null || calendarRange === void 0 ? void 0 : calendarRange.start) &&
            (calendarRange === null || calendarRange === void 0 ? void 0 : calendarRange.end)) {
            const startField = buildDomainSearchField(domainName, domainStartDateProperty);
            const endField = buildDomainSearchField(domainName, domainEndDateProperty);
            const rangeStartFormatted = formatDate(calendarRange.start);
            const rangeEndFormatted = formatDate(calendarRange.end);
            dateRangeFilters.push({
                searchField: startField,
                searchOperator: '<=',
                searchValue: rangeEndFormatted
            }, {
                searchField: endField,
                searchOperator: '>=',
                searchValue: rangeStartFormatted
            });
        }
        const extraFilters = (searchMethodObject === null || searchMethodObject === void 0 ? void 0 : searchMethodObject.filterElements) || [];
        return Object.assign(Object.assign({ eagerLoad: true, getAll: true }, (searchMethodObject || {})), { filterElements: baseFilters.concat(dateRangeFilters, extraFilters) });
    }, [
        transactionTypeId,
        searchMethodObject,
        domainName,
        domainStartDateProperty,
        domainEndDateProperty,
        calendarRange
    ]);
    const [{ loading }, executeSearch] = useAxiosMutate(ConfigService.productV1ApiUrl, 'UdpTransaction/search', { method: 'post' });
    const legendItems = useMemo(() => Object.entries(transactionTypeStatusColorsMap !== null && transactionTypeStatusColorsMap !== void 0 ? transactionTypeStatusColorsMap : {}).map(([label, colorKey]) => {
        var _a;
        return ({
            label,
            color: (_a = STATUS_BG_COLORS[colorKey]) !== null && _a !== void 0 ? _a : DEFAULT_STATUS_BG
        });
    }), [transactionTypeStatusColorsMap]);
    const applyCalendarResponse = useCallback((response) => {
        var _a;
        var _b;
        if ((response === null || response === void 0 ? void 0 : response.status) !== 200) {
            setCalendarEvents([]);
            return;
        }
        const pageList = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.pageList) !== null && _b !== void 0 ? _b : [];
        const formatted = pageList
            .map((transaction) => {
            var _a;
            var _b, _c, _d, _e;
            const ebo = (_b = transaction === null || transaction === void 0 ? void 0 : transaction.entityBusinessObject) !== null && _b !== void 0 ? _b : {};
            const startValue = ebo[domainStartDateProperty];
            const endValue = ebo[domainEndDateProperty];
            const eventStart = startValue !== null && startValue !== void 0 ? startValue : endValue;
            if (!eventStart)
                return null;
            const statusName = (_a = transaction === null || transaction === void 0 ? void 0 : transaction.udpTransactionUdpTransactionTypeStatus) === null || _a === void 0 ? void 0 : _a.name;
            const statusColorKey = transactionTypeStatusColorsMap === null || transactionTypeStatusColorsMap === void 0 ? void 0 : transactionTypeStatusColorsMap[statusName];
            const statusBg = (_c = STATUS_BG_COLORS[statusColorKey]) !== null && _c !== void 0 ? _c : DEFAULT_STATUS_BG;
            return Object.assign(Object.assign({ title: (_e = (_d = getTransactionTypeLabel(transaction)) !== null && _d !== void 0 ? _d : transaction === null || transaction === void 0 ? void 0 : transaction.entityBusinessKey) !== null && _e !== void 0 ? _e : domainName, start: eventStart }, (startValue && endValue ? { end: endValue } : {})), { backgroundColor: 'transparent', borderColor: 'transparent', extendedProps: Object.assign(Object.assign({}, transaction), { statusBg }) });
        })
            .filter(Boolean);
        setCalendarEvents(formatted);
    }, [
        domainStartDateProperty,
        domainEndDateProperty,
        domainName,
        getTransactionTypeLabel,
        transactionTypeStatusColorsMap
    ]);
    const refreshCalendarEvents = useCallback(async () => {
        if (!hasDomainDateConfig)
            return;
        if (!(calendarRange === null || calendarRange === void 0 ? void 0 : calendarRange.start) || !(calendarRange === null || calendarRange === void 0 ? void 0 : calendarRange.end))
            return;
        try {
            const response = await executeSearch({ data: searchObject });
            applyCalendarResponse(response);
        }
        catch (_a) {
            setCalendarEvents([]);
        }
        // executeSearch intentionally excluded — axios-hooks returns a new identity each render.
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [hasDomainDateConfig, calendarRange, searchObject, applyCalendarResponse]);
    useEffect(() => {
        if (!hasDomainDateConfig)
            return;
        if (!(calendarRange === null || calendarRange === void 0 ? void 0 : calendarRange.start) || !(calendarRange === null || calendarRange === void 0 ? void 0 : calendarRange.end))
            return;
        let cancelled = false;
        executeSearch({ data: searchObject })
            .then((response) => {
            if (cancelled)
                return;
            applyCalendarResponse(response);
        })
            .catch(() => {
            if (!cancelled)
                setCalendarEvents([]);
        });
        return () => { cancelled = true; };
        // executeSearch intentionally excluded — axios-hooks returns a new identity each render.
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [searchObject, hasDomainDateConfig, calendarRange, applyCalendarResponse]);
    useEffect(() => {
        if (!handleCalendarApiCallback)
            return;
        handleCalendarApiCallback(refreshCalendarEvents);
        return () => handleCalendarApiCallback(null);
    }, [handleCalendarApiCallback, refreshCalendarEvents]);
    return (React.createElement("div", null, React.createElement(UdpPrimaryActionHeader, { title: headerConfig.title, primaryAction: headerConfig.primaryAction, secondaryActions: headerConfig.secondaryActions }), legendItems.length > 0 && (React.createElement("div", { style: { marginBottom: '4px' } }, React.createElement(UdpFlexbox, { direction: "row", wrap: "wrap", justify: "flex-end" }, legendItems.map(({ label, color }) => (React.createElement(UdpBadge, { key: label, appearance: "ghost" }, React.createElement("span", { slot: "start", style: {
            display: 'inline-block',
            width: 'var(--udp-spacing-md, 8px)',
            height: 'var(--udp-spacing-md, 8px)',
            marginRight: 'var(--udp-spacing-sm, 4px)',
            borderRadius: '50%',
            backgroundColor: color
        } }), label)))))), React.createElement(AmbientCard, { fullWidth: true }, React.createElement(UdpCalendar, { initialView: initialCalendarView, toggleViewOptions: "dayGridDay,dayGridWeek,dayGridMonth", events: calendarEvents, eventOnclick: (info) => { openWorkflowActionTransaction(info.event.extendedProps); }, eventContent: info => {
            var _a, _b, _c;
            var _d, _e, _f;
            const now = Date.now();
            const startMs = (_d = (_a = info.event.start) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _d !== void 0 ? _d : 0;
            const endMs = (_e = (_b = info.event.end) === null || _b === void 0 ? void 0 : _b.getTime()) !== null && _e !== void 0 ? _e : startMs;
            const isPast = endMs < now;
            const bg = (_f = (_c = info.event.extendedProps) === null || _c === void 0 ? void 0 : _c.statusBg) !== null && _f !== void 0 ? _f : '#f5f5f5';
            const opacity = 1; //isPast ? 0.65 : 1; // Keeping past events at full opacity as per UX feedback, but can be adjusted if needed.
            const startDate = info.event.start;
            const endDate = info.event.end;
            const startDay = startDate ? startDate.toDateString() : null;
            const endDay = endDate ? endDate.toDateString() : null;
            const segmentSpansMultipleDays = info.isStart && info.isEnd && endDay && startDay !== endDay;
            let timeRowHtml = '';
            if (segmentSpansMultipleDays) {
                timeRowHtml = `<div style="display:flex; justify-content:space-between; gap:8px; word-wrap: break-word; white-space: normal;"><b>${format12HourTime(startDate)}</b><b>${format12HourTime(endDate)}</b></div>`;
            }
            else if (info.isStart && info.isEnd) {
                timeRowHtml = `<div style="word-wrap: break-word; white-space: normal;"><b>${format12HourTime(startDate)}${endDate ? ' - ' + format12HourTime(endDate) : ''}</b></div>`;
            }
            else if (info.isStart) {
                timeRowHtml = `<div style="word-wrap: break-word; white-space: normal;"><b>${format12HourTime(startDate)}</b></div>`;
            }
            else if (info.isEnd) {
                timeRowHtml = `<div style="word-wrap: break-word; white-space: normal; text-align:right;"><b>${format12HourTime(endDate)}</b></div>`;
            }
            return {
                html: `
              <div style="width:100%; cursor:pointer; padding:5px; background-color: ${bg}; color: #242424; opacity: ${opacity};">
                ${timeRowHtml}
                <div style="word-wrap: break-word; white-space: normal;">
                  ${info.event.title + ' - ' + info.event.extendedProps.entityBusinessObject[calendarViewConfiguration === null || calendarViewConfiguration === void 0 ? void 0 : calendarViewConfiguration.domainPropertyToDisplay]}
                </div>
              </div>
            `,
            };
        }, width: 'auto', height: 700, dayHeaders: true, datesSet: handleCalendarDatesSet }))));
};
export default UdpTransactionCalendar;
//# sourceMappingURL=UdpTransactionCalendar.js.map