import { type TablerIcon } from '@material-hu/icons/tabler';

import { type FileExtensions } from 'src/constants/filesPreview';
import { type PaginationParams } from 'src/utils/pagination';
import { type iconsPolicyTypes } from 'src/utils/vacations';

import { type AutocompleteField } from 'src/components/AdvancedFilter/types';

import { type Days } from './date';
import { type TimeTrackingDaySummaryHours } from './shifts';
import { type User } from './user';

export enum ReportType {
  CONSOLIDATED = 'consolidated',
  DETAILED = 'detailed',
}

export type PerformanceReportParams = {
  startDate: string;
  endDate: string;
  userIds: string;
  itemIds: string;
  userFields: string;
  userCustomFields: string;
  segmentationGroups: string;
  reportType?: ReportType;
  search: string;
  status: string;
  incidences: string;
  email: string;
  hourCategoryIds?: string;
  includeScheduledTime?: boolean;
  includeClockInOut?: boolean;
  includeAutoCloseIncidence?: boolean;
  includeKiosk?: boolean;
};

export type GroupItem = {
  label: string;
  value: number;
  checked: boolean;
};

export type SegmentationGroup = {
  name: string;
  value: number;
  items: GroupItem[];
};

export type ReportExtension = FileExtensions.XLSX | FileExtensions.CSV;

export type ReportFilterFields = {
  segmentationItems: Record<string, boolean>;
  users: User[];
  statusItems: Record<string, boolean>;
  incidencesItems: Record<string, boolean>;
  siteIds: Record<string, boolean>;
  hasHoliday: boolean;
  hasTimeOff: boolean;
  includeDeactivated: boolean;
};

export type ReportDownloadFields = {
  email: string;
  enableProfileFields: boolean;
  enableSegmentationGroups: boolean;
  enableHourTypes: boolean;
  profileFields: AutocompleteField[];
  segmentationGroups: AutocompleteField[];
  hourTypes: Record<string | number, boolean>;
  reportType: ReportType;
  fileExtension: ReportExtension;
  // Detailed report options
  includeScheduledTime: boolean;
  includeClockInOut: boolean;
  includeAutoCloseIncidence: boolean;
  includeKiosk: boolean;
};

export enum UserTrackingStatus {
  ACTIVE = 'ACTIVE',
  NOT_CLOCKED_IN = 'NOT_CLOCKED_IN',
  INACTIVE = 'INACTIVE',
}

export enum UserAccountStatus {
  ACTIVE = 'ACTIVE',
  DEACTIVATED = 'DEACTIVATED',
}

export enum Incidence {
  ABSENT = 'ABSENT',
  AUTO_CLOSE = 'AUTO_CLOSE',
  EXTRA_HOURS = 'EXTRA_HOURS',
  FACIAL_RECOGNITION_SKIPPED = 'FACIAL_RECOGNITION_SKIPPED',
  LATE = 'LATE',
  LOCATION_INCIDENCE = 'LOCATION_INCIDENCE',
  NOT_CLOCKED_IN = 'NOT_CLOCKED_IN',
  UNDERWORKED = 'UNDERWORKED',
}

export enum TrackingDayType {
  WORK = 'work',
  FREE = 'free',
  VACATION = 'vacation',
}

export type ControlRegister = {
  currentDate: string;
  daySummaries: DaySummary[];
  differenceHours: number;
  estimatedHours: number;
  extraHours: number;
  fullName: string;
  incidencesTagsPresent: Incidence[];
  profilePicture: string | null;
  status: UserTrackingStatus;
  userAccountStatus: UserAccountStatus;
  userId: number;
  workedHours: number;
  workScheduleName: string;
};

export type ControlRegisterParams = {
  startDate: string;
  endDate: string;
  search: string;
  userIds: string;
  siteIds: string;
  itemIds: string;
  status: string;
  incidences: string;
  includeDeactivated?: boolean;
};

export type UserControlParams = Pick<
  ControlRegisterParams,
  'userIds' | 'endDate' | 'startDate' | 'includeDeactivated'
>;

export type ControlRegisterPaginationParams = ControlRegisterParams &
  PaginationParams;

export enum EntryType {
  START = 'START',
  END = 'END',
}

export enum EntrySource {
  APP = 'APP',
  AUTO_CLOSE = 'AUTO_CLOSE',
  DAY_CHANGE = 'DAY_CHANGE',
  INTEGRATION = 'INTEGRATION',
  KIOSK = 'KIOSK',
  MANUAL = 'MANUAL',
  SYSTEM = 'SYSTEM',
  WEB = 'WEB',
  // DELETE
  USER = 'USER',
}

