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

import api from 'src/config/api';
import {
  type CoordinatorFilterParams,
  type HydratedTask,
  type Task,
  type VisitTaskBody,
} from 'src/pages/dashboard/serviceManagement/types';
import { type Pagination } from 'src/types/services';

const safeEncode = (val: string) => {
  try {
    return encodeURIComponent(decodeURIComponent(val));
  } catch {
    return encodeURIComponent(val);
  }
};

let abortController: AbortController | null = null;

export const getTasks = ({
  limit,
  cursor,
  page,
  usePage = false,
  order,
  orderBy,
  role,
  q,
  statesIn,
  catalogItemsIn,
  createdAtFrom,
  createdAtTo,
  completedAtFrom,
  completedAtTo,
  initiatorsIn,
  assigneesIn,
  initiatorSegmentations,
  parentTaskInitiatorsIn,
  parentTaskCatalogItemsIn,
  type,
  closed,
}: any) => {
  if (abortController) {
    abortController.abort();
  }

  abortController = new AbortController();

  const paginationParams = usePage ? { page: page ?? 1 } : { cursor };

  return api.get<Pagination<Task[]>>('workflows/tasks', {
    params: pickBy(
      {
        text: q,
        limit,
        ...paginationParams,
        sortField: orderBy,
        sortDirection: order,
        role,
        statesIn,
        catalogItemsIn,
        createdAtFrom,
        createdAtTo,
        completedAtFrom,
        completedAtTo,
        initiatorsIn,
        assigneesIn,
        initiatorSegmentations,
        parentTaskInitiatorsIn,
        parentTaskCatalogItemsIn,
        type,
        closed,
      },
      value => {
        // Keep boolean values
        return typeof value === 'boolean' || Boolean(value);
      },
    ),
    paramsSerializer: params => {
      return Object.entries(params)
        .map(
          ([key, value]) =>
            `${safeEncode(String(key))}=${safeEncode(String(value))}`,
        )
        .join('&');
    },
    signal: abortController.signal,
  });
};

export const getHydratedTasks = (params: CoordinatorFilterParams) =>
  api.get<Pagination<HydratedTask[]>>(`workflows/tasks/hydrated`, {
    params: pickBy(params, identity),
    paramsSerializer: p => {
      return Object.entries(p)
        .map(
          ([key, value]) =>
            `${safeEncode(String(key))}=${safeEncode(String(value))}`,
        )
        .join('&');
    },
  });

export const getTask = (id: string) => api.get<Task>(`workflows/tasks/${id}`);

export const visitTask = (taskId: string, body?: VisitTaskBody) =>
  api.post(`workflows/tasks/${taskId}/visit`, body);
