import { requestClient } from '#/api/request'; export interface ArchiveStats { conversations: number; exports: number; imports: number; last_message_at: string; media: number; media_failed: number; media_ready: number; messages: number; people: number; } export interface ArchiveConversation { conversation_type: string; external_id: string; id: string; last_content: string; last_message_at: string; message_count: number; name: string; source_account: string; status: string; } export interface ArchiveMessage { attachment_count: number; attachments: ArchiveAttachment[]; content: string; direction: string; id: string; message_type: string; sender_name: string; sender_person_id: null | string; sent_at: string; sequence_no: null | number; source_message_id: string; status: string; } export interface ArchiveAttachment { attachment_index: number; attachment_role: string; checksum?: string; id: string; match_confidence: number; match_method: string; media_type: 'audio' | 'file' | 'image' | 'video'; mime_type: string; original_filename: string; sha256: string; size_bytes: number; status: string; } export interface ArchiveMediaAccess { expires_in: number; id: string; url: string; } export interface ArchiveStorage { bucket: string; custom_domain: string; enabled: boolean; encryption_mode: string; export_prefix: string; media_prefix: string; release_prefix: string; region: string; secret_id_masked: string; secret_id_present: boolean; secret_key_masked: string; secret_key_present: boolean; updated_at: string; } export interface ArchiveMedia { bucket: string; created_at: string; encryption_mode: string; id: string; last_error: string; media_type: string; mime_type: string; object_key: string; original_filename: string; region: string; sha256: string; size_bytes: number; status: string; verified_at: string; version_id: string; } export interface ArchivePerson { conversation_count: number; created_at: string; display_name: string; id: string; identity_count: number; message_count: number; patient_binding_count: number; primary_patient_id: null | number; primary_patient_name: string; real_name: string; updated_at: string; } export interface ArchiveIdentity { created_at: string; external_id: string; id: string; identity_type: string; scope_id: string; source: string; updated_at: string; verified: boolean; } export interface ArchivePersonDetail { display_name: string; id: string; identities: ArchiveIdentity[]; patient_bindings: PatientBinding[]; real_name: string; } export interface PatientBinding { bind_method: string; confidence: number; created_at: string; diagnosis_id: number; id: string; is_primary: boolean; patient_id: number; patient_name: string; phone_masked: string; relation_type: 'family' | 'guardian' | 'other' | 'proxy' | 'self'; status: 'active' | 'revoked'; updated_at: string; } export interface ZytPatientCandidate { age: null | number; diagnosis_id: number; gender: number | string; patient_id: number; patient_name: string; phone_masked: string; source_update_time: string; } export interface ArchiveExportFile { file_name: string; format: string; id: string; sha256: string; size_bytes: number; storage_status: string; } export interface ArchiveExportJob { completed_at: string; created_at: string; cutoff_at: string; error_message: string; files: ArchiveExportFile[]; filters: Record; formats: string[]; id: string; progress: number; started_at: string; status: 'completed' | 'failed' | 'queued' | 'running'; total_rows: number; } function query(values: Record) { const params = new URLSearchParams(); Object.entries(values).forEach(([key, value]) => { if (value !== '') params.set(key, String(value)); }); const text = params.toString(); return text ? `?${text}` : ''; } export function fetchArchiveStats(accountId = 0) { return requestClient.get( `/archive/stats${query({ account_id: accountId })}`, ); } export function fetchArchiveConversations(limit = 50, cursor = '', accountId = 0) { return requestClient.get<{ has_more: boolean; items: ArchiveConversation[]; next_cursor: string; }>(`/archive/conversations${query({ account_id: accountId, cursor, limit })}`); } export function fetchArchiveMessages( conversationId: string, limit = 100, cursor = '', accountId = 0, ) { return requestClient.get<{ has_more: boolean; items: ArchiveMessage[]; next_cursor: string; }>( `/archive/conversations/${encodeURIComponent(conversationId)}/messages${query({ account_id: accountId, cursor, limit })}`, ); } export function fetchArchiveMediaAccessUrls( mediaIds: string[], expires = 900, accountId = 0, ) { return requestClient.post<{ items: ArchiveMediaAccess[] }>( `/archive/media/access-urls${query({ account_id: accountId })}`, { expires, media_ids: mediaIds }, ); } export function fetchArchiveStorage() { return requestClient.get<{ storage: ArchiveStorage }>('/archive/storage'); } export function saveArchiveStorage(data: Partial & { secret_id?: string; secret_key?: string; }) { return requestClient.put<{ storage: ArchiveStorage }>( '/archive/storage', data, ); } export function testArchiveStorage() { return requestClient.post<{ result: { bucket: string; ok: boolean; region: string; request_id: string }; }>('/archive/storage/test'); } export function fetchArchiveMedia(limit = 100, accountId = 0) { return requestClient.get<{ items: ArchiveMedia[] }>( `/archive/media${query({ account_id: accountId, limit })}`, ); } export function fetchArchivePeople(limit = 100, keyword = '', accountId = 0) { return requestClient.get<{ items: ArchivePerson[] }>( `/archive/people${query({ account_id: accountId, keyword, limit })}`, ); } export function fetchArchivePerson(personId: string, accountId = 0) { return requestClient.get<{ person: ArchivePersonDetail }>( `/archive/people/${encodeURIComponent(personId)}${query({ account_id: accountId })}`, ); } export function bindArchiveIdentity( personId: string, data: { external_id: string; identity_type: string; scope_id: string; verified: boolean; }, accountId = 0, ) { return requestClient.post<{ person: ArchivePersonDetail }>( `/archive/people/${encodeURIComponent(personId)}/identities${query({ account_id: accountId })}`, data, ); } export function searchZytPatients( keyword: string, accountId: number, pageNo = 1, pageSize = 20, ) { return requestClient.get<{ items: ZytPatientCandidate[]; page_no: number; page_size: number; total: number; }>( `/archive/patients/search${query({ account_id: accountId, keyword, page_no: pageNo, page_size: pageSize })}`, ); } export function bindArchivePatient( personId: string, data: { diagnosis_id: number; patient_id: number; relation_type: PatientBinding['relation_type']; }, accountId: number, ) { return requestClient.put<{ binding: PatientBinding; person: ArchivePersonDetail; }>( `/archive/people/${encodeURIComponent(personId)}/patient-bindings${query({ account_id: accountId })}`, data, ); } export function unbindArchivePatient( personId: string, bindingId: string, accountId: number, ) { return requestClient.delete<{ person: ArchivePersonDetail }>( `/archive/people/${encodeURIComponent(personId)}/patient-bindings/${encodeURIComponent(bindingId)}${query({ account_id: accountId })}`, ); } export function createArchiveExport(data: { filters: Record; formats: string[]; }, accountId = 0) { return requestClient.post<{ job: ArchiveExportJob }>( `/archive/exports${query({ account_id: accountId })}`, data, ); } export function fetchArchiveExports(limit = 100, accountId = 0) { return requestClient.get<{ jobs: ArchiveExportJob[] }>( `/archive/exports${query({ account_id: accountId, limit })}`, ); } export function downloadArchiveExport(fileId: string, accountId = 0) { return requestClient.download( `/archive/export-files/${encodeURIComponent(fileId)}/download${query({ account_id: accountId })}`, ); }