import { identity, pickBy } from 'lodash-es';

import { type SubtasksFormValues } from 'src/pages/dashboard/serviceManagement/agentWorkspace/Subtasks';
import {
  type HistoryApprovalsFormValues,
  type PendingApprovalsFormValues,
} from 'src/pages/dashboard/serviceManagement/agentWorkspace/types';
import { safeIsoDate } from 'src/pages/dashboard/serviceManagement/agentWorkspace/utils';
import { OXXO_SEGMENTATION_OPTIONS } from 'src/pages/dashboard/serviceManagement/constants';
import {
  type AgentGroup,
  type CoordinatorTaskFilters,
  type ParsedTaskAgentPanelFilters,
} from 'src/pages/dashboard/serviceManagement/types';
import { type User } from 'src/types/user';
import { type LokaliseTFunction } from 'src/utils/i18n';

export const parseCoordinatorFilters = (
  formValues: CoordinatorTaskFilters,
): ParsedTaskAgentPanelFilters => {
  if (!formValues) {
    return {
      startDate: null,
      endDate: null,
      serviceItemsIn: [],
      agentsIn: [],
      agentGroupsIn: [],
      statesIn: [],
      initiatorsIn: [],
      collaboratorTypesIn: [],
    };
  }

  const { creationDateFrom, creationDateTo, dateOptions, ...rest } = formValues;

  let start: Date | null = null;
  let end: Date | null = null;

  if (dateOptions?.dateRange) {
    start = creationDateFrom ? new Date(creationDateFrom) : null;
    end = creationDateTo ? new Date(creationDateTo) : null;
  } else if (dateOptions?.lastSevenDays) {
    ({ start, end } = getRelativeDates(7));
  } else if (dateOptions?.lastFourteenDays) {
    ({ start, end } = getRelativeDates(14));
  } else if (dateOptions?.lastThirtyDays) {
    ({ start, end } = getRelativeDates(30));
  }

  // Convert start/end Dates to ISO strings (UTC) using local time
  return {
    startDate: start,
    endDate: end,
    ...rest,
  };
};

export function getRelativeDates(daysAgo: number): { start: Date; end: Date } {
  const end = new Date();
  const start = new Date();
  start.setDate(start.getDate() - daysAgo);
  return { start, end };
}

function parseInitiatorSegmentations(segmentationItems: string[]) {
  if (!segmentationItems || !segmentationItems.length) return null;

  const groupId = OXXO_SEGMENTATION_OPTIONS.groupId;
  const segmentations = {
    [groupId]: segmentationItems,
  };

  const jsonString = JSON.stringify(segmentations);

  return encodeURIComponent(jsonString);
}

export function parseCoordinatorPanelFilters(filters: CoordinatorTaskFilters) {
  const parsedFiltersWithDates = parseCoordinatorFilters(filters);

  // Parse date to UTC and service items as string ids separated by comma
  return pickBy(
    {
      createdAtFrom: safeIsoDate(parsedFiltersWithDates.startDate, true),
      createdAtTo: safeIsoDate(parsedFiltersWithDates.endDate, false),
      catalogItemsIn:
        parsedFiltersWithDates.serviceItemsIn
          ?.map(serviceItem => serviceItem.id)
          .join(',') ?? '',
      statesIn:
        parsedFiltersWithDates.statesIn?.map(state => state.id).join(',') ?? '',
      initiatorsIn:
        parsedFiltersWithDates.initiatorsIn
          ?.map(initiator => initiator.id)
          .join(',') ?? '',
      assigneesIn:
        parsedFiltersWithDates.agentsIn
          ?.map((agent: User) => agent.id)
          .join(',') ?? '',
      agentGroupsIn:
        parsedFiltersWithDates.agentGroupsIn
          ?.map((agentGroup: AgentGroup) => agentGroup.id)
          .join(',') ?? '',
      // OXXO only
      initiatorSegmentations: parseInitiatorSegmentations(
        parsedFiltersWithDates.collaboratorTypesIn?.map(
          (collaboratorType: { title: string; id: number }) =>
            collaboratorType.id.toString(),
        ) ?? [],
      ),
    },
    identity,
  );
}

export const getCreationDateFilterDescription = ({
  dateRangeValueSelected,
  lastSevenDays,
  lastFourteenDays,
  lastThirtyDays,
  fromDate,
  toDate,
  language,
  t,
}: {
  dateRangeValueSelected: boolean;
  lastSevenDays: boolean;
  lastFourteenDays: boolean;
  lastThirtyDays: boolean;
  fromDate?: Date | null;
  toDate?: Date | null;
  t: LokaliseTFunction;
  language: string;
}) => {
  // Check if any of the predefined date options are selected
  if (lastSevenDays) {
    return t('last_n_days', { days: 7 });
  }
  if (lastFourteenDays) {
    return t('last_n_days', { days: 14 });
  }
  if (lastThirtyDays) {
    return t('last_n_days', { days: 30 });
  }

  // Check if date range is selected and handle from/to dates
  if (dateRangeValueSelected) {
    const formatDate = (date: any) => {
      if (!date) return null;
      if (date instanceof Date) {
        return date.toLocaleDateString(language);
      }
      return date.toString().trim();
    };

    const formattedFromDate = formatDate(fromDate);
    const formattedToDate = formatDate(toDate);

    if (formattedFromDate && formattedToDate) {
      return `${formattedFromDate} - ${formattedToDate}`;
    } else if (formattedFromDate) {
      return `${t('from')} ${formattedFromDate}`;
    } else if (formattedToDate) {
      return `${t('general:until')} ${formattedToDate}`;
    }
  }

  return '';
};