type KioskData = {
  botAppId: number | null;
  createdBy: number;
  description: string;
  faceRecognitionBlocking: boolean;
  faceRecognitionEnabled: boolean;
  id: string;
  instance: null;
  instanceId: number | null;
  name: string;
  status: 'ACTIVE' | 'INACTIVE';
};

export type SiteLocation = {
  latitude: number;
  longitude: number;
  tolerance: number;
  address: string;
};

export type SiteCoordinates = Pick<SiteLocation, 'latitude' | 'longitude'>;

export type TimeTrackingEntry = {
  comment: string | null;
  createdAt: string; // Format: "2026-03-04T20:07:27.525359191Z"
  createdBy: number | null;
  entryId: string;
  eventTime: string | null;
  facialRecognitionSkipped: boolean | null;
  id: number;
  instanceId: number;
  isRemoteWork: boolean;
  kiosk: KioskData | null;
  kioskId: string | null;
  latitude: number | null;
  location: SiteCoordinates | null;
  locationIncidence: boolean;
  longitude: number | null;
  siteId: number | null;
  siteName: string | null;
  autoCloseFallback?:
    | 'SCHEDULED_HOURS_NO_PLANNING'
    | 'SCHEDULED_HOURS_HOURS_COMPLETED'
    | 'END_OF_WORKDAY_NO_PLANNING'
    | 'END_OF_WORKDAY_ENTRY_AFTER_SLOT'
    | null;
  source: EntrySource;
  summaryId: number;
  time: string; // Format "2026-03-04T20:07:27.525359191Z"
  type: EntryType;
  updatedAt: string; // Format: "2026-03-04T20:07:27.525359191Z"
  updatedBy: number | null;
  userId: number;
};

// Type use for creating entries
export type DraftEntry = Partial<TimeTrackingEntry>;

export type PairedEntry = {
  id: string;
  start?: TimeTrackingEntry | DraftEntry;
  end?: TimeTrackingEntry | DraftEntry;
};

export type TimeSlot = {
  startTime: string;
  endTime: string;
};

export type Holiday = {
  id: number;
  daySummaryId: number;
  holidayId: number;
  holidayName: string;
};

export type TimeOffRequest = {
  activityType: 'NON_WORK' | 'WORK';
  consumptionType: 'HALF_DAY' | 'FULL_DAY' | 'HOURS' | null; // null is for retrocompatibility with older daySummaries
  daySummaryId: number;
  fromDate: string | null; // Format: 'YYYY-MM-DD'
  fromTime: string | null; // Format: 'HH:MM'
  hours: number | null;
  id: number;
  timeOffPolicyTypeIcon: keyof typeof iconsPolicyTypes;
  timeOffPolicyTypeName: string;
  timeOffRequestId: number;
  toDate: string | null; // Format: 'YYYY-MM-DD'
  toTime: string | null; // Format: 'HH:MM'
};

export enum ScheduleSource {
  NO_SCHEDULE = 'NO_SCHEDULE',
  WORK_SCHEDULE = 'WORK_SCHEDULE',
  SHIFT = 'SHIFT',
}

export type ShiftAssociations = {
  description: string;
  id: number;
  name: string;
  timeSlots: TimeSlot[];
};

export type DaySummary = {
  autoCloseMode?:
    | 'FIXED_HOURS'
    | 'SCHEDULED_HOURS'
    | 'END_OF_WORKDAY'
    | 'ALERT_ONLY';
  autoCloseTime?: string | null;
  date: string;
  dateString: string;
  dayChange: string;
  estimatedHours: number;
  extraHours: number;
  holidays: Holiday[];
  id: number;
  incidences: Incidence[];
  instanceId: number;
  isWorkday: boolean;
  latenessTolerance: number | null;
  nightShift: boolean;
  scheduledHours: number;
  scheduleSource: ScheduleSource;
  shiftAssignedDayId?: number;
  shiftAssociations?: ShiftAssociations[];
  state: 'OPEN' | 'CLOSED';
  timeOffRequests: TimeOffRequest[];
  timeSlots: TimeSlot[] | null;
  timeTrackingEntries: TimeTrackingEntry[];
  userId: number;
  weekday: Days;
  workedHours: number;
  workScheduleDescription?: string;
  workScheduleId?: number;
  workScheduleName?: string;
};

export type LocationState = {
  fromDate: Date;
  toDate: Date;
};

export type TimeTrackingOutletContext = {
  fromDate: Date;
  toDate: Date;
  handleFromDateChange: (date: Date) => void;
  handleToDateChange: (date: Date) => void;
  search: string;
  setSearch: (search: string) => void;
  reportFilters: ReportFilterFields | null;
  setReportFilters: (filters: ReportFilterFields) => void;
  setTotalRecords: (total: number) => void;
  totalRecords: number;
};

