// Shared types and constants for eHandyHire

export type UserRole = 'CUSTOMER' | 'WORKER' | 'ADMIN';

export const GENDER_VALUES = ['MALE', 'FEMALE', 'OTHER', 'PREFER_NOT_TO_SAY'] as const;

export type Gender = (typeof GENDER_VALUES)[number];

export const GENDER_LABELS: Record<Gender, string> = {
  MALE: 'Male',
  FEMALE: 'Female',
  OTHER: 'Other',
  PREFER_NOT_TO_SAY: 'Prefer not to say',
};

export const GENDER_OPTIONS = GENDER_VALUES.map((value) => ({
  value,
  label: GENDER_LABELS[value],
}));

export type JobStatus =
  | 'OPEN'
  | 'QUOTED'
  | 'ACCEPTED'
  | 'IN_PROGRESS'
  | 'COMPLETED'
  | 'CANCELLED';

export type QuotationStatus = 'PENDING' | 'ACCEPTED' | 'REJECTED' | 'WITHDRAWN';

export {
  ADMIN_REGION_IDS,
  ADMIN_REGION_LABELS,
  CITY_DEFINITIONS,
  CITY_SERVICE_AREAS,
  DAVAO_REGION_CITIES,
  DEFAULT_REGION_SLUG,
  ISLAND_GROUP_IDS,
  ISLAND_GROUP_LABELS,
  REGION_OPTIONS,
  REGION_SLUGS,
  REGION_WIDE_DEFINITIONS,
  REGION_WIDE_SERVICE_AREAS,
  SERVICE_AREA_COORDINATES,
  SERVICE_AREA_LABELS,
  SERVICE_AREA_VALUES,
  SLUG_TO_SERVICE_AREA,
  WORKER_SELECTABLE_SERVICE_AREAS,
  WORKER_SERVICE_AREA_GROUPS,
  buildRegionOptionGroups,
  buildWorkerServiceAreaGroups,
  cityLabelsForBrowseArea,
  getAdminRegionForCity,
  getIslandGroupForCity,
  isEntireRegion,
  isShowAllBrowseArea,
  parseServiceArea,
  serviceAreaToSlug,
  serviceAreasForFilter,
  type AdminRegionId,
  type IslandGroupId,
  type RegionOptionGroup,
  type ServiceArea,
  type WorkerSelectableServiceArea,
} from './serviceAreas';

export const JOB_STATUS_LABELS: Record<JobStatus, string> = {
  OPEN: 'Open',
  QUOTED: 'Quoted',
  ACCEPTED: 'Accepted',
  IN_PROGRESS: 'In Progress',
  COMPLETED: 'Completed',
  CANCELLED: 'Cancelled',
};

export const QUOTATION_STATUS_LABELS: Record<QuotationStatus, string> = {
  PENDING: 'Pending',
  ACCEPTED: 'Hired',
  REJECTED: 'Declined',
  WITHDRAWN: 'Withdrawn',
};

/** Worker applications on a job (customer view) */
export const APPLICATION_STATUS_LABELS: Record<QuotationStatus, string> = {
  PENDING: 'Pending review',
  ACCEPTED: 'Hired',
  REJECTED: 'Declined',
  WITHDRAWN: 'Withdrawn',
};

export const JOB_PROGRESS_STEPS = [
  { status: 'ACCEPTED' as JobStatus, label: 'Hired' },
  { status: 'IN_PROGRESS' as JobStatus, label: 'In progress' },
  { status: 'COMPLETED' as JobStatus, label: 'Completed' },
] as const;

export function jobProgressStepIndex(status: JobStatus): number {
  if (status === 'COMPLETED') return 2;
  if (status === 'IN_PROGRESS') return 1;
  if (status === 'ACCEPTED') return 0;
  return -1;
}

/** Job statuses where the customer can release the worker and accept new quotes. */
export const CUSTOMER_REOPENABLE_JOB_STATUSES: JobStatus[] = [
  'ACCEPTED',
  'IN_PROGRESS',
  'CANCELLED',
];

export interface ApiResponse<T = unknown> {
  success: boolean;
  data?: T;
  message?: string;
  error?: string;
  meta?: PaginationMeta;
}

export interface PaginationMeta {
  page: number;
  limit: number;
  total: number;
  totalPages: number;
}

export interface AuthTokens {
  accessToken: string;
  refreshToken: string;
}

export interface JwtPayload {
  userId: string;
  role: UserRole;
  email?: string;
}

export const JOB_REACTION_TYPES = ['LIKE', 'LOVE', 'ANGRY'] as const;
export type JobReactionType = (typeof JOB_REACTION_TYPES)[number];

export const EMPTY_JOB_REACTION_COUNTS: Record<JobReactionType, number> = {
  LIKE: 0,
  LOVE: 0,
  ANGRY: 0,
};

export interface JobReactionSummary {
  counts: Record<JobReactionType, number>;
  userReaction: JobReactionType | null;
}

export interface JobReactionUpdatePayload {
  jobId: string;
  userId: string;
  userReaction: JobReactionType | null;
  counts: Record<JobReactionType, number>;
}

export const JOB_FEED_ROOM = 'job-feed';

// Socket.IO event names
export const SOCKET_EVENTS = {
  SEND_MESSAGE: 'send-message',
  RECEIVE_MESSAGE: 'receive-message',
  TYPING: 'typing',
  READ_RECEIPT: 'read-receipt',
  NEW_JOB: 'new-job',
  NEW_QUOTE: 'new-quote',
  JOB_STATUS_UPDATE: 'job-status-update',
  NOTIFICATION: 'notification',
  JOIN_ROOM: 'join-room',
  LEAVE_ROOM: 'leave-room',
  JOIN_JOB_FEED: 'join-job-feed',
  LEAVE_JOB_FEED: 'leave-job-feed',
  SET_JOB_REACTION: 'set-job-reaction',
  JOB_REACTION: 'job-reaction',
} as const;

export const MAX_WORKER_PORTFOLIO_IMAGES = 5;

export {
  computeWorkerRankScore,
  WORKER_RANK_PRIOR_MEAN,
  WORKER_RANK_PRIOR_WEIGHT,
  type WorkerRankInput,
} from './workerRank';

export {
  CATEGORY_SEARCH_ALIASES,
  expandSearchTerms,
  categorySlugsMatchingSearch,
  categorySearchKeywords,
  matchesExpandedSearch,
} from './searchSynonyms';
