import { useState, useEffect, useCallback } from 'react' import { databases, DATABASE_ID, COLLECTIONS, Query, ID } from '../lib/appwrite' const DEMO_MODE = !import.meta.env.VITE_APPWRITE_PROJECT_ID // Demo data für Testing - Vollständiges Dummy-Ticket 10001 mit allen Worksheets const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000) const twoDaysAgo = new Date(Date.now() - 48 * 60 * 60 * 1000) const threeDaysAgo = new Date(Date.now() - 72 * 60 * 60 * 1000) const DEMO_WORKSHEETS = [ { $id: 'ws-10001-001', wsid: '100001', woid: '10001', workorderId: 'dummy-10001', employeeId: 'user-max-id', employeeName: 'Max Mustermann', employeeShort: 'MM', serviceType: 'Remote', oldStatus: 'Open', newStatus: 'Occupied', oldResponseLevel: '', newResponseLevel: '24/7', totalTime: 30, startDate: '23.12.2025', startTime: '0800', endDate: '23.12.2025', endTime: '0830', details: 'Erste Analyse durchgeführt. Server komplett offline. Keine Remote-Verbindung möglich. Vor-Ort-Einsatz erforderlich.', isComment: false, $createdAt: threeDaysAgo.toISOString() }, { $id: 'ws-10001-002', wsid: '100002', woid: '10001', workorderId: 'dummy-10001', employeeId: 'user-lisa-id', employeeName: 'Lisa Schneider', employeeShort: 'LS', serviceType: 'On Site', oldStatus: 'Occupied', newStatus: 'Assigned', oldResponseLevel: '24/7', newResponseLevel: '24/7', totalTime: 120, startDate: '23.12.2025', startTime: '1000', endDate: '23.12.2025', endTime: '1200', details: 'Vor-Ort-Einsatz: Hardware-Check durchgeführt. Netzteil des Hauptservers defekt. Ersatzteil bestellt. Notfall-Backup-Server gestartet.', isComment: false, $createdAt: threeDaysAgo.toISOString() }, { $id: 'ws-10001-003', wsid: '100003', woid: '10001', workorderId: 'dummy-10001', employeeId: 'user-tom-id', employeeName: 'Tom Klein', employeeShort: 'TK', serviceType: 'On Site', oldStatus: 'Assigned', newStatus: 'Assigned', oldResponseLevel: '24/7', newResponseLevel: '24/7', totalTime: 0, startDate: '24.12.2025', startTime: '1400', endDate: '24.12.2025', endTime: '1400', details: 'Warte auf Ersatzteil-Lieferung. Kunde informiert. Backup-System läuft stabil.', isComment: true, $createdAt: twoDaysAgo.toISOString() }, { $id: 'ws-10001-004', wsid: '100004', woid: '10001', workorderId: 'dummy-10001', employeeId: 'user-max-id', employeeName: 'Max Mustermann', employeeShort: 'MM', serviceType: 'On Site', oldStatus: 'Assigned', newStatus: 'In Test', oldResponseLevel: '24/7', newResponseLevel: '24/7', totalTime: 180, startDate: '25.12.2025', startTime: '0900', endDate: '25.12.2025', endTime: '1200', details: 'Ersatzteil eingebaut. Server gestartet. Alle Dienste wiederhergestellt. System-Tests durchgeführt. Datenbank-Verbindungen geprüft.', isComment: false, $createdAt: twoDaysAgo.toISOString() }, { $id: 'ws-10001-005', wsid: '100005', woid: '10001', workorderId: 'dummy-10001', employeeId: 'user-lisa-id', employeeName: 'Lisa Schneider', employeeShort: 'LS', serviceType: 'Remote', oldStatus: 'In Test', newStatus: 'Awaiting', oldResponseLevel: '24/7', newResponseLevel: 'Support', totalTime: 45, startDate: '26.12.2025', startTime: '1000', endDate: '26.12.2025', endTime: '1045', details: 'Remote-Monitoring eingerichtet. Warte auf Kunden-Feedback nach 24h Testphase. Alle Systeme laufen stabil.', isComment: false, $createdAt: yesterday.toISOString() }, { $id: 'ws-10001-006', wsid: '100006', woid: '10001', workorderId: 'dummy-10001', employeeId: 'user-tom-id', employeeName: 'Tom Klein', employeeShort: 'TK', serviceType: 'COMMENT', oldStatus: 'Awaiting', newStatus: 'Closed', oldResponseLevel: 'Support', newResponseLevel: 'Backoffice', totalTime: 0, startDate: '30.12.2025', startTime: '0900', endDate: '30.12.2025', endTime: '0900', details: 'Kunde bestätigt: Alle Systeme funktionieren einwandfrei. Problem vollständig behoben. Ticket kann geschlossen werden.', isComment: true, $createdAt: new Date().toISOString() } ] export function useWorksheets(woid = null) { const [worksheets, setWorksheets] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const fetchWorksheets = useCallback(async () => { setLoading(true) if (DEMO_MODE) { // Filter demo data by WOID if provided const filtered = woid ? DEMO_WORKSHEETS.filter(ws => ws.woid === woid) : DEMO_WORKSHEETS setWorksheets(filtered) setLoading(false) return } try { const queries = [Query.orderDesc('$createdAt')] // Filter by WOID if provided if (woid) { queries.push(Query.equal('woid', woid)) } if (import.meta.env.DEV) { console.log('📋 Fetching worksheets:') console.log(' Database ID:', DATABASE_ID) console.log(' Collection ID:', COLLECTIONS.WORKSHEETS) console.log(' WOID Filter:', woid || 'none') } const response = await databases.listDocuments( DATABASE_ID, COLLECTIONS.WORKSHEETS, queries ) setWorksheets(response.documents) setError(null) } catch (err) { let errorMessage = err.message || 'Fehler beim Laden der Worksheets' if (err.code === 401 || errorMessage.includes('not authorized')) { errorMessage = 'Berechtigung fehlt: Bitte überprüfe die Read-Berechtigungen der Worksheets Collection.' } else if (errorMessage.includes('Collection') && errorMessage.includes('not found')) { errorMessage = 'Worksheets Collection nicht gefunden. Bitte erstelle die Collection in Appwrite (siehe WORKSHEETS_COLLECTION_SETUP.md).' } setError(errorMessage) console.error('Error fetching worksheets:', err) } finally { setLoading(false) } }, [woid]) useEffect(() => { fetchWorksheets() }, [fetchWorksheets]) /** * Generiert eine eindeutige 6-stellige WSID * Startet bei 100000 und zählt sequentiell hoch */ const generateWSID = useCallback(async () => { if (DEMO_MODE) { const maxWsid = worksheets.length > 0 ? Math.max(...worksheets.map(ws => parseInt(ws.wsid)).filter(w => !isNaN(w))) : 99999 return (maxWsid + 1).toString() } try { // Hole ALLE Worksheets (nicht gefiltert) um höchste WSID zu finden const response = await databases.listDocuments( DATABASE_ID, COLLECTIONS.WORKSHEETS, [Query.orderDesc('wsid'), Query.limit(1)] ) if (response.documents.length === 0) { return '100000' // Erste WSID } const highestWsid = parseInt(response.documents[0].wsid) if (isNaN(highestWsid)) { console.warn('Ungültige WSID gefunden, starte bei 100000') return '100000' } return (highestWsid + 1).toString() } catch (err) { console.error('Error generating WSID:', err) // Fallback: Verwende lokale Worksheets const maxWsid = worksheets.length > 0 ? Math.max(...worksheets.map(ws => parseInt(ws.wsid)).filter(w => !isNaN(w))) : 99999 return (maxWsid + 1).toString() } }, [worksheets]) /** * Berechnet Arbeitszeit aus Start- und Endzeit * Format: "1000" = 10:00, "1430" = 14:30 * @returns Minuten oder null wenn ungültig */ const calculateTime = (startTime, endTime) => { if (!startTime || !endTime) return null try { const startHour = parseInt(startTime.substring(0, 2)) const startMin = parseInt(startTime.substring(2, 4)) const endHour = parseInt(endTime.substring(0, 2)) const endMin = parseInt(endTime.substring(2, 4)) if (isNaN(startHour) || isNaN(startMin) || isNaN(endHour) || isNaN(endMin)) { return null } const startTotal = startHour * 60 + startMin const endTotal = endHour * 60 + endMin let diff = endTotal - startTotal // Handle overnight (z.B. 23:00 - 01:00) if (diff < 0) { diff += 24 * 60 } return diff } catch (err) { return null } } /** * Erstellt ein neues Worksheet */ const createWorksheet = async (data, currentUser) => { if (DEMO_MODE) { const wsid = await generateWSID() const newWs = { ...data, $id: Date.now().toString(), wsid, $createdAt: new Date().toISOString() } setWorksheets(prev => [newWs, ...prev]) return { success: true, data: newWs } } try { // Validierung if (!data.woid || data.woid.trim() === '') { return { success: false, error: 'WOID ist erforderlich' } } if (!data.workorderId || data.workorderId.trim() === '') { return { success: false, error: 'Work Order ID ist erforderlich' } } if (!data.details || data.details.trim() === '') { return { success: false, error: 'Details sind erforderlich' } } // WSID generieren const wsid = await generateWSID() // Automatische Zeitberechnung (wenn nicht manuell angegeben) let totalTime = data.totalTime || 0 if (!data.isComment && data.startTime && data.endTime && !data.totalTime) { const calculatedTime = calculateTime(data.startTime, data.endTime) if (calculatedTime !== null) { totalTime = calculatedTime } } // Worksheet-Daten vorbereiten const worksheetData = { wsid, woid: data.woid.trim(), workorderId: data.workorderId.trim(), employeeId: currentUser.$id, employeeName: currentUser.name || currentUser.email, employeeShort: data.employeeShort || '', serviceType: data.serviceType || 'Remote', oldStatus: data.oldStatus || '', newStatus: data.newStatus || data.oldStatus || '', oldResponseLevel: data.oldResponseLevel || '', newResponseLevel: data.newResponseLevel || data.oldResponseLevel || '', totalTime: parseInt(totalTime) || 0, startDate: data.startDate || '', startTime: data.startTime || '', endDate: data.endDate || data.startDate || '', endTime: data.endTime || '', details: data.details.trim(), isComment: data.isComment || false, createdAt: new Date().toISOString() } console.log('Creating worksheet with data:', worksheetData) const response = await databases.createDocument( DATABASE_ID, COLLECTIONS.WORKSHEETS, ID.unique(), worksheetData ) setWorksheets(prev => [response, ...prev]) return { success: true, data: response } } catch (err) { console.error('Error creating worksheet:', err) return { success: false, error: err.message || 'Fehler beim Erstellen des Worksheets' } } } /** * Aktualisiert ein Worksheet */ const updateWorksheet = async (id, data) => { if (DEMO_MODE) { setWorksheets(prev => prev.map(ws => ws.$id === id ? { ...ws, ...data } : ws)) return { success: true } } try { const response = await databases.updateDocument( DATABASE_ID, COLLECTIONS.WORKSHEETS, id, data ) setWorksheets(prev => prev.map(ws => ws.$id === id ? response : ws)) return { success: true, data: response } } catch (err) { console.error('Error updating worksheet:', err) return { success: false, error: err.message } } } /** * Löscht ein Worksheet (sollte normalerweise nicht erlaubt sein - Audit Trail!) */ const deleteWorksheet = async (id) => { if (DEMO_MODE) { setWorksheets(prev => prev.filter(ws => ws.$id !== id)) return { success: true } } try { await databases.deleteDocument( DATABASE_ID, COLLECTIONS.WORKSHEETS, id ) setWorksheets(prev => prev.filter(ws => ws.$id !== id)) return { success: true } } catch (err) { console.error('Error deleting worksheet:', err) return { success: false, error: err.message } } } /** * Berechnet die Gesamtarbeitszeit für alle Worksheets * @returns Minuten */ const getTotalTime = useCallback(() => { return worksheets .filter(ws => !ws.isComment) .reduce((sum, ws) => sum + (ws.totalTime || 0), 0) }, [worksheets]) /** * Gruppiert Worksheets nach Mitarbeiter * @returns Object mit employeeId als Key */ const getWorksheetsByEmployee = useCallback(() => { return worksheets.reduce((acc, ws) => { const empId = ws.employeeId if (!acc[empId]) { acc[empId] = { employeeName: ws.employeeName, employeeShort: ws.employeeShort, worksheets: [], totalTime: 0 } } acc[empId].worksheets.push(ws) if (!ws.isComment) { acc[empId].totalTime += ws.totalTime || 0 } return acc }, {}) }, [worksheets]) /** * Gibt die Status-Historie zurück (chronologisch) */ const getStatusHistory = useCallback(() => { return worksheets .filter(ws => ws.oldStatus && ws.newStatus) .map(ws => ({ wsid: ws.wsid, date: ws.startDate, time: ws.startTime, employee: ws.employeeName, from: ws.oldStatus, to: ws.newStatus, details: ws.details })) .reverse() // Älteste zuerst }, [worksheets]) return { worksheets, loading, error, createWorksheet, updateWorksheet, deleteWorksheet, refresh: fetchWorksheets, getTotalTime, getWorksheetsByEmployee, getStatusHistory, calculateTime } }