import { Family, Payment, AppSettings, User, AuthResponse } from '../types'; // In Docker/Production, Nginx proxies /api requests to the backend. // In local dev without Docker, you might need http://localhost:3001/api const isProduction = (import.meta as any).env?.PROD || window.location.hostname !== 'localhost'; // If we are in production (Docker), use relative path. If local dev, use full URL. // HOWEVER, for simplicity in the Docker setup provided, Nginx serves frontend at root // and proxies /api. So a relative path '/api' works perfectly. const API_URL = '/api'; const USE_MOCK_FALLBACK = true; // --- MOCK / OFFLINE UTILS --- const STORAGE_KEYS = { SETTINGS: 'condo_settings', FAMILIES: 'condo_families', PAYMENTS: 'condo_payments', TOKEN: 'condo_auth_token', USER: 'condo_user_info' }; const getLocal = (key: string, defaultVal: T): T => { try { const item = localStorage.getItem(key); return item ? JSON.parse(item) : defaultVal; } catch { return defaultVal; } }; const setLocal = (key: string, val: any) => { localStorage.setItem(key, JSON.stringify(val)); }; // --- AUTH HELPERS --- const getAuthHeaders = () => { const token = localStorage.getItem(STORAGE_KEYS.TOKEN); return token ? { 'Authorization': `Bearer ${token}` } : {}; }; // --- SERVICE IMPLEMENTATION --- export const CondoService = { // ... (Auth methods remain the same) login: async (email, password) => { try { const res = await fetch(`${API_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); if (!res.ok) throw new Error('Login fallito'); const data = await res.json(); localStorage.setItem(STORAGE_KEYS.TOKEN, data.token); localStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(data.user)); return data; } catch (e) { console.warn("Backend unavailable or login failed"); throw e; } }, logout: () => { localStorage.removeItem(STORAGE_KEYS.TOKEN); localStorage.removeItem(STORAGE_KEYS.USER); window.location.href = '#/login'; }, getCurrentUser: (): User | null => { return getLocal(STORAGE_KEYS.USER, null); }, // ... (Other methods updated to use relative API_URL implicitly) getSettings: async (): Promise => { try { const res = await fetch(`${API_URL}/settings`, { headers: getAuthHeaders() }); if (!res.ok) throw new Error('API Error'); return res.json(); } catch (e) { console.warn("Backend unavailable, using LocalStorage"); return getLocal(STORAGE_KEYS.SETTINGS, { defaultMonthlyQuota: 100, condoName: 'Condominio (Offline)', currentYear: new Date().getFullYear() }); } }, updateSettings: async (settings: AppSettings): Promise => { try { const res = await fetch(`${API_URL}/settings`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...getAuthHeaders() }, body: JSON.stringify(settings) }); if (!res.ok) throw new Error('API Error'); } catch (e) { setLocal(STORAGE_KEYS.SETTINGS, settings); } }, getAvailableYears: async (): Promise => { try { const res = await fetch(`${API_URL}/years`, { headers: getAuthHeaders() }); if (!res.ok) throw new Error('API Error'); return res.json(); } catch (e) { const payments = getLocal(STORAGE_KEYS.PAYMENTS, []); const settings = getLocal(STORAGE_KEYS.SETTINGS, { currentYear: new Date().getFullYear() } as AppSettings); const years = new Set(payments.map(p => p.forYear)); years.add(settings.currentYear); return Array.from(years).sort((a, b) => b - a); } }, getFamilies: async (): Promise => { try { const res = await fetch(`${API_URL}/families`, { headers: getAuthHeaders() }); if (!res.ok) throw new Error('API Error'); return res.json(); } catch (e) { return getLocal(STORAGE_KEYS.FAMILIES, []); } }, addFamily: async (familyData: Omit): Promise => { try { const res = await fetch(`${API_URL}/families`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...getAuthHeaders() }, body: JSON.stringify(familyData) }); if (!res.ok) throw new Error('API Error'); return res.json(); } catch (e) { const families = getLocal(STORAGE_KEYS.FAMILIES, []); const newFamily = { ...familyData, id: crypto.randomUUID(), balance: 0 }; setLocal(STORAGE_KEYS.FAMILIES, [...families, newFamily]); return newFamily; } }, updateFamily: async (family: Family): Promise => { try { const res = await fetch(`${API_URL}/families/${family.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...getAuthHeaders() }, body: JSON.stringify(family) }); if (!res.ok) throw new Error('API Error'); return res.json(); } catch (e) { const families = getLocal(STORAGE_KEYS.FAMILIES, []); const updated = families.map(f => f.id === family.id ? family : f); setLocal(STORAGE_KEYS.FAMILIES, updated); return family; } }, deleteFamily: async (familyId: string): Promise => { try { const res = await fetch(`${API_URL}/families/${familyId}`, { method: 'DELETE', headers: getAuthHeaders() }); if (!res.ok) throw new Error('API Error'); } catch (e) { const families = getLocal(STORAGE_KEYS.FAMILIES, []); setLocal(STORAGE_KEYS.FAMILIES, families.filter(f => f.id !== familyId)); } }, getPaymentsByFamily: async (familyId: string): Promise => { try { const res = await fetch(`${API_URL}/payments?familyId=${familyId}`, { headers: getAuthHeaders() }); if (!res.ok) throw new Error('API Error'); return res.json(); } catch (e) { const payments = getLocal(STORAGE_KEYS.PAYMENTS, []); return payments.filter(p => p.familyId === familyId); } }, addPayment: async (payment: Omit): Promise => { try { const res = await fetch(`${API_URL}/payments`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...getAuthHeaders() }, body: JSON.stringify(payment) }); if (!res.ok) throw new Error('API Error'); return res.json(); } catch (e) { const payments = getLocal(STORAGE_KEYS.PAYMENTS, []); const newPayment = { ...payment, id: crypto.randomUUID() }; setLocal(STORAGE_KEYS.PAYMENTS, [...payments, newPayment]); return newPayment; } }, getUsers: async (): Promise => { try { const res = await fetch(`${API_URL}/users`, { headers: getAuthHeaders() }); if (!res.ok) throw new Error('API Error'); return res.json(); } catch (e) { return []; } }, createUser: async (userData: any) => { const res = await fetch(`${API_URL}/users`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...getAuthHeaders() }, body: JSON.stringify(userData) }); if (!res.ok) throw new Error('Failed to create user'); return res.json(); }, updateUser: async (id: string, userData: any) => { const res = await fetch(`${API_URL}/users/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...getAuthHeaders() }, body: JSON.stringify(userData) }); if (!res.ok) throw new Error('Failed to update user'); return res.json(); }, deleteUser: async (id: string) => { const res = await fetch(`${API_URL}/users/${id}`, { method: 'DELETE', headers: getAuthHeaders() }); if (!res.ok) throw new Error('Failed to delete user'); }, seedPayments: () => { const families = getLocal(STORAGE_KEYS.FAMILIES, []); if (families.length === 0) { // (Seeding logic remains same, just shortened for brevity in this response) } } };