import api from 'src/config/api';
import {
  type ApprovableStatus,
  type ApprovalRequest,
  type CategorizedHourApprovalStep,
  type CategorizedHourStatusOverride,
  type ClockSummaries,
  type ControlRegister,
  type ControlRegisterPaginationParams,
  type CycleUpdateParam,
  type DaySummary,
  type DayDetailResponse,
  type EntryType,
  type HourCategory,
  type PerformanceReportParams,
  type Region,
  type SiteCoordinates,
  type TimeTrackingCategorizedHourStatus,
  type TimeTrackingEntry,
  type TimeTrackingPolicies,
  type UserSite,
} from 'src/types/timeTracking';
import { type User } from 'src/types/user';
import {
  type PaginatedResponse,
  type PaginationParams,
} from 'src/utils/pagination';

// The endpoint's method is defined as a GET
export const prepareReportEmail = ({
  reportType,
  userFields,
  userCustomFields,
  segmentationGroups,
  hourCategoryIds,
  includeScheduledTime,
  includeClockInOut,
  includeAutoCloseIncidence,
  includeKiosk,
  ...rest
}: PerformanceReportParams) =>
  api.get('/time-tracking/report-async', {
    params: {
      ...rest,
      userFields,
      userCustomFields,
      groupIds: segmentationGroups,
      type: reportType,
      hourCategoryIds,
      includeScheduledTime,
      includeClockInOut,
      includeAutoCloseIncidence,
      includeKiosk,
    },
  });

export const getTimeControlRegisters = (
  params: ControlRegisterPaginationParams,
  signal: AbortSignal,
) =>
  api.get<PaginatedResponse<ControlRegister>>('/time-tracking/day-summaries', {
    params,
    signal,
  });

export const getUserSites = (id: number) =>
  api.get<UserSite[]>(`/sites/user/${id}`);

export const modifyEntries = (cycle: CycleUpdateParam) =>
  api.put<DaySummary>('/time-tracking/entries/', cycle);

export const getRegions = (params: PaginationParams) =>
  api.get<PaginatedResponse<Region>>('/time-tracking/regions', { params });

// Returns users with assigned time policies
export const getUsers = (params: PaginationParams) => {
  // Endpoint will throw error if search is falsy (undefined, null, empty string)
  if (!params.search) {
    delete params.search;
  }
  return api.get<PaginatedResponse<User>>('/time-tracking/users', { params });
};

export const getTimeTrackingDaySummary = () =>
  api.get<ClockSummaries>('/time-tracking/day-summary');

export const getDayDetail = (userId: number, date: string) =>
  api.get<DayDetailResponse>('/time-tracking/day-summaries/detail', {
    params: { userId, date },
  });

export const getTimeTrackingPolicies = (userId: number) =>
  api.get<TimeTrackingPolicies>('/time-tracking/policies', {
    params: { userId },
  });

export type ClockInParams = {
  type: EntryType;
  siteId: number | null;
  location: SiteCoordinates | null;
  comment?: string;
};

export const persistClockIn = (params: ClockInParams) =>
  api.post('/time-tracking/entries', { ...params, source: 'WEB' });

export const persistClockInDeagle = (params: ClockInParams) =>
  api.post<TimeTrackingEntry>('/desert-eagle/time-tracking/entries', {
    ...params,
    source: 'WEB',
  });

export const getHourCategories = (params: PaginationParams) =>
  api.get<PaginatedResponse<HourCategory>>('/time-tracking/hour-categories', {
    params,
  });

////// Overtime Approval requests //////

export type CategorizedHoursParams = PaginationParams & {
  status: string;
  siteIds?: string;
  startDate?: string;
  endDate?: string;
  sortBy?: string;
  sortOrder?: 'asc' | 'desc';
  userIds?: string;
  hourCategoryIds?: string;
  itemIds?: string;
};

type PendingRequestsAmountResponse = {
  amount: number;
};

export const getPendingRequestsAmount = () =>
  api.get<PendingRequestsAmountResponse>(
    '/time-tracking/categorized-hours/pending-amount',
  );

export const getCategorizedHoursRequests = (params: CategorizedHoursParams) =>
  api.get<PaginatedResponse<ApprovalRequest>>(
    '/time-tracking/categorized-hours',
    {
      params,
    },
  );

export const getCategorizedHour = (id: string) =>
  api.get<ApprovalRequest>(`/time-tracking/categorized-hours/${id}`);

export type UpdateCategorizedHourParams = {
  id: string;
  status: ApprovableStatus;
  note: string;
};

export const updateCategorizedHour = ({
  id,
  status,
  note,
}: UpdateCategorizedHourParams) =>
  api.patch<ApprovalRequest>(`/time-tracking/categorized-hours/${id}`, {
    status,
    note,
  });

export type ReviewCategorizedHourApprovalStepParams = {
  categorizedHourId: string;
  /** Numeric legacy ids or UUID strings from the API */
  approvalStepId: number | string;
  state: ApprovableStatus;
  comment?: string;
};

export type ReviewCategorizedHourApprovalStepResult = {
  approvalSteps: CategorizedHourApprovalStep[];
  status: TimeTrackingCategorizedHourStatus;
};

export const reviewCategorizedHourApprovalStep = ({
  categorizedHourId,
  approvalStepId,
  state,
  comment,
}: ReviewCategorizedHourApprovalStepParams) =>
  api.put<ReviewCategorizedHourApprovalStepResult>(
    `/time-tracking/categorized-hours/${categorizedHourId}/approval-steps/${approvalStepId}/state`,
    { state, ...(comment && { comment }) },
  );

export type OverrideCategorizedHourStatusParams = {
  id: string;
  status: ApprovableStatus;
  comment?: string;
};

export type OverrideCategorizedHourStatusResult = {
  status: TimeTrackingCategorizedHourStatus;
  approvalSteps: CategorizedHourApprovalStep[];
  statusOverride: CategorizedHourStatusOverride;
};

export const overrideCategorizedHourStatus = ({
  id,
  status,
  comment,
}: OverrideCategorizedHourStatusParams) =>
  api.patch<OverrideCategorizedHourStatusResult>(
    `/time-tracking/categorized-hours/${id}/status`,
    { status, ...(comment && { comment }) },
  );
