import { Family, Payment, AppSettings, User, AlertDefinition, Condo, Notice, NoticeRead, Ticket, TicketAttachment } from '../types'; // --- CONFIGURATION TOGGLE --- const FORCE_LOCAL_DB = false; const API_URL = '/api'; const STORAGE_KEYS = { TOKEN: 'condo_auth_token', USER: 'condo_user_info', ACTIVE_CONDO_ID: 'condo_active_id', }; const getAuthHeaders = () => { const token = localStorage.getItem(STORAGE_KEYS.TOKEN); return token ? { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } : { 'Content-Type': 'application/json' }; }; const request = async (endpoint: string, options: RequestInit = {}): Promise => { const response = await fetch(`${API_URL}${endpoint}`, { ...options, headers: { ...getAuthHeaders(), ...options.headers, }, }); if (response.status === 401) { CondoService.logout(); throw new Error("Unauthorized"); } if (!response.ok) { const errText = await response.text(); throw new Error(errText || `API Error: ${response.status}`); } return response.json(); }; export const CondoService = { // --- CONDO CONTEXT MANAGEMENT --- getActiveCondoId: (): string | null => { return localStorage.getItem(STORAGE_KEYS.ACTIVE_CONDO_ID); }, setActiveCondo: (condoId: string) => { localStorage.setItem(STORAGE_KEYS.ACTIVE_CONDO_ID, condoId); window.location.reload(); }, getCondos: async (): Promise => { return request('/condos'); }, getActiveCondo: async (): Promise => { const condos = await CondoService.getCondos(); const activeId = CondoService.getActiveCondoId(); if (!activeId && condos.length > 0) { // Do not reload here, just set it silently or let the UI handle it localStorage.setItem(STORAGE_KEYS.ACTIVE_CONDO_ID, condos[0].id); return condos[0]; } return condos.find(c => c.id === activeId); }, saveCondo: async (condo: Condo): Promise => { // If no ID, it's a creation if (!condo.id || condo.id.length < 5) { // Simple check if it's a new ID request return request('/condos', { method: 'POST', body: JSON.stringify(condo) }); } else { return request(`/condos/${condo.id}`, { method: 'PUT', body: JSON.stringify(condo) }); } }, deleteCondo: async (id: string) => { await request(`/condos/${id}`, { method: 'DELETE' }); if (localStorage.getItem(STORAGE_KEYS.ACTIVE_CONDO_ID) === id) { localStorage.removeItem(STORAGE_KEYS.ACTIVE_CONDO_ID); } }, // --- NOTICES (BACHECA) --- getNotices: async (condoId?: string): Promise => { let url = '/notices'; const activeId = condoId || CondoService.getActiveCondoId(); if (activeId) url += `?condoId=${activeId}`; return request(url); }, saveNotice: async (notice: Notice): Promise => { if (!notice.id) { return request('/notices', { method: 'POST', body: JSON.stringify(notice) }); } else { return request(`/notices/${notice.id}`, { method: 'PUT', body: JSON.stringify(notice) }); } }, deleteNotice: async (id: string) => { await request(`/notices/${id}`, { method: 'DELETE' }); }, markNoticeAsRead: async (noticeId: string, userId: string) => { await request(`/notices/${noticeId}/read`, { method: 'POST', body: JSON.stringify({ userId }) }); }, getNoticeReadStatus: async (noticeId: string): Promise => { return request(`/notices/${noticeId}/reads`); }, getUnreadNoticesForUser: async (userId: string, condoId: string): Promise => { return request(`/notices/unread?userId=${userId}&condoId=${condoId}`); }, // --- AUTH --- login: async (email, password) => { const data = await request<{token: string, user: User}>('/auth/login', { method: 'POST', body: JSON.stringify({ email, password }) }); localStorage.setItem(STORAGE_KEYS.TOKEN, data.token); localStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(data.user)); // Set active condo if user belongs to a family if (data.user.familyId) { try { const families = await CondoService.getFamilies(); // This will filter by user perms automatically on server const fam = families.find(f => f.id === data.user.familyId); if (fam) { localStorage.setItem(STORAGE_KEYS.ACTIVE_CONDO_ID, fam.condoId); } } catch (e) { console.error("Could not set active condo on login", e); } } return data; }, logout: () => { localStorage.removeItem(STORAGE_KEYS.TOKEN); localStorage.removeItem(STORAGE_KEYS.USER); window.location.href = '#/login'; }, getCurrentUser: (): User | null => { const u = localStorage.getItem(STORAGE_KEYS.USER); return u ? JSON.parse(u) : null; }, updateProfile: async (data: Partial & { password?: string }) => { return request<{success: true, user: User}>('/profile', { method: 'PUT', body: JSON.stringify(data) }); }, // --- SETTINGS (Global) --- getSettings: async (): Promise => { return request('/settings'); }, updateSettings: async (settings: AppSettings): Promise => { await request('/settings', { method: 'PUT', body: JSON.stringify(settings) }); }, getAvailableYears: async (): Promise => { return request('/years'); }, // --- FAMILIES --- getFamilies: async (condoId?: string): Promise => { let url = '/families'; const activeId = condoId || CondoService.getActiveCondoId(); if (activeId) url += `?condoId=${activeId}`; return request(url); }, addFamily: async (familyData: Omit): Promise => { const activeCondoId = CondoService.getActiveCondoId(); if (!activeCondoId) throw new Error("Nessun condominio selezionato"); return request('/families', { method: 'POST', body: JSON.stringify({ ...familyData, condoId: activeCondoId }) }); }, updateFamily: async (family: Family): Promise => { return request(`/families/${family.id}`, { method: 'PUT', body: JSON.stringify(family) }); }, deleteFamily: async (familyId: string): Promise => { await request(`/families/${familyId}`, { method: 'DELETE' }); }, // --- PAYMENTS --- getPaymentsByFamily: async (familyId: string): Promise => { return request(`/payments?familyId=${familyId}`); }, getCondoPayments: async (condoId: string): Promise => { return request(`/payments?condoId=${condoId}`); }, addPayment: async (payment: Omit): Promise => { return request('/payments', { method: 'POST', body: JSON.stringify(payment) }); }, // --- USERS --- getUsers: async (condoId?: string): Promise => { let url = '/users'; const activeId = condoId || CondoService.getActiveCondoId(); if (activeId) url += `?condoId=${activeId}`; return request(url); }, createUser: async (userData: any) => { return request('/users', { method: 'POST', body: JSON.stringify(userData) }); }, updateUser: async (id: string, userData: any) => { return request(`/users/${id}`, { method: 'PUT', body: JSON.stringify(userData) }); }, deleteUser: async (id: string) => { await request(`/users/${id}`, { method: 'DELETE' }); }, // --- ALERTS --- getAlerts: async (condoId?: string): Promise => { let url = '/alerts'; const activeId = condoId || CondoService.getActiveCondoId(); if (activeId) url += `?condoId=${activeId}`; return request(url); }, saveAlert: async (alert: AlertDefinition & { condoId?: string }): Promise => { const activeCondoId = CondoService.getActiveCondoId(); if (!alert.id) { return request('/alerts', { method: 'POST', body: JSON.stringify({ ...alert, condoId: activeCondoId }) }); } else { return request(`/alerts/${alert.id}`, { method: 'PUT', body: JSON.stringify(alert) }); } }, deleteAlert: async (id: string) => { await request(`/alerts/${id}`, { method: 'DELETE' }); }, // --- TICKETS --- getTickets: async (condoId?: string): Promise => { let url = '/tickets'; const activeId = condoId || CondoService.getActiveCondoId(); if (activeId) url += `?condoId=${activeId}`; return request(url); }, createTicket: async (data: Omit, 'attachments'> & { attachments?: { fileName: string, fileType: string, data: string }[] }) => { const activeId = CondoService.getActiveCondoId(); if(!activeId) throw new Error("No active condo"); return request('/tickets', { method: 'POST', body: JSON.stringify({ ...data, condoId: activeId }) }); }, updateTicket: async (id: string, data: { status: string, priority: string }) => { return request(`/tickets/${id}`, { method: 'PUT', body: JSON.stringify(data) }); }, deleteTicket: async (id: string) => { await request(`/tickets/${id}`, { method: 'DELETE' }); }, getTicketAttachment: async (ticketId: string, attachmentId: string): Promise => { return request(`/tickets/${ticketId}/attachments/${attachmentId}`); }, // --- SEEDING --- seedPayments: () => { // No-op in remote mode } };