import { BookProject, Chapter, Entity, Idea, WorkflowData, UserProfile } from '../types'; // --- CONFIGURATION --- const AUTH_API_ROOT = 'https://app.nocodebackend.com/api/user-auth'; const DATA_API_ROOT = 'https://app.nocodebackend.com/api/data'; const INSTANCE_ID = '54770_plumeia_db'; // --- HELPERS --- const getHeaders = () => { const token = localStorage.getItem('ncb_session_token'); const headers: Record = { 'Content-Type': 'application/json', 'X-Database-Instance': INSTANCE_ID }; if (token) { headers['Authorization'] = `Bearer ${token}`; } return headers; }; const handleAuthResponse = async (res: Response) => { const data = await res.json(); console.log("[API] Auth Response:", data); if (!res.ok) { throw new Error(data.message || 'Authentication failed'); } // Token extraction strategy based on NCB patterns const token = data.user?.token || data.token || data.session?.token || data.auth_token || data.accessToken || data._token; if (token) { console.log("[API] Token extracted and saved:", token); localStorage.setItem('ncb_session_token', token); } else { console.warn("[API] No token found in successful auth response!"); } return data; }; // --- AUTH SERVICE --- export const authService = { async getSession() { const token = localStorage.getItem('ncb_session_token'); if (!token) return null; try { const res = await fetch(`${AUTH_API_ROOT}/get-session?Instance=${INSTANCE_ID}`, { method: 'GET', headers: getHeaders() }); if (!res.ok) { if (res.status === 401) { localStorage.removeItem('ncb_session_token'); } return null; } const data = await res.json(); return data.user || data; } catch (err) { console.error("[Auth] getSession error:", err); return null; } }, async signIn(email: string, password: string) { try { // Force X-Database-Instance header as URL param is insufficient for some NCB versions const res = await fetch(`${AUTH_API_ROOT}/sign-in/email?Instance=${INSTANCE_ID}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Database-Instance': INSTANCE_ID }, body: JSON.stringify({ email, password }) }); return await handleAuthResponse(res); } catch (err: any) { console.error("[Auth] signIn error:", err); return { error: err.message || 'Connection failed' }; } }, async signUp(email: string, password: string, name: string) { try { const res = await fetch(`${AUTH_API_ROOT}/sign-up/email?Instance=${INSTANCE_ID}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Database-Instance': INSTANCE_ID }, body: JSON.stringify({ email, password, name }) }); return await handleAuthResponse(res); } catch (err: any) { return { error: err.message || 'Registration failed' }; } }, async signOut() { try { await fetch(`${AUTH_API_ROOT}/sign-out?Instance=${INSTANCE_ID}`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); } catch (err) { console.error("[Auth] signOut error:", err); } finally { localStorage.removeItem('ncb_session_token'); } } }; // --- DATA SERVICE --- export const dataService = { // -- PROFILES -- async getProfile(userId: string) { try { const encodedId = encodeURIComponent(userId); const url = `${DATA_API_ROOT}/read/profiles?Instance=${INSTANCE_ID}&user_id=${encodedId}`; const res = await fetch(url, { headers: getHeaders() }); const json = await res.json(); return json.data?.[0] || null; } catch (err) { console.error("[Data] getProfile error:", err); return null; } }, async createProfile(profileData: any) { return this.createItem('profiles', profileData); }, // -- PROJECTS -- async getProjects(userId: string) { try { const encodedId = encodeURIComponent(userId); const url = `${DATA_API_ROOT}/read/projects?Instance=${INSTANCE_ID}&user_id=${encodedId}`; const res = await fetch(url, { headers: getHeaders() }); const json = await res.json(); return json.data || []; } catch (err) { console.error("[Data] getProjects error:", err); return []; } }, async createProject(projectData: Partial & { user_id: string }) { // Map Frontend types to Database Columns explicitly if needed, but names match mostly // DB: title, author, genre, sub_genre, target_audience, tone, pov, tense, synopsis, themes, style_guide return this.createItem('projects', projectData); }, // -- GENERIC CRUD -- async getRelatedData(table: string, projectId: number) { try { const url = `${DATA_API_ROOT}/read/${table}?Instance=${INSTANCE_ID}&project_id=${projectId}`; const res = await fetch(url, { headers: getHeaders() }); const json = await res.json(); return json.data || []; } catch (err) { console.error(`[Data] getRelatedData ${table} error:`, err); return []; } }, async createItem(table: string, data: any) { try { console.log(`[Data] Creating item in ${table}...`, data); const url = `${DATA_API_ROOT}/create/${table}?Instance=${INSTANCE_ID}`; const res = await fetch(url, { method: 'POST', headers: getHeaders(), body: JSON.stringify(data), credentials: 'include' }); const result = await res.json(); if (!res.ok) { console.error(`[Data] Create ${table} failed:`, result); return { status: 'error', message: result.message || 'Creation failed' }; } return { status: 'success', ...result }; } catch (err) { console.error(`[Data] Create ${table} network error:`, err); return { status: 'error', message: err }; } }, async updateItem(table: string, id: number, data: any) { try { const url = `${DATA_API_ROOT}/update/${table}/${id}?Instance=${INSTANCE_ID}`; await fetch(url, { method: 'PUT', headers: getHeaders(), body: JSON.stringify(data) }); } catch (err) { console.error(`[Data] Update ${table} error:`, err); } }, async deleteItem(table: string, id: number) { try { const url = `${DATA_API_ROOT}/delete/${table}/${id}?Instance=${INSTANCE_ID}`; await fetch(url, { method: 'DELETE', headers: getHeaders() }); } catch (err) { console.error(`[Data] Delete ${table} error:`, err); } } };