/* eslint-disable @typescript-eslint/no-explicit-any */ import type { TaskBoard, TaskBoardViewState, TaskBoardGroup, TaskCard, TaskColumn, TaskColumnRow, TaskActivity, TaskAttachment, TaskAutomation, TaskAutomationCatalog, TaskAutomationRun, TaskChecklistItem, TaskComment, TaskCoverType, TaskLabel, TaskLinkedAttendanceRecord, TaskLinkedCalendarEvent, TaskLinkedDocument, TaskLinkedEmployee, TaskLinkedGuest, TaskLinkedGuestVisit, TaskLinkedMessage, TaskLinkedPost, TaskLinkedProcurementRequest, TaskLinkedRequest, TaskExternalLink, User, } from "@/types/api"; import { buildQuery, type RawRequestFn, type RequestFn } from "./utils"; function parseDownloadFilename(response: Response, fallback: string): string { const disposition = response.headers.get("content-disposition") || ""; const encodedMatch = disposition.match(/filename\*=UTF-8''([^;]+)/); const plainMatch = disposition.match(/filename="?([^";]+)"?/); return encodedMatch?.[1] ? decodeURIComponent(encodedMatch[1]) : plainMatch?.[1] || fallback; } export function createTasksApi(request: RequestFn, requestRaw: RawRequestFn) { return { getTaskBoards: (params?: Record) => request(`/api/v1/tasks/boards/${buildQuery(params)}`), getTaskBoard: (id: number): Promise => request(`/api/v1/tasks/boards/${id}/`), getTaskBoardParticipantCandidates: (id: number): Promise => request(`/api/v1/tasks/boards/${id}/participant-candidates/`), createTaskBoard: (data: Record): Promise => request("/api/v1/tasks/boards/", { method: "POST", body: JSON.stringify(data), }), updateTaskBoard: (id: number, data: Record): Promise => request(`/api/v1/tasks/boards/${id}/`, { method: "PATCH", body: JSON.stringify(data), }), uploadTaskBoardAvatar: (id: number, file: File): Promise => { const formData = new FormData(); formData.append("avatar", file); return request(`/api/v1/tasks/boards/${id}/`, { method: "PATCH", body: formData, }); }, deleteTaskBoard: (id: number): Promise => request(`/api/v1/tasks/boards/${id}/`, { method: "DELETE" }), moveTaskBoardToGroup: ( id: number, group: number | null, ): Promise<{ board: number; group_ids: number[]; group_id: number | null }> => request(`/api/v1/tasks/boards/${id}/move-to-group/`, { method: "POST", body: JSON.stringify({ group }), }), setTaskBoardGroups: ( id: number, groups: number[], ): Promise<{ board: number; group_ids: number[]; group_id: number | null }> => request(`/api/v1/tasks/boards/${id}/groups/`, { method: "POST", body: JSON.stringify({ groups }), }), toggleTaskBoardPin: (id: number): Promise<{ ok: boolean; is_pinned: boolean }> => request(`/api/v1/tasks/boards/${id}/pin/`, { method: "POST" }), toggleTaskBoardNotifications: ( id: number, ): Promise<{ ok: boolean; notifications_enabled: boolean }> => request(`/api/v1/tasks/boards/${id}/notifications/`, { method: "POST" }), updateTaskBoardViewState: ( id: number, data: { scope: "column" | "base" | "row"; object_id: number; collapsed: boolean; }, ): Promise => request(`/api/v1/tasks/boards/${id}/view-state/`, { method: "PATCH", body: JSON.stringify(data), }), getTaskBoardGroups: (): Promise< TaskBoardGroup[] | { results: TaskBoardGroup[] } > => request("/api/v1/tasks/board-groups/"), createTaskBoardGroup: (data: { name: string; is_shared?: boolean }): Promise => request("/api/v1/tasks/board-groups/", { method: "POST", body: JSON.stringify(data), }), updateTaskBoardGroup: ( id: number, data: { name: string; is_shared?: boolean }, ): Promise => request(`/api/v1/tasks/board-groups/${id}/`, { method: "PATCH", body: JSON.stringify(data), }), deleteTaskBoardGroup: (id: number): Promise => request(`/api/v1/tasks/board-groups/${id}/`, { method: "DELETE" }), toggleDefaultTaskBoardGroup: ( id: number, ): Promise<{ group: TaskBoardGroup; is_default_for_current_user: boolean; }> => request(`/api/v1/tasks/board-groups/${id}/set-default/`, { method: "POST", }), toggleTaskBoardGroupHidden: ( id: number, ): Promise<{ group: TaskBoardGroup; is_hidden: boolean }> => request(`/api/v1/tasks/board-groups/${id}/toggle-hidden/`, { method: "POST", }), markTaskBoardNotificationsRead: ( id: number, ): Promise<{ status: string; count: number; notification_ids: number[] }> => request(`/api/v1/tasks/boards/${id}/notifications/read/`, { method: "POST", }), getTaskAutomationCatalog: (): Promise => request("/api/v1/tasks/automations/catalog/"), getTaskAutomations: ( params?: Record, ): Promise => request(`/api/v1/tasks/automations/${buildQuery(params)}`), createTaskAutomation: ( data: Omit, ): Promise => request("/api/v1/tasks/automations/", { method: "POST", body: JSON.stringify(data), }), updateTaskAutomation: ( id: number, data: Partial, ): Promise => request(`/api/v1/tasks/automations/${id}/`, { method: "PATCH", body: JSON.stringify(data), }), deleteTaskAutomation: (id: number): Promise => request(`/api/v1/tasks/automations/${id}/`, { method: "DELETE" }), getTaskAutomationButtons: (taskId: number): Promise => request(`/api/v1/tasks/automations/buttons/?task=${taskId}`), runTaskAutomation: ( automationId: number, taskId: number, ): Promise => request(`/api/v1/tasks/automations/${automationId}/run/`, { method: "POST", body: JSON.stringify({ task: taskId }), }), createTaskColumn: (data: Record): Promise => request("/api/v1/tasks/columns/", { method: "POST", body: JSON.stringify(data), }), updateTaskColumn: ( id: number, data: Record, ): Promise => request(`/api/v1/tasks/columns/${id}/`, { method: "PATCH", body: JSON.stringify(data), }), deleteTaskColumn: (id: number): Promise => request(`/api/v1/tasks/columns/${id}/`, { method: "DELETE" }), reorderTaskColumns: ( board: number, columnIds: number[], parent: number | null = null, ): Promise<{ board: number; parent: number | null; column_ids: number[] }> => request("/api/v1/tasks/columns/reorder/", { method: "POST", body: JSON.stringify({ board, parent, column_ids: columnIds }), }), createTaskColumnRow: (data: Record): Promise => request("/api/v1/tasks/column-rows/", { method: "POST", body: JSON.stringify(data), }), updateTaskColumnRow: ( id: number, data: Record, ): Promise => request(`/api/v1/tasks/column-rows/${id}/`, { method: "PATCH", body: JSON.stringify(data), }), deleteTaskColumnRow: (id: number): Promise => request(`/api/v1/tasks/column-rows/${id}/`, { method: "DELETE" }), createTaskLabel: (data: Record): Promise => request("/api/v1/tasks/labels/", { method: "POST", body: JSON.stringify(data), }), getTaskLabels: (): Promise => request("/api/v1/tasks/labels/"), createTask: (data: Record): Promise => request("/api/v1/tasks/", { method: "POST", body: JSON.stringify(data), }), updateTask: (id: number, data: Record): Promise => request(`/api/v1/tasks/${id}/`, { method: "PATCH", body: JSON.stringify(data), }), moveTask: ( id: number, data: { column: number; row?: number | null; position?: number }, ): Promise => request(`/api/v1/tasks/${id}/move/`, { method: "POST", body: JSON.stringify(data), }), completeTask: (id: number): Promise => request(`/api/v1/tasks/${id}/complete/`, { method: "POST", }), claimTask: (id: number): Promise => request(`/api/v1/tasks/${id}/claim/`, { method: "POST", }), getTaskActivity: (id: number): Promise => request(`/api/v1/tasks/${id}/activity/`), getTaskAttachments: (id: number): Promise => request(`/api/v1/tasks/${id}/attachments/`), uploadTaskAttachments: (id: number, files: File[]): Promise => { const formData = new FormData(); files.forEach((file) => formData.append("files", file)); return request(`/api/v1/tasks/${id}/attachments/`, { method: "POST", body: formData, }); }, downloadTaskAttachment: async ( taskId: number, attachment: Pick, ): Promise<{ blob: Blob; filename: string }> => { const response = await requestRaw( attachment.download_url || `/api/v1/tasks/${taskId}/attachments/${attachment.id}/download/`, ); return { blob: await response.blob(), filename: parseDownloadFilename(response, attachment.file_name), }; }, downloadTaskAttachmentThumbnail: async ( taskId: number, attachment: Pick, ): Promise => { const response = await requestRaw( attachment.thumbnail_url || `/api/v1/tasks/${taskId}/attachments/${attachment.id}/thumbnail/`, ); return response.blob(); }, deleteTaskAttachment: (taskId: number, attachmentId: number): Promise => request(`/api/v1/tasks/${taskId}/attachments/${attachmentId}/`, { method: "DELETE", }), setTaskCover: ( taskId: number, data: { kind: TaskCoverType; source_id?: number }, ): Promise => request(`/api/v1/tasks/${taskId}/cover/`, { method: "POST", body: JSON.stringify(data), }), clearTaskCover: (taskId: number): Promise => request(`/api/v1/tasks/${taskId}/cover/`, { method: "DELETE", }), getTaskChecklist: (id: number): Promise => request(`/api/v1/tasks/${id}/checklist/`), addTaskChecklistItem: ( id: number, data: { title: string; position?: number; is_completed?: boolean }, ): Promise => request(`/api/v1/tasks/${id}/checklist/`, { method: "POST", body: JSON.stringify(data), }), updateTaskChecklistItem: ( id: number, itemId: number, data: { title?: string; position?: number; is_completed?: boolean }, ): Promise => request(`/api/v1/tasks/${id}/checklist/${itemId}/`, { method: "PATCH", body: JSON.stringify(data), }), deleteTaskChecklistItem: (id: number, itemId: number): Promise => request(`/api/v1/tasks/${id}/checklist/${itemId}/`, { method: "DELETE", }), getTaskComments: (id: number): Promise => request(`/api/v1/tasks/${id}/comments/`), addTaskComment: ( id: number, text: string, files: File[] = [], ): Promise => { const formData = new FormData(); formData.append("text", text); files.forEach((file) => formData.append("files", file)); return request(`/api/v1/tasks/${id}/comments/`, { method: "POST", body: formData, }); }, updateTaskComment: (id: number, commentId: number, text: string): Promise => request(`/api/v1/tasks/${id}/comments/${commentId}/`, { method: "PATCH", body: JSON.stringify({ text }), }), deleteTaskComment: (id: number, commentId: number): Promise => request(`/api/v1/tasks/${id}/comments/${commentId}/`, { method: "DELETE", }), getPostLinkedTasks: (postId: number): Promise => request(`/api/v1/tasks/linked-post-tasks/?post_id=${postId}`), getCalendarEventLinkedTasks: (eventId: number): Promise => request(`/api/v1/tasks/linked-event-tasks/?event_id=${eventId}`), getDocumentLinkedTasks: (documentId: number): Promise => request(`/api/v1/tasks/linked-document-tasks/?document_id=${documentId}`), getRequestLinkedTasks: (requestId: number): Promise => request(`/api/v1/tasks/linked-request-tasks/?request_id=${requestId}`), getProcurementRequestLinkedTasks: (requestId: number): Promise => request(`/api/v1/tasks/linked-procurement-request-tasks/?procurement_request_id=${requestId}`), getEmployeeLinkedTasks: (employeeId: number): Promise => request(`/api/v1/tasks/linked-employee-tasks/?employee_id=${employeeId}`), getGuestLinkedTasks: (guestId: number): Promise => request(`/api/v1/tasks/linked-guest-tasks/?guest_id=${guestId}`), getGuestVisitLinkedTasks: (guestVisitId: number): Promise => request(`/api/v1/tasks/linked-guest-visit-tasks/?guest_visit_id=${guestVisitId}`), getAttendanceRecordLinkedTasks: (attendanceRecordId: number): Promise => request(`/api/v1/tasks/linked-attendance-record-tasks/?attendance_record_id=${attendanceRecordId}`), getTaskLinkedPosts: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-posts/`), linkTaskPost: (id: number, postId: number): Promise => request(`/api/v1/tasks/${id}/linked-posts/`, { method: "POST", body: JSON.stringify({ post_id: postId }), }), unlinkTaskPost: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-posts/${linkId}/`, { method: "DELETE", }), getTaskLinkedMessages: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-messages/`), linkTaskMessage: (id: number, messageId: number): Promise => request(`/api/v1/tasks/${id}/linked-messages/`, { method: "POST", body: JSON.stringify({ message_id: messageId }), }), unlinkTaskMessage: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-messages/${linkId}/`, { method: "DELETE", }), getTaskLinkedDocuments: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-documents/`), linkTaskDocument: (id: number, documentId: number): Promise => request(`/api/v1/tasks/${id}/linked-documents/`, { method: "POST", body: JSON.stringify({ document_id: documentId }), }), unlinkTaskDocument: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-documents/${linkId}/`, { method: "DELETE", }), getTaskLinkedRequests: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-requests/`), linkTaskRequest: (id: number, requestId: number): Promise => request(`/api/v1/tasks/${id}/linked-requests/`, { method: "POST", body: JSON.stringify({ request_id: requestId }), }), unlinkTaskRequest: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-requests/${linkId}/`, { method: "DELETE", }), getTaskLinkedProcurementRequests: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-procurement-requests/`), linkTaskProcurementRequest: (id: number, requestId: number): Promise => request(`/api/v1/tasks/${id}/linked-procurement-requests/`, { method: "POST", body: JSON.stringify({ procurement_request_id: requestId }), }), unlinkTaskProcurementRequest: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-procurement-requests/${linkId}/`, { method: "DELETE", }), getTaskLinkedEmployees: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-employees/`), linkTaskEmployee: (id: number, employeeId: number): Promise => request(`/api/v1/tasks/${id}/linked-employees/`, { method: "POST", body: JSON.stringify({ employee_id: employeeId }), }), unlinkTaskEmployee: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-employees/${linkId}/`, { method: "DELETE", }), getTaskLinkedGuests: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-guests/`), linkTaskGuest: (id: number, guestId: number): Promise => request(`/api/v1/tasks/${id}/linked-guests/`, { method: "POST", body: JSON.stringify({ guest_id: guestId }), }), unlinkTaskGuest: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-guests/${linkId}/`, { method: "DELETE", }), getTaskLinkedGuestVisits: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-guest-visits/`), linkTaskGuestVisit: (id: number, guestVisitId: number): Promise => request(`/api/v1/tasks/${id}/linked-guest-visits/`, { method: "POST", body: JSON.stringify({ guest_visit_id: guestVisitId }), }), unlinkTaskGuestVisit: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-guest-visits/${linkId}/`, { method: "DELETE", }), getTaskLinkedAttendanceRecords: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-attendance-records/`), linkTaskAttendanceRecord: (id: number, attendanceRecordId: number): Promise => request(`/api/v1/tasks/${id}/linked-attendance-records/`, { method: "POST", body: JSON.stringify({ attendance_record_id: attendanceRecordId }), }), unlinkTaskAttendanceRecord: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-attendance-records/${linkId}/`, { method: "DELETE", }), getTaskLinkedEvents: (id: number): Promise => request(`/api/v1/tasks/${id}/linked-events/`), linkTaskCalendarEvent: (id: number, eventId: number): Promise => request(`/api/v1/tasks/${id}/linked-events/`, { method: "POST", body: JSON.stringify({ event_id: eventId }), }), unlinkTaskCalendarEvent: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/linked-events/${linkId}/`, { method: "DELETE", }), getTaskExternalLinks: (id: number): Promise => request(`/api/v1/tasks/${id}/external-links/`), addTaskExternalLink: ( id: number, data: { url: string; title?: string }, ): Promise => request(`/api/v1/tasks/${id}/external-links/`, { method: "POST", body: JSON.stringify(data), }), deleteTaskExternalLink: (id: number, linkId: number): Promise => request(`/api/v1/tasks/${id}/external-links/${linkId}/`, { method: "DELETE", }), deleteTask: (id: number): Promise => request(`/api/v1/tasks/${id}/`, { method: "DELETE" }), }; }