export type UserSite = {
  assignedAllUsers: boolean;
  createdAt: string;
  id: number;
  body: string | null;
  location: SiteLocation;
  name: string;
  updatedAt: string;
  userIds: number[] | null;
};

export type CycleUpdateParam = {
  summaryId?: number;
  entries: DraftEntry[];
};

export type TimePairs = {
  id?: string;
  end: string;
  start: string;
};

export type EntryField = {
  time: Date | undefined;
  siteId: number;
  kioskId?: number;
  comment: string;
};

export type EntryFormFields = {
  start: EntryField;
  end: EntryField;
};

export type DirtyEntryFormFields = {
  start?: Partial<Record<keyof EntryField, boolean>>;
  end?: Partial<Record<keyof EntryField, boolean>>;
};

export type ModifiedEntryFields = {
  values: Partial<EntryField>;
  currentEntry?: Partial<TimeTrackingEntry>;
  summaryDay: string;
  sites: UserSite[];
  timezone: string;
  applyNightShift?: boolean;
};

export type RegionHoliday = {
  date: string;
  id: number;
  name: string;
  createdAt: string;
  updatedAt: string;
};

export type Site = {
  body: string;
  location: SiteLocation;
  id: number;
  name: string;
  userIds: number[];
};

export type Region = {
  body: string;
  holidays?: RegionHoliday[];
  id: number;
  sitesCount: number;
  title: string;
  userCount: string;
  userIds: number[];
  sites: Site[];
};

export type ParsedHoliday = {
  hours: number;
  name: string;
  type: 'HOLIDAY' | 'TIME_OFF';
  icon: TablerIcon;
};

export type TimeTrackingPolicies = {
  allUsers: boolean;
  clockingInAppEnabled: boolean;
  clockingInKioskEnabled: boolean;
  clockingInWebEnabled: boolean;
  description: string;
  enableRemoteWork: boolean;
  faceRecognitionBlocking: boolean;
  faceRecognitionEnabled: boolean;
  id: number;
  instanceId: number;
  latenessTolerance: number;
  name: string;
  nightShift: boolean;
  notificationsEnabled: boolean;
  userIds: number[];
};

type ScheduledDay = {
  dayOfWeek:
    | 'MONDAY'
    | 'TUESDAY'
    | 'WEDNESDAY'
    | 'THURSDAY'
    | 'FRIDAY'
    | 'SATURDAY'
    | 'SUNDAY';
  timeSlots: TimeSlot[];
};

type WorkSchedule = {
  autoCreated: boolean;
  code: string;
  collaborators: number[];
  createdAt: string;
  createdBy: number;
  deletedAt: string | null;
  description: string;
  generalTimeSlots: TimeSlot[];
  hash: string | null;
  id: number;
  instanceId: number;
  lastVersion: boolean;
  name: string;
  scheduledDays: ScheduledDay[];
  updatedAt: string;
  version: number;
};

export type ClockSummaries = {
  daySummary: DaySummary;
  previousDaySummary: DaySummary;
  entries: Omit<PairedEntry, 'id'>[];
  estimatedHours: number;
  workSchedule: WorkSchedule;
};

export type TimeOffPopoverInfo = {
  timeOff: TimeOffRequest;
  schedule: {
    summaryHours: TimeTrackingDaySummaryHours;
    timeSlots: TimeSlot[];
  };
};

export type HourCategory = {
  id: number;
  name: string;
};

// --- Day Detail (daily drawer endpoint) ---

export enum DayDetailEntryType {
  CLOCK_IN = 'CLOCK_IN',
  CLOCK_OUT = 'CLOCK_OUT',
}

export enum DayDetailEntrySource {
  MOBILE = 'MOBILE',
  WEB = 'WEB',
  KIOSK = 'KIOSK',
  MANUAL = 'MANUAL',
  AUTO_CLOSE = 'AUTO_CLOSE',
  DAY_CHANGE = 'DAY_CHANGE',
  INTEGRATION = 'INTEGRATION',
  SYSTEM = 'SYSTEM',
}

export enum DayDetailScheduleSource {
  WORK_SCHEDULE = 'WORK_SCHEDULE',
  SHIFT = 'SHIFT',
  NONE = 'NONE',
}

export type DayDetailUser = {
  id: number;
  firstName: string;
  lastName: string;
  profilePicture: string | null;
};

export type DayDetailWorkSchedule = {
  id: number;
  name: string;
  description: string;
};