/**
 * Calculates the number of active filters for the collaborator panel/filter system.
 * Each of the included array-based filters (e.g., serviceItems, agents, task statuses, etc.)
 * is counted as "active" if it contains at least one selected item. The dateOptions filter
 * is counted as active if any of its values are true.
 *
 * @param filters Partial<CoordinatorTaskFilters>: The filters object, possibly containing only some filter keys.
 * @returns number: The count of active filters currently applied.
 */
export const calculateActiveCollaboratorFiltersCount = (
  filters: Partial<CoordinatorTaskFilters>,
) => {
  let count = 0;

  // Count array filters that have at least one item
  const arrayFilters = [
    'serviceItemsIn',
    'agentsIn',
    'agentGroupsIn',
    'statesIn',
    'initiatorsIn',
    'collaboratorTypesIn',
  ] as const;

  arrayFilters.forEach(key => {
    const value = filters[key];
    if (Array.isArray(value) && value.length > 0) {
      count += 1;
    }
  });

  // Count dateOptions if any option is true
  if (filters.dateOptions && Object.values(filters.dateOptions).some(Boolean)) {
    count += 1;
  }

  return count;
};

export const parseSubtasksFilters = (filters: SubtasksFormValues | null) => {
  if (!filters) return {};

  const { createdAtFrom, createdAtTo, dateOptions } = filters;

  let start: Date | null = null;
  let end: Date | null = null;

  if (dateOptions?.dateRange || !dateOptions) {
    start = createdAtFrom ? new Date(createdAtFrom) : null;
    end = createdAtTo ? new Date(createdAtTo) : null;
  } else if (dateOptions?.lastSevenDays) {
    ({ start, end } = getRelativeDates(7));
  } else if (dateOptions?.lastFourteenDays) {
    ({ start, end } = getRelativeDates(14));
  } else if (dateOptions?.lastThirtyDays) {
    ({ start, end } = getRelativeDates(30));
  }

  return pickBy(
    {
      statesIn: filters.statesIn?.map(state => state.id),
      parentTaskCatalogItemsIn: filters.parentTaskCatalogItemsIn?.map(
        serviceItem => serviceItem.id,
      ),
      parentTaskInitiatorsIn: filters.parentTaskInitiatorsIn?.map(
        initiator => initiator.id,
      ),
      createdAtFrom: safeIsoDate(start, true),
      createdAtTo: safeIsoDate(end, false),
    },
    value =>
      value !== undefined &&
      value !== null &&
      !(Array.isArray(value) && value.length === 0),
  );
};

// Resolves the start/end of an approvals date filter from either a
// preset (`lastSevenDays`/`lastFourteenDays`/`lastThirtyDays`) or an
// explicit `from`/`to` range when `dateRange` is selected.
const resolveDateRange = (
  dateOptions:
    | {
        lastSevenDays?: boolean;
        lastFourteenDays?: boolean;
        lastThirtyDays?: boolean;
        dateRange?: boolean;
      }
    | undefined,
  fromDate: Date | null | undefined,
  toDate: Date | null | undefined,
): { start: Date | null; end: Date | null } => {
  if (dateOptions?.dateRange || !dateOptions) {
    return {
      start: fromDate ? new Date(fromDate) : null,
      end: toDate ? new Date(toDate) : null,
    };
  }
  if (dateOptions.lastSevenDays) return getRelativeDates(7);
  if (dateOptions.lastFourteenDays) return getRelativeDates(14);
  if (dateOptions.lastThirtyDays) return getRelativeDates(30);
  return { start: null, end: null };
};

export const parsePendingApprovalsFilters = (
  filters: PendingApprovalsFormValues | null,
) => {
  if (!filters) return {};

  const { start, end } = resolveDateRange(
    filters.dateOptions,
    filters.createdAtFrom,
    filters.createdAtTo,
  );

  return pickBy(
    {
      parentTaskCatalogItemsIn: filters.parentTaskCatalogItemsIn?.map(
        serviceItem => serviceItem.id,
      ),
      parentTaskInitiatorsIn: filters.parentTaskInitiatorsIn?.map(
        initiator => initiator.id,
      ),
      createdAtFrom: safeIsoDate(start, true),
      createdAtTo: safeIsoDate(end, false),
    },
    value =>
      value !== undefined &&
      value !== null &&
      !(Array.isArray(value) && value.length === 0),
  );
};

export const parseHistoryApprovalsFilters = (
  filters: HistoryApprovalsFormValues | null,
) => {
  if (!filters) return {};

  const { start, end } = resolveDateRange(
    filters.dateOptions,
    filters.completedAtFrom,
    filters.completedAtTo,
  );

  return pickBy(
    {
      parentTaskCatalogItemsIn: filters.parentTaskCatalogItemsIn?.map(
        serviceItem => serviceItem.id,
      ),
      statesIn: filters.statesIn?.map(state => state.id),
      parentTaskInitiatorsIn: filters.parentTaskInitiatorsIn?.map(
        initiator => initiator.id,
      ),
      completedAtFrom: safeIsoDate(start, true),
      completedAtTo: safeIsoDate(end, false),
    },
    value =>
      value !== undefined &&
      value !== null &&
      !(Array.isArray(value) && value.length === 0),
  );
};