export type DayDetailSchedule = {
  source: DayDetailScheduleSource;
  workSchedule: DayDetailWorkSchedule | null;
  shiftAssociations: ShiftAssociations[] | null;
};

export type DayDetailHours = {
  worked: number;
  scheduled: number;
  estimated: number;
  extra: number;
  timeOff: number | null;
};

export type DayDetailCategorizedHour = {
  category: {
    name: string;
    description: string;
  };
  hours: number;
};

export type DayDetailTimeSlot = {
  startTime: string;
  endTime: string;
};

export type DayDetailEntrySite = {
  id: number;
  name: string;
};

export type DayDetailEntry = {
  id: number;
  type: DayDetailEntryType;
  userId: number;
  time: string;
  date: string;
  source: DayDetailEntrySource;
  site: DayDetailEntrySite | null;
  siteName: string | null;
  coordinates: SiteCoordinates | null;
  comment: string | null;
  locationIncidence: boolean;
  isRemoteWork: boolean;
  createdAt: string;
  updatedAt: string;
};

export type DayDetailResponse = {
  id: number;
  date: string;
  dateString: string;
  userId: number;
  user: DayDetailUser;
  weekday: Days;
  isWorkday: boolean;
  nightShift: boolean;
  schedule: DayDetailSchedule;
  hours: DayDetailHours;
  categorizedHours: DayDetailCategorizedHour[];
  timeSlots: DayDetailTimeSlot[];
  entries: DayDetailEntry[];
  holidays: Holiday[];
  timeOffRequests: TimeOffRequest[];
  incidences: Incidence[];
};

export enum TimeTrackingCategorizedHourStatus {
  APPROVED = 'APPROVED',
  AUTO_APPROVED = 'AUTO_APPROVED',
  /** Filter-only. Maps to PENDING hours with at least one reviewed step. */
  IN_PROGRESS = 'IN_PROGRESS',
  PENDING = 'PENDING',
  REJECTED = 'REJECTED',
  CANCELLED = 'CANCELLED',
  CANCELED_BY_MODIFICATION = 'CANCELED_BY_MODIFICATION',
}

export type ApprovableStatus =
  | TimeTrackingCategorizedHourStatus.APPROVED
  | TimeTrackingCategorizedHourStatus.REJECTED;

export type WorkTimeSlot = {
  startTime: string; // Format: "HH:MM"
  endTime: string; // Format: "HH:MM"
};

export type CategorizedHourEntry = {
  id: number;
  time: string; // Format: "2026-02-12T09:00:00.000Z"
  type: EntryType;
};

export enum CategorizedHourApprovalStepState {
  PENDING = 'PENDING',
  WAITING_OTHER_STEP = 'WAITING_OTHER_STEP',
  APPROVED = 'APPROVED',
  REJECTED = 'REJECTED',
}

export type CategorizedHourApprovalStepPotentialApprover = {
  id: number;
  createdAt: string;
  deleted: boolean;
  email: string;
  employeeInternalId: string;
  firstName: string;
  hiringDate: string | null;
  isAgent: boolean;
  lastName: string;
  profilePicture: string | null;
  status: 'ACTIVE' | 'INACTIVE';
};

export type CategorizedHourApprovalStep = {
  id: number | string;
  state: CategorizedHourApprovalStepState;
  position: number;
  approverId: number | null;
  comment: string | null;
  potentialApprovers: CategorizedHourApprovalStepPotentialApprover[];
  approver?: User | null;
};

export type CategorizedHourStatusOverride = {
  admin: CategorizedHourApprovalStepPotentialApprover | null;
  comment: string | null;
};

export type ApprovalRequest = {
  dateString: string;
  employeeInternalId: string;
  entries: CategorizedHourEntry[];
  fullName: string;
  hourCategoryId: number;
  hourCategoryName: string;
  hours: number;
  id: string;
  instanceId: number;
  note: string | null;
  profilePicture: string | null;
  status: TimeTrackingCategorizedHourStatus;
  currentStepId?: number | string | null;
  userId: number;
  workTimeSlots: WorkTimeSlot[];
  approvalSteps?: CategorizedHourApprovalStep[];
  isLoggedUserPotentialApprover?: boolean;
  isStatusOverridden?: boolean;
  statusOverride?: CategorizedHourStatusOverride | null;
};

export type CategorizedHourStatusUpdatedSocket = {
  categorizedHourId: string;
  hourStatus: TimeTrackingCategorizedHourStatus;
  steps: {
    stepId: string;
    status: CategorizedHourApprovalStepState;
    potentialApproverIds: number[];
  }[];
};
