
import { 
  SystemSettings, Workshop, InventoryItem, StorageRecord, Customer, 
  SystemUser, NewsEntry, WorkOrder, Offer, Appointment, InventorySession, 
  WarehouseLocation, AuditLogEntry, LoginLog, CashTransaction, CashClosing, CashCount, SeasonType, ModuleType, Vehicle, WorkCategory, StockMovement, GoodsReceiptData, StorageStatus, Technician, TimeEntry, WorkshopLift, LoanerCar, CashOpening, Supplier, ReferenceType
} from '../types';
import { MOCK_NEWS, MOCK_SYSTEM_USERS, MOCK_CUSTOMERS, MOCK_RECORDS, MOCK_VEHICLES, MOCK_PARTS, MOCK_LOGS } from './mockData';
import { addDays, format, addHours } from 'date-fns';

const DB_KEYS = {
  SETTINGS: 'tyremanager_settings', 
  WORKSHOPS: 'tyremanager_workshops',
  RECORDS: 'tyremanager_records',
  CUSTOMERS: 'tyremanager_customers',
  VEHICLES: 'tyremanager_vehicles',
  ORDERS: 'tyremanager_orders',
  APPOINTMENTS: 'tyremanager_appointments',
  USERS: 'tyremanager_users',
  NEWS: 'tyremanager_news',
  LOCATIONS: 'tyremanager_locations',
  TRANSACTIONS: 'tyremanager_transactions',
  CLOSINGS: 'tyremanager_closings',
  OPENINGS: 'tyremanager_openings', 
  TECHNICIANS: 'tyremanager_technicians',
  LIFTS: 'tyremanager_lifts',
  PARTS: 'tyremanager_parts',
  SESSIONS: 'tyremanager_sessions',
  REG_STATUS: 'tyremanager_reg_status',
  LOGS: 'tyremanager_logs',
  AUDIT_LOGS: 'tyremanager_audit_logs',
  LOGIN_LOGS: 'tyremanager_login_logs',
  STOCK_MOVEMENTS: 'tyremanager_stock_movements',
  COUNTERS: 'tyremanager_counters',
  TIME_ENTRIES: 'tyremanager_time_entries',
  SUPPLIERS: 'tyremanager_suppliers',
  OFFERS: 'tyremanager_offers'
};

const storage = {
  get: <T>(key: string, fallback: T): T => {
    const data = localStorage.getItem(key);
    return data ? JSON.parse(data) : fallback;
  },
  set: (key: string, data: any) => {
    localStorage.setItem(key, JSON.stringify(data));
  }
};

let currentWorkshopId = 'W1';
let currentUserSession: SystemUser | null = storage.get<SystemUser[]>(DB_KEYS.USERS, [])[0] || null;

const addAuditLog = (params: {
  action: AuditLogEntry['action'];
  entityType: AuditLogEntry['entityType'];
  entityId: string;
  oldValues?: any;
  newValues?: any;
  details?: string;
}) => {
  const logs = storage.get<AuditLogEntry[]>(DB_KEYS.AUDIT_LOGS, []);
  const currentUser = api.getCurrentUser();
  const newLog: AuditLogEntry = {
    id: `audit-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
    timestamp: new Date().toISOString(),
    userId: currentUser?.id.toString() || 'system',
    userName: currentUser?.name || 'System',
    action: params.action,
    entityType: params.entityType,
    entityId: params.entityId,
    oldValues: params.oldValues,
    newValues: params.newValues,
    details: params.details,
    workshopId: currentWorkshopId,
    ipAddress: '127.0.0.1' // In a real app, this would be the client's IP
  };
  storage.set(DB_KEYS.AUDIT_LOGS, [newLog, ...logs]);
};

const addLoginLog = (success: boolean) => {
  const logs = storage.get<LoginLog[]>(DB_KEYS.LOGIN_LOGS, []);
  const currentUser = api.getCurrentUser();
  const newLog: LoginLog = {
    id: `login-${Date.now()}`,
    userId: currentUser?.id.toString() || 'unknown',
    userName: currentUser?.name || 'Unknown',
    timestamp: new Date().toISOString(),
    ipAddress: '127.0.0.1',
    success,
    workshopId: currentWorkshopId
  };
  storage.set(DB_KEYS.LOGIN_LOGS, [newLog, ...logs]);
};

const getNextNumber = (type: 'stock' | 'inventory' | 'order' | 'offer'): string => {
  const counters = storage.get<Record<string, number>>(DB_KEYS.COUNTERS, {
    stock: 1000,
    inventory: 500,
    order: 2000,
    offer: 3000
  });
  const next = counters[type] + 1;
  counters[type] = next;
  storage.set(DB_KEYS.COUNTERS, counters);
  
  const prefixes = {
    stock: 'STK',
    inventory: 'INV',
    order: 'ORD',
    offer: 'OFF'
  };
  return `${prefixes[type]}-${next}`;
};

const defaultWorkingHours = { 
    1: {start:'08:00',end:'17:00',pause: 60,active:true}, 
    2: {start:'08:00',end:'17:00',pause: 60,active:true}, 
    3: {start:'08:00',end:'17:00',pause: 60,active:true}, 
    4: {start:'08:00',end:'17:00',pause: 60,active:true}, 
    5: {start:'08:00',end:'16:00',pause: 45,active:true}, 
    6: {start:'09:00',end:'13:00',pause: 0,active:true}, // Samstag offen für Demo
    0: {start:'00:00',end:'00:00',pause: 0,active:false} 
};

// Richer default settings with Loaner Cars pre-filled
const getDefaultSettings = (name: string): SystemSettings => ({
  companyName: name, address: 'Musterstraße 1', zip: '12345', city: 'Musterstadt', 
  phone: '0123 / 456789', email: 'info@werkstatt-muster.de', website: 'www.werkstatt-muster.de',
  bankName: 'Musterbank AG', iban: 'DE12 3456 7890 1234 5678 90', bic: 'MUSTDEFFXXX',
  taxId: '12/345/67890', vatId: 'DE 123 456 789', managingDirector: 'Max Mustermann',
  activeSeason: SeasonType.WINTER, 
  vehicleManufacturers: ['VW', 'Audi', 'BMW', 'Mercedes', 'Skoda', 'Seat', 'Tesla', 'Ford', 'Opel', 'Porsche'], 
  allowUsedCarInCheckIn: true, separateUsedCarStock: true, gwLocationPrefix: 'GW-', defaultMarkup: 30, hourlyRate: 120, 
  categoryRates: { 'Mechanik': 120, 'Karosserie': 140, 'Elektrik': 130, 'Hochvolt': 160, 'Lack': 150 } as any, 
  predefinedTasks: [
      { id: 't1', code: '0311', name: 'Räderwechsel (Satz)', category: WorkCategory.MECHANICS, defaultDuration: 30, fixedPrice: 40 },
      { id: 't2', code: '0313', name: 'Radeinlagerung (Saison)', category: WorkCategory.MECHANICS, defaultDuration: 10, fixedPrice: 60 },
      { id: 't3', code: '0101', name: 'Inspektion nach Herstellervorgabe', category: WorkCategory.MECHANICS, defaultDuration: 90 },
      { id: 't4', code: '0900', name: 'Fehlerspeicher auslesen', category: WorkCategory.ELECTRONICS, defaultDuration: 20, fixedPrice: 35 },
      { id: 't5', code: 'LWM', name: 'Leihwagen Miete (Tag)', category: WorkCategory.MECHANICS, defaultDuration: 0, bookingGroup: 'MISC' }
  ], 
  loanerCars: [
      { id: 'lc1', brand: 'VW', model: 'Golf 8', licensePlate: 'M-XY 999', pricePerDay: 35, active: true, currentMileage: 15400, fuelLevel: 90, damages: 'Kratzer Stoßstange hinten' },
      { id: 'lc2', brand: 'VW', model: 'Polo', licensePlate: 'M-AB 111', pricePerDay: 29, active: true, currentMileage: 22100, fuelLevel: 45 },
      { id: 'lc3', brand: 'Audi', model: 'A3 Sportback', licensePlate: 'M-ZZ 888', pricePerDay: 49, active: true, currentMileage: 5600, fuelLevel: 100 },
      { id: 'lc4', brand: 'Ford', model: 'Transit', licensePlate: 'M-TR 55', pricePerDay: 59, active: true, currentMileage: 89000, fuelLevel: 80, damages: 'Delle Schiebetür' }
  ], 
  taxRate: 19, lunchBreak: { active: true, start: '12:00', end: '13:00' }, 
  prices: { mountingTiered: { upTo17: 15, inch18: 18, inch19: 20, inch20: 22, inch21: 25, above22: 30 }, swap: 40, storage: 60, disposal: 5, cleaning: 10, valves: 5 }, 
  modules: [{ id: 'CORE', name: 'Reifen & Einlagerung', active: true, priceMonthly: 0 }, { id: 'CRM', name: 'Kundenverwaltung', active: true, priceMonthly: 19 }, { id: 'WORKSHOP', name: 'Werkstatt & Kalender', active: true, priceMonthly: 39 }, { id: 'STOCK', name: 'Teilehandel', active: true, priceMonthly: 19 }, { id: 'FINANCE', name: 'Kasse & Finanzen', active: true, priceMonthly: 29 }], 
  discountGroups: [
      { id: 'dg1', name: 'Standard', discountPercent: 0 },
      { id: 'dg2', name: 'Stammkunden', discountPercent: 10 },
      { id: 'dg3', name: 'Mitarbeiter', discountPercent: 20 }
  ],
  workOrderAdditionalText: 'Vielen Dank für Ihren Auftrag! Bitte prüfen Sie die Radmuttern nach 50km Fahrt auf festen Sitz.'
});

const initializeDB = (config?: { companyName: string, address: string, zip: string, city: string, adminUser: string, adminName: string }) => {
  // Only init if workshops are missing (indicator for empty DB) OR if config is provided (forced init)
  if (config || !localStorage.getItem(DB_KEYS.WORKSHOPS)) {
    const workshops = [
        { id: 'W1', name: config?.companyName || 'Hauptfiliale München', slug: 'main' },
        { id: 'W2', name: 'Zweigstelle Hamburg', slug: 'hamburg' }
    ];
    storage.set(DB_KEYS.WORKSHOPS, workshops);
    
    // Create settings with user config
    const defaultSettings = getDefaultSettings(workshops[0].name);
    if (config) {
        defaultSettings.companyName = config.companyName;
        defaultSettings.address = config.address;
        defaultSettings.zip = config.zip;
        defaultSettings.city = config.city;
    }
    workshops.forEach(ws => storage.set(`${DB_KEYS.SETTINGS}_${ws.id}`, ws.id === 'W1' ? defaultSettings : getDefaultSettings(ws.name)));
    
    // 1. LIFTS
    const initialLifts: WorkshopLift[] = [
        { id: 'lift-1', name: 'Bühne 1 (Annahme)', workshopId: 'W1' },
        { id: 'lift-2', name: 'Bühne 2 (Mechanik)', workshopId: 'W1' },
        { id: 'lift-3', name: 'Bühne 3 (Mechanik)', workshopId: 'W1' },
        { id: 'lift-4', name: 'Bühne 4 (Achsmess)', workshopId: 'W1' },
        { id: 'lift-5', name: 'Grube 1', workshopId: 'W1' }
    ];
    storage.set(DB_KEYS.LIFTS, initialLifts);

    // 2. TECHNICIANS (Linked to Users)
    const initialTechs: Technician[] = [
        { id: 't1', name: 'Max (Meister)', color: '#ef4444', workshopId: 'W1', workingHours: defaultWorkingHours, liftId: 'lift-1' }, // Red
        { id: 't2', name: 'Lisa (Geselle)', color: '#f59e0b', workshopId: 'W1', workingHours: defaultWorkingHours, liftId: 'lift-2' }, // Amber
        { id: 't3', name: 'Alex (Azubi)', color: '#10b981', workshopId: 'W1', workingHours: defaultWorkingHours, liftId: undefined }, // Green (Springer)
        { id: 't4', name: 'Bernd (Mechaniker)', color: '#3b82f6', workshopId: 'W1', workingHours: defaultWorkingHours, liftId: 'lift-3' }, // Blue
        
        // SALES & SERVICE STAFF
        { id: 't5', name: 'Julia (Verkauf)', color: '#8b5cf6', workshopId: 'W1', workingHours: defaultWorkingHours }, // Violet
        { id: 't6', name: 'Peter (Service)', color: '#06b6d4', workshopId: 'W1', workingHours: defaultWorkingHours }, // Cyan
        { id: 't7', name: 'Hans (Lager)', color: '#d97706', workshopId: 'W1', workingHours: defaultWorkingHours }, // Amber-600

        // ADMIN & OTHER STAFF
        { id: 't_global', name: 'Global Admin', color: '#111827', workshopId: 'W1', workingHours: defaultWorkingHours }, // Black
        { id: 't_admin', name: 'Admin (Chef)', color: '#4b5563', workshopId: 'W1', workingHours: defaultWorkingHours }, // Gray
        { id: 't_tom', name: 'Tom (Verkauf)', color: '#8b5cf6', workshopId: 'W1', workingHours: defaultWorkingHours }, // Violet
        { id: 't_anna', name: 'Anna (Service)', color: '#06b6d4', workshopId: 'W1', workingHours: defaultWorkingHours }, // Cyan
        { id: 't_klaus', name: 'Klaus (Lager)', color: '#d97706', workshopId: 'W1', workingHours: defaultWorkingHours } // Amber-600
    ];
    storage.set(DB_KEYS.TECHNICIANS, initialTechs);

    // 3. BASE DATA
    // Create custom admin user if config provided
    let initialUsers = [...MOCK_SYSTEM_USERS];

    // Add global_admin for demo purposes if not present
    if (!initialUsers.some(u => u.username === 'global_admin')) {
        const globalAdmin: SystemUser = {
            id: 998,
            username: 'global_admin',
            role_id: 0, // Superadmin
            workshop_id: 'W1',
            technicianId: 't_global',
            active: true,
            email: 'global@admin.demo',
            onlinenow: false,
            last_sessionid: null
        };
        initialUsers.push(globalAdmin);
    }

    // Add specific demo users for each department to showcase permissions
    const demoUsers: SystemUser[] = [
        { id: 901, username: 'demo_admin', role_id: 1, workshop_id: 'W1', technicianId: 't_admin', active: true, email: 'admin@demo.test', onlinenow: false, last_sessionid: null },
        { id: 902, username: 'demo_verkauf', role_id: 2, workshop_id: 'W1', technicianId: 't5', active: true, email: 'verkauf@demo.test', onlinenow: false, last_sessionid: null },
        { id: 903, username: 'demo_service', role_id: 3, workshop_id: 'W1', technicianId: 't6', active: true, email: 'service@demo.test', onlinenow: false, last_sessionid: null },
        { id: 904, username: 'demo_lager', role_id: 4, workshop_id: 'W1', technicianId: 't7', active: true, email: 'lager@demo.test', onlinenow: false, last_sessionid: null },
        { id: 905, username: 'demo_mechaniker', role_id: 5, workshop_id: 'W1', technicianId: 't1', active: true, email: 'mechaniker@demo.test', onlinenow: false, last_sessionid: null },
    ];

    demoUsers.forEach(du => {
        if (!initialUsers.some(u => u.username === du.username)) {
            initialUsers.push(du);
        }
    });

    if (config) {
        // Replace default admin or add new one
        const newAdmin: SystemUser = {
            id: 999,
            username: config.adminUser,
            role_id: 1,
            workshop_id: 'W1',
            technicianId: 't_admin',
            active: true,
            email: 'admin@local.test',
            onlinenow: false,
            last_sessionid: null
        };
        // Ensure we have a valid admin user
        initialUsers = [newAdmin, ...initialUsers.filter(u => u.username !== 'admin')];
    }

    storage.set(DB_KEYS.USERS, initialUsers);
    
    // Initialize customers with random balances for demo
    const initialCustomers = MOCK_CUSTOMERS.map(c => ({
        ...c,
        accountBalance: Math.random() > 0.7 ? (Math.random() * 500 - 250) : 0 // Some have debt, some credit, most 0
    }));
    storage.set(DB_KEYS.CUSTOMERS, initialCustomers);
    
    storage.set(DB_KEYS.VEHICLES, [...MOCK_VEHICLES]);
    storage.set(DB_KEYS.RECORDS, [...MOCK_RECORDS]);
    storage.set(DB_KEYS.NEWS, [...MOCK_NEWS]);
    storage.set(DB_KEYS.PARTS, [...MOCK_PARTS]);
    storage.set(DB_KEYS.LOGS, [...MOCK_LOGS]);
    
    // 4. LOCATIONS (Generate grid)
    const locs: WarehouseLocation[] = [];
    for(let i=1; i<=20; i++) locs.push({ id: `loc-${i}`, name: `00${i}`, type: 'shelf', workshopId: 'W1' });
    for(let i=1; i<=10; i++) locs.push({ id: `gw-${i}`, name: `GW-${i.toString().padStart(2, '0')}`, type: 'floor', workshopId: 'W1' });
    storage.set(DB_KEYS.LOCATIONS, locs);

    storage.set(DB_KEYS.SUPPLIERS, [
        { id: 'sup-1', name: 'WM SE', customerNumber: '100200', email: 'bestellung@wm.de', phone: '089 111222' },
        { id: 'sup-2', name: 'Stahlgruber', customerNumber: '556677', email: 'order@stahlgruber.de' },
        { id: 'sup-3', name: 'Reifen Gundlach', customerNumber: 'RG-999', shopUrl: 'https://b2b.reifengundlach.de' }
    ]);

    // 5. DYNAMIC ORDERS & APPOINTMENTS (Today/Tomorrow)
    const today = new Date();
    const tomorrow = addDays(today, 1);
    
    const genOrder = (id: string, custId: string, plate: string, status: WorkOrder['status'], techId: string, offsetHours: number, duration: number, title: string, hasLoaner: boolean = false): WorkOrder => {
        const baseTime = new Date(today);
        baseTime.setHours(8, 0, 0, 0);
        const start = addHours(baseTime, offsetHours);
        return {
            id, customerId: custId, licensePlate: plate, status, 
            createdAt: addHours(today, -24).toISOString(), 
            workshopId: 'W1', hourlyRate: 120, totalDuration: duration, totalNet: 100, totalGross: 119, technicianId: techId,
            paidAmount: 0, balance: 119,
            bringInDate: start.toISOString(),
            expectedDeliveryDate: addHours(start, duration/60).toISOString(),
            startedAt: status === 'in_progress' ? start.toISOString() : undefined,
            interventions: [{ 
                id: `i-${id}`, title, 
                tasks: [
                    { code: '0311', name: 'Arbeitsposition', duration: duration, category: WorkCategory.MECHANICS, price: (duration/60)*120, technicianId: techId },
                    ...(hasLoaner ? [{ code: 'LWM', name: 'Leihwagen Miete', duration: 0, category: WorkCategory.MECHANICS, price: 35, bookingGroup: 'MISC' as const }] : [])
                ], 
                additionalItems: [] 
            }]
        };
    };

    const genApp = (id: string, order: WorkOrder, time: string): Appointment => ({
        id, technicianId: order.technicianId!, orderId: order.id, customerName: 'Kunde', licensePlate: order.licensePlate,
        title: order.interventions[0].title, date: format(new Date(order.bringInDate!), 'yyyy-MM-dd'), startTime: time, duration: order.totalDuration,
        status: order.status === 'in_progress' ? 'in_progress' : (order.status === 'completed' ? 'completed' : 'scheduled'), workshopId: 'W1'
    });

    const orders: WorkOrder[] = [
        genOrder('AU-1001', 'c1', 'M-XY 123', 'completed', 't1', 0, 60, 'Räderwechsel'), // Max 08:00
        genOrder('AU-1002', 'c2', 'M-AB 456', 'in_progress', 't1', 1.5, 90, 'Inspektion & Öl'), // Max 09:30
        genOrder('AU-1003', 'c4', 'T-EST 99', 'planned', 't1', 4, 45, 'Räder & Wuchten'), // Max 12:00
        
        genOrder('AU-1004', 'c3', 'M-BG 777', 'in_progress', 't2', 0, 120, 'Bremsen HA komplett', true), // Lisa 08:00 + Loaner
        genOrder('AU-1005', 'c5', 'M-JJ 55', 'planned', 't2', 3, 60, 'Klima-Service'), // Lisa 11:00

        genOrder('AU-1006', 'c7', 'M-PP 2020', 'planned', 't4', 1, 60, 'Achsmessung'), // Bernd 09:00
    ];

    const apps: Appointment[] = [
        genApp('ap1', orders[0], '08:00'),
        genApp('ap2', orders[1], '09:30'),
        genApp('ap3', orders[2], '13:00'),
        genApp('ap4', orders[3], '08:00'),
        genApp('ap5', orders[4], '11:00'),
        genApp('ap6', orders[5], '09:00'),
        // Tomorrow
        { id: 'ap7', technicianId: 't1', title: 'HU/AU', customerName: 'Firma Logistik', licensePlate: 'M-LO 100', date: format(tomorrow, 'yyyy-MM-dd'), startTime: '08:00', duration: 60, status: 'scheduled', workshopId: 'W1' }
    ];

    storage.set(DB_KEYS.ORDERS, orders);
    storage.set(DB_KEYS.APPOINTMENTS, apps);

    // Initial Time Entries
    const timeEntries: TimeEntry[] = [
        { id: 'te1', userId: 5, date: format(today, 'yyyy-MM-dd'), startTime: '07:45', type: 'shift' }, // Max in
        { id: 'te2', userId: 6, date: format(today, 'yyyy-MM-dd'), startTime: '07:55', type: 'shift' }, // Lisa in
    ];
    storage.set(DB_KEYS.TIME_ENTRIES, timeEntries);
  }
};

// initializeDB(); // Removed auto-init

const simulateNetwork = async <T>(data: T, delay = 100): Promise<T> => {
  return new Promise((resolve) => setTimeout(() => resolve(data), delay));
};

export const api = {
  addLog: (type: string, action: string, details: string) => {
    addAuditLog({
      action: 'UPDATE',
      entityType: type,
      entityId: 'system',
      details: `${action}: ${details}`
    });
  },
  getAuditLogs: async () => simulateNetwork(storage.get<AuditLogEntry[]>(DB_KEYS.AUDIT_LOGS, [])),
  getLoginLogs: async () => simulateNetwork(storage.get<LoginLog[]>(DB_KEYS.LOGIN_LOGS, [])),
  getStockMovements: async () => simulateNetwork(storage.get<StockMovement[]>(DB_KEYS.STOCK_MOVEMENTS, [])),
  
  createStockMovement: async (movement: Partial<StockMovement>) => {
    const list = storage.get<StockMovement[]>(DB_KEYS.STOCK_MOVEMENTS, []);
    const currentUser = api.getCurrentUser();
    
    // Check for active inventory
    const sessions = storage.get<InventorySession[]>(DB_KEYS.SESSIONS, []);
    const activeInventory = sessions.find(s => s.status === 'open' && s.workshopId === currentWorkshopId);
    
    const newMovement: StockMovement = {
      ...movement,
      id: `sm-${Date.now()}`,
      movementNumber: getNextNumber('stock'),
      createdAt: new Date().toISOString(),
      createdBy: currentUser?.name || 'System',
      workshopId: currentWorkshopId,
      isImmutable: true,
      notes: activeInventory 
        ? `${movement.notes || ''} (WÄHREND INVENTUR ${activeInventory.sessionNumber})`.trim()
        : movement.notes
    } as StockMovement;
    
    list.push(newMovement);
    storage.set(DB_KEYS.STOCK_MOVEMENTS, list);
    
    addAuditLog({
      action: 'CREATE',
      entityType: 'StockMovement',
      entityId: newMovement.id,
      newValues: newMovement,
      details: `Lagerbuchung ${newMovement.movementNumber} erstellt`
    });
    
    return simulateNetwork(newMovement);
  },

  stornoStockMovement: async (id: string, reason: string) => {
    const list = storage.get<StockMovement[]>(DB_KEYS.STOCK_MOVEMENTS, []);
    const original = list.find(m => m.id === id);
    if (!original) throw new Error("Originalbuchung nicht gefunden");
    
    const currentUser = api.getCurrentUser();
    const stornoMovement: StockMovement = {
      ...original,
      id: `sm-storno-${Date.now()}`,
      movementNumber: getNextNumber('stock'),
      type: 'storno',
      quantity: -original.quantity,
      originalMovementId: original.id,
      notes: `Storno von ${original.movementNumber}: ${reason}`,
      createdAt: new Date().toISOString(),
      createdBy: currentUser?.name || 'System',
      isImmutable: true
    };
    
    list.push(stornoMovement);
    storage.set(DB_KEYS.STOCK_MOVEMENTS, list);
    
    // Also update part stock
    const parts = storage.get<InventoryItem[]>(DB_KEYS.PARTS, []);
    const partIdx = parts.findIndex(p => p.id === original.partId);
    if (partIdx !== -1) {
      parts[partIdx].quantity += stornoMovement.quantity;
      storage.set(DB_KEYS.PARTS, parts);
    }

    addAuditLog({
      action: 'STORNO',
      entityType: 'StockMovement',
      entityId: stornoMovement.id,
      details: `Storno für Buchung ${original.movementNumber} durchgeführt`
    });

    return simulateNetwork(stornoMovement);
  },
  isInstalled: () => !!localStorage.getItem('app_installed'),
  installApplication: async (config: { companyName: string, address: string, zip: string, city: string, adminUser: string, adminName: string }) => {
      localStorage.clear(); // Clean slate
      initializeDB(config);
      localStorage.setItem('app_installed', 'true');
      return simulateNetwork(true);
  },
  getSystemSettings: async () => simulateNetwork(storage.get<SystemSettings>(`${DB_KEYS.SETTINGS}_${currentWorkshopId}`, getDefaultSettings('Werkstatt'))),
  saveSystemSettings: async (newSettings: SystemSettings) => { storage.set(`${DB_KEYS.SETTINGS}_${currentWorkshopId}`, newSettings); window.dispatchEvent(new Event('settings-updated')); return simulateNetwork(true); },
  getWorkshops: async () => simulateNetwork(storage.get<Workshop[]>(DB_KEYS.WORKSHOPS, [])),
  getWorkshop: () => currentWorkshopId,
  switchWorkshop: async (id: string) => { currentWorkshopId = id; window.dispatchEvent(new Event('settings-updated')); return simulateNetwork(true); },

  getCurrentUser: () => currentUserSession ? { ...currentUserSession, name: currentUserSession.username, role: currentUserSession.role_id === 1 ? 'Admin' : (currentUserSession.role_id === 0 ? 'Superadmin' : 'User'), roleId: currentUserSession.role_id, workshopId: currentUserSession.workshop_id, technicianId: currentUserSession.technicianId } : null,
  login: async (u: string, p: string) => { 
    const users = storage.get<SystemUser[]>(DB_KEYS.USERS, []); 
    const user = users.find(user => user.username === u); 
    if (user) { 
        // If user has a password set, check it. Otherwise allow any password for backward compatibility with existing mock users.
        if (user.password && user.password !== p) {
            throw new Error("Ungültiges Passwort");
        }
        currentUserSession = user; 
        api.addLog('audit', 'Login', `Benutzer ${u} angemeldet.`); 
        return simulateNetwork(api.getCurrentUser()); 
    } 
    throw new Error("Ungültiger Benutzername"); 
  },
  logout: () => { currentUserSession = null; },

  getFreeLocation: async (isUsedCar: boolean) => {
    const locs = storage.get<WarehouseLocation[]>(DB_KEYS.LOCATIONS, []).filter(l => l.workshopId === currentWorkshopId);
    const recs = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []);
    const sett = storage.get<SystemSettings>(`${DB_KEYS.SETTINGS}_${currentWorkshopId}`, getDefaultSettings('Werkstatt'));
    const occupied = new Set(recs.filter(r => r.status !== StorageStatus.PICKED_UP && r.workshopId === currentWorkshopId).map(r => r.location));
    
    if (isUsedCar && sett.separateUsedCarStock) {
      const prefix = sett.gwLocationPrefix || 'GW-';
      const gwLoc = locs
        .filter(l => l.name.startsWith(prefix))
        .sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }))
        .find(l => !occupied.has(l.name));
      return simulateNetwork(gwLoc ? gwLoc.name : null);
    }
    
    const free = locs
        .sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }))
        .find(l => !occupied.has(l.name));
    return simulateNetwork(free ? free.name : null);
  },

  getStorageRecords: async () => simulateNetwork(storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []).filter(r => r.workshopId === currentWorkshopId)),
  getStorageRecordsByCustomer: async (customerId: string) => {
      const all = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []);
      return simulateNetwork(all.filter(r => r.customerId === customerId && r.workshopId === currentWorkshopId));
  },
  createStorageRecord: async (data: Partial<StorageRecord>) => {
      let list = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []);
      const newRec = { ...data, id: `r-${Date.now()}`, workshopId: currentWorkshopId } as StorageRecord;
      list.push(newRec);
      storage.set(DB_KEYS.RECORDS, list);
      api.addLog('auslagerung', 'Neu-Einlagerung', `${data.licensePlate} an Ort ${data.location}.`);
      return simulateNetwork(newRec);
  },
  updateStorageRecord: async (id: string, data: Partial<StorageRecord>) => {
      let list = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []);
      storage.set(DB_KEYS.RECORDS, list.map(r => r.id === id ? { ...r, ...data } : r));
      return simulateNetwork(true);
  },
  checkOutRecord: async (id: string, user: string) => {
      let list = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []);
      const rec = list.find(r => r.id === id);
      if (rec) { rec.status = StorageStatus.PICKED_UP; storage.set(DB_KEYS.RECORDS, list); api.addLog('auslagerung', 'Auslagerung', `${rec.licensePlate} durch ${user}.`); }
      return simulateNetwork(true);
  },
  relocateRecord: async (id: string, loc: string, user: string) => {
      let list = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []);
      const rec = list.find(r => r.id === id);
      if (rec) { const old = rec.location; rec.location = loc; storage.set(DB_KEYS.RECORDS, list); api.addLog('relocate', 'Umlagerung', `${rec.licensePlate}: ${old} -> ${loc}`); }
      return simulateNetwork(true);
  },
  convertToUsedCar: async (id: string, user: string) => {
    let list = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []);
    const rec = list.find(r => r.id === id);
    if (rec) { 
      rec.isUsedCar = true; 
      rec.customerId = 'stock-usedcar'; 
      
      // Also find other records for the same license plate and convert them
      list.forEach(r => {
        if (r.licensePlate === rec.licensePlate && r.workshopId === currentWorkshopId) {
          r.isUsedCar = true;
          r.customerId = 'stock-usedcar';
        }
      });
      
      storage.set(DB_KEYS.RECORDS, list); 
      
      // Also update the vehicle if it exists
      let vList = storage.get<Vehicle[]>(DB_KEYS.VEHICLES, []);
      const vehicle = vList.find(v => v.licensePlate === rec.licensePlate && v.workshopId === currentWorkshopId);
      if (vehicle) {
          vehicle.customerId = 'stock-usedcar';
          storage.set(DB_KEYS.VEHICLES, vList);
      }

      api.addLog('audit', 'GW-Übernahme', `${rec.licensePlate} inkl. eingelagerter Reifen durch ${user}.`); 
    }
    return simulateNetwork(true);
  },

  getLocations: async () => simulateNetwork(storage.get<WarehouseLocation[]>(DB_KEYS.LOCATIONS, []).filter(l => l.workshopId === currentWorkshopId)),
  createLocation: async (name: string) => {
      let list = storage.get<WarehouseLocation[]>(DB_KEYS.LOCATIONS, []);
      const nl = { id: `loc-${Date.now()}`, name, type: 'shelf', workshopId: currentWorkshopId } as WarehouseLocation;
      list.push(nl);
      storage.set(DB_KEYS.LOCATIONS, list);
      return simulateNetwork(nl);
  },
  getLifts: async () => simulateNetwork(storage.get<WorkshopLift[]>(DB_KEYS.LIFTS, []).filter(l => l.workshopId === currentWorkshopId)),
  createLift: async (name: string) => {
      let list = storage.get<WorkshopLift[]>(DB_KEYS.LIFTS, []);
      const nl = { id: `lift-${Date.now()}`, name, workshopId: currentWorkshopId };
      list.push(nl);
      storage.set(DB_KEYS.LIFTS, list);
      return simulateNetwork(nl);
  },
  deleteLift: async (id: string) => {
      let list = storage.get<WorkshopLift[]>(DB_KEYS.LIFTS, []);
      storage.set(DB_KEYS.LIFTS, list.filter(l => l.id !== id));
      return simulateNetwork(true);
  },

  getParts: async () => {
      let parts = storage.get<InventoryItem[]>(DB_KEYS.PARTS, []);
      // Inject missing mock parts to ensure we always have some data for testing
      let modified = false;
      for (const mockPart of MOCK_PARTS) {
          if (!parts.some(p => p.id === mockPart.id)) {
              parts.push(mockPart);
              modified = true;
          }
      }
      if (modified) {
          storage.set(DB_KEYS.PARTS, parts);
      }
      return simulateNetwork(parts.filter(p => p.workshopId === currentWorkshopId));
  },
  updatePart: async (id: string, data: Partial<InventoryItem>) => {
      let list = storage.get<InventoryItem[]>(DB_KEYS.PARTS, []);
      const oldPart = list.find(p => p.id === id);
      if (!oldPart) return simulateNetwork(false);

      // Prevent direct quantity updates via this method
      const { quantity, ...otherData } = data;
      const updatedPart = { ...oldPart, ...otherData, updatedAt: new Date().toISOString() };
      
      storage.set(DB_KEYS.PARTS, list.map(p => p.id === id ? updatedPart : p));
      
      addAuditLog({
        action: 'UPDATE',
        entityType: 'InventoryItem',
        entityId: id,
        oldValues: oldPart,
        newValues: updatedPart
      });

      return simulateNetwork(true);
  },
  deletePart: async (id: string) => {
      let list = storage.get<InventoryItem[]>(DB_KEYS.PARTS, []);
      const currentUser = api.getCurrentUser();
      // GoBD: Soft delete
      storage.set(DB_KEYS.PARTS, list.map(p => p.id === id ? { 
        ...p, 
        deletedAt: new Date().toISOString(), 
        deletedBy: currentUser?.name || 'System' 
      } : p));
      
      addAuditLog({
        action: 'DELETE',
        entityType: 'InventoryItem',
        entityId: id,
        details: 'Teil archiviert (Soft-Delete)'
      });
      
      return simulateNetwork(true);
  },
  savePart: async (p: InventoryItem) => {
      let list = storage.get<InventoryItem[]>(DB_KEYS.PARTS, []);
      const currentUser = api.getCurrentUser();
      const partToSave = { 
        ...p, 
        workshopId: p.workshopId || currentWorkshopId,
        createdAt: p.createdAt || new Date().toISOString(),
        createdBy: p.createdBy || currentUser?.name || 'System'
      };
      const existingIdx = list.findIndex(x => x.id === partToSave.id);
      
      if (existingIdx !== -1) {
          const oldPart = list[existingIdx];
          // Prevent direct quantity updates via this method
          const { quantity, ...otherData } = partToSave;
          list[existingIdx] = { ...oldPart, ...otherData, updatedAt: new Date().toISOString() };
          
          addAuditLog({
            action: 'UPDATE',
            entityType: 'InventoryItem',
            entityId: partToSave.id,
            oldValues: oldPart,
            newValues: list[existingIdx]
          });
      } else {
          const newId = partToSave.id || `p-${Date.now()}`;
          const finalPart = { ...partToSave, id: newId };
          list.push(finalPart);
          // Initial stock movement
          if (finalPart.quantity > 0) {
            await api.createStockMovement({
              partId: finalPart.id,
              partName: finalPart.name,
              quantity: finalPart.quantity,
              type: 'in',
              notes: 'Anfangsbestand bei Neuanlage'
            });
          }
          addAuditLog({
            action: 'CREATE',
            entityType: 'InventoryItem',
            entityId: finalPart.id,
            newValues: finalPart
          });
      }
      storage.set(DB_KEYS.PARTS, list);
      return simulateNetwork(partToSave);
  },
  processGoodsReceipt: async (receipt: GoodsReceiptData) => {
    let partsList = storage.get<InventoryItem[]>(DB_KEYS.PARTS, []);
    for (const pos of receipt.positions) {
        // Suche nur im Bestand des aktuellen Standorts
        let part = partsList.find(p => p.workshopId === currentWorkshopId && ((pos.itemId && p.id === pos.itemId) || (pos.articleNumber && p.articleNumber === pos.articleNumber)));
        const qtyToDeliver = Number(pos.deliveredQuantity) || 0;
        if (part) {
            part.quantity += qtyToDeliver;
            part.purchasePrice = Number(pos.purchasePrice) || part.purchasePrice;
            part.lastRestockDate = receipt.receiptDate;
            
            await api.createStockMovement({
              partId: part.id,
              partName: part.name,
              quantity: qtyToDeliver,
              type: 'in',
              referenceType: 'GOODS_RECEIPT',
              referenceNumber: receipt.receiptNumber,
              notes: `Wareneingang ${receipt.receiptNumber}`
            });
        } else {
            const newPart: InventoryItem = {
                id: `p-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
                articleNumber: pos.articleNumber || 'UNBEKANNT',
                name: pos.name || 'Neuer Artikel',
                category: pos.category || 'Ersatzteile',
                manufacturer: '-',
                quantity: qtyToDeliver,
                unit: (pos.unit as any) || 'stk',
                minQuantity: 5,
                purchasePrice: Number(pos.purchasePrice) || 0,
                salesPrice: (Number(pos.purchasePrice) || 0) * 1.3,
                location: pos.location || 'WE-Lager',
                supplierId: receipt.supplierId,
                lastRestockDate: receipt.receiptDate,
                bookingGroup: 'PARTS',
                workshopId: currentWorkshopId, // Zuweisung zum aktuellen Standort
                createdAt: new Date().toISOString(),
                createdBy: api.getCurrentUser()?.name || 'System'
            };
            partsList.push(newPart);
            
            await api.createStockMovement({
              partId: newPart.id,
              partName: newPart.name,
              quantity: qtyToDeliver,
              type: 'in',
              referenceType: 'GOODS_RECEIPT',
              referenceNumber: receipt.receiptNumber,
              notes: `Wareneingang ${receipt.receiptNumber} (Neuanlage)`
            });
        }
        api.addLog('audit', 'Wareneingang', `Artikel ${pos.articleNumber || pos.name} am Standort ${currentWorkshopId} gebucht (+${qtyToDeliver})`);
    }
    storage.set(DB_KEYS.PARTS, partsList);
    
    addAuditLog({
      action: 'CREATE',
      entityType: 'GoodsReceipt',
      entityId: receipt.receiptNumber,
      details: `Wareneingang ${receipt.receiptNumber} verarbeitet`
    });
    
    return simulateNetwork(true);
  },

  getSuppliers: async () => simulateNetwork(storage.get<Supplier[]>(DB_KEYS.SUPPLIERS, [])),
  saveSupplier: async (s: Supplier) => { let list = storage.get<Supplier[]>(DB_KEYS.SUPPLIERS, []); if (s.id) storage.set(DB_KEYS.SUPPLIERS, list.map(sup => sup.id === s.id ? s : sup)); else { list.push({ ...s, id: `sup-${Date.now()}` }); storage.set(DB_KEYS.SUPPLIERS, list); } return simulateNetwork(true); },
  exportGoBDData: async (startDate: string, endDate: string) => {
    const filterByDate = (item: any) => {
      const date = item.createdAt || item.timestamp || item.date;
      if (!date) return true;
      return date >= startDate && date <= endDate;
    };

    const data = {
      auditLogs: storage.get<AuditLogEntry[]>(DB_KEYS.AUDIT_LOGS, []).filter(filterByDate),
      loginLogs: storage.get<LoginLog[]>(DB_KEYS.LOGIN_LOGS, []).filter(filterByDate),
      stockMovements: storage.get<StockMovement[]>(DB_KEYS.STOCK_MOVEMENTS, []).filter(filterByDate),
      parts: storage.get<InventoryItem[]>(DB_KEYS.PARTS, []),
      customers: storage.get<Customer[]>(DB_KEYS.CUSTOMERS, []),
      orders: storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []).filter(filterByDate),
      offers: storage.get<Offer[]>(DB_KEYS.OFFERS, []).filter(filterByDate),
      inventorySessions: storage.get<InventorySession[]>(DB_KEYS.SESSIONS, []).filter(filterByDate)
    };

    // Helper to convert to CSV
    const toCSV = (arr: any[]) => {
      if (arr.length === 0) return '';
      const headers = Object.keys(arr[0]);
      const rows = arr.map(obj => 
        headers.map(header => {
          const val = obj[header];
          return typeof val === 'object' ? JSON.stringify(val).replace(/"/g, '""') : `"${val}"`;
        }).join(',')
      );
      return [headers.join(','), ...rows].join('\n');
    };

    return simulateNetwork({
      json: JSON.stringify(data, null, 2),
      csv: {
        auditLogs: toCSV(data.auditLogs),
        loginLogs: toCSV(data.loginLogs),
        stockMovements: toCSV(data.stockMovements),
        parts: toCSV(data.parts),
        customers: toCSV(data.customers),
        orders: toCSV(data.orders)
      },
      exportInfo: {
        generatedAt: new Date().toISOString(),
        period: `${startDate} - ${endDate}`,
        workshopId: currentWorkshopId
      }
    });
  },
  getSystemLogs: async (type: string) => { const all = storage.get<AuditLogEntry[]>(DB_KEYS.AUDIT_LOGS, []); return simulateNetwork(all.filter(l => l.workshopId === currentWorkshopId)); },
  exportAuditData: async () => simulateNetwork(JSON.stringify(storage.get<AuditLogEntry[]>(DB_KEYS.AUDIT_LOGS, []), null, 2)),

  getCustomers: async () => simulateNetwork(storage.get<Customer[]>(DB_KEYS.CUSTOMERS, []).filter(c => c.workshopId === currentWorkshopId)),
  createCustomer: async (c: Partial<Customer>) => {
      let list = storage.get<Customer[]>(DB_KEYS.CUSTOMERS, []);
      const nc = { ...c, id: `c-${Date.now()}`, workshopId: currentWorkshopId } as Customer;
      list.push(nc);
      storage.set(DB_KEYS.CUSTOMERS, list);
      return simulateNetwork(nc);
  },
  updateCustomer: async (id: string, data: Partial<Customer>) => {
      let list = storage.get<Customer[]>(DB_KEYS.CUSTOMERS, []);
      storage.set(DB_KEYS.CUSTOMERS, list.map(c => c.id === id ? { ...c, ...data } : c));
      return simulateNetwork(true);
  },
  updateCustomerBalance: async (customerId: string, amount: number) => {
      let list = storage.get<Customer[]>(DB_KEYS.CUSTOMERS, []);
      storage.set(DB_KEYS.CUSTOMERS, list.map(c => {
          if (c.id === customerId) {
              return { ...c, accountBalance: (c.accountBalance || 0) + amount };
          }
          return c;
      }));
      return simulateNetwork(true);
  },
  getVehicles: async () => {
      const customers = storage.get<Customer[]>(DB_KEYS.CUSTOMERS, []).filter(c => c.workshopId === currentWorkshopId);
      const customerIds = new Set(customers.map(c => c.id));
      return simulateNetwork(storage.get<Vehicle[]>(DB_KEYS.VEHICLES, []).filter(v => 
          v.workshopId === currentWorkshopId || customerIds.has(v.customerId) || (v.customerId === 'stock-usedcar' && (v.workshopId === currentWorkshopId || !v.workshopId))
      ));
  },
  getVehiclesByCustomer: async (cid: string) => simulateNetwork(storage.get<Vehicle[]>(DB_KEYS.VEHICLES, []).filter(v => v.customerId === cid)),
  createVehicle: async (v: Partial<Vehicle>) => {
      let list = storage.get<Vehicle[]>(DB_KEYS.VEHICLES, []);
      const nv = { ...v, id: `v-${Date.now()}`, workshopId: currentWorkshopId } as Vehicle;
      list.push(nv);
      storage.set(DB_KEYS.VEHICLES, list);
      return simulateNetwork(nv);
  },
  updateVehicle: async (id: string, data: Partial<Vehicle>) => {
      let list = storage.get<Vehicle[]>(DB_KEYS.VEHICLES, []);
      storage.set(DB_KEYS.VEHICLES, list.map(v => v.id === id ? { ...v, ...data } : v));
      return simulateNetwork(true);
  },
  deleteVehicle: async (id: string) => {
      let list = storage.get<Vehicle[]>(DB_KEYS.VEHICLES, []);
      storage.set(DB_KEYS.VEHICLES, list.filter(v => v.id !== id));
      return simulateNetwork(true);
  },
  convertVehicleToUsedCar: async (vehicleId: string) => {
      // 1. Convert Vehicle
      let vList = storage.get<Vehicle[]>(DB_KEYS.VEHICLES, []);
      const vehicle = vList.find(v => v.id === vehicleId);
      if (!vehicle) throw new Error("Vehicle not found");
      
      vehicle.customerId = 'stock-usedcar';
      vehicle.workshopId = vehicle.workshopId || currentWorkshopId;
      storage.set(DB_KEYS.VEHICLES, vList);

      // 2. Convert associated tires
      let rList = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []);
      let changed = false;
      rList.forEach(r => {
          if (r.licensePlate === vehicle.licensePlate && (r.workshopId === currentWorkshopId || !r.workshopId)) {
              r.customerId = 'stock-usedcar';
              r.isUsedCar = true;
              r.workshopId = r.workshopId || currentWorkshopId;
              changed = true;
          }
      });
      if (changed) {
          storage.set(DB_KEYS.RECORDS, rList);
      }
      
      return simulateNetwork(true);
  },
  getWorkOrders: async () => {
      const list = storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []);
      // Deduplicate by ID
      const uniqueList = Array.from(new Map(list.map(item => [item.id, item])).values());
      if (uniqueList.length !== list.length) {
          storage.set(DB_KEYS.ORDERS, uniqueList);
      }
      return simulateNetwork(uniqueList.filter(o => o.workshopId === currentWorkshopId));
  },
  getWorkOrdersByCustomer: async (customerId: string) => {
      const list = storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []);
      return simulateNetwork(list.filter(o => (o.customerId === customerId || o.invoiceRecipientId === customerId) && o.workshopId === currentWorkshopId));
  },
  getOffers: async () => {
      let list = storage.get<Offer[]>(DB_KEYS.OFFERS, []);
      return simulateNetwork(list.filter(o => o.workshopId === currentWorkshopId));
  },
  getOffersByCustomer: async (customerId: string) => {
      const list = storage.get<Offer[]>(DB_KEYS.OFFERS, []);
      return simulateNetwork(list.filter(o => o.customerId === customerId && o.workshopId === currentWorkshopId));
  },
  createOffer: async (data: Partial<Offer>) => {
      let list = storage.get<Offer[]>(DB_KEYS.OFFERS, []);
      const no: Offer = {
          ...data,
          id: `off-${Date.now()}`,
          offerNumber: `AN-${new Date().getFullYear()}-${list.length + 1001}`,
          createdAt: new Date().toISOString(),
          workshopId: currentWorkshopId,
          status: 'draft',
          interventions: data.interventions || [],
          totalDuration: data.totalDuration || 0,
          totalNet: data.totalNet || 0,
          totalGross: data.totalGross || 0,
          hourlyRate: data.hourlyRate || 120
      } as Offer;
      list.push(no);
      storage.set(DB_KEYS.OFFERS, list);
      api.addLog('system', 'Angebot erstellt', `Angebot ${no.offerNumber} für Kunde ${no.customerId} erstellt.`);
      return simulateNetwork(no);
  },
  updateOffer: async (id: string, data: Partial<Offer>) => {
      let list = storage.get<Offer[]>(DB_KEYS.OFFERS, []);
      storage.set(DB_KEYS.OFFERS, list.map(o => o.id === id ? { ...o, ...data } : o));
      return simulateNetwork(true);
  },
  deleteOffer: async (id: string) => {
      let list = storage.get<Offer[]>(DB_KEYS.OFFERS, []);
      storage.set(DB_KEYS.OFFERS, list.map(o => o.id === id ? { ...o, status: 'rejected' } : o));
      return simulateNetwork(true);
  },
  convertOfferToOrder: async (offerId: string) => {
      let offers = storage.get<Offer[]>(DB_KEYS.OFFERS, []);
      const offer = offers.find(o => o.id === offerId);
      if (!offer) throw new Error("Angebot nicht gefunden");
      
      const orderData: WorkOrder = {
          id: `wo-${Date.now()}`,
          customerId: offer.customerId,
          licensePlate: offer.licensePlate,
          manufacturer: offer.manufacturer,
          model: offer.model,
          interventions: offer.interventions,
          totalDuration: offer.totalDuration,
          hourlyRate: offer.hourlyRate,
          totalNet: offer.totalNet,
          totalGross: offer.totalGross,
          mileage: offer.mileage,
          vin: offer.vin,
          hsn: offer.hsn,
          tsn: offer.tsn,
          firstRegistration: offer.firstRegistration,
          fuelType: offer.fuelType,
          nextHU: offer.nextHU,
          voucher: offer.voucher,
          workshopId: offer.workshopId,
          technicianId: offer.technicianId,
          status: 'created',
          createdAt: new Date().toISOString(),
          paidAmount: 0,
          balance: offer.totalGross
      };
      
      const newOrder = await api.createWorkOrder(orderData);
      
      storage.set(DB_KEYS.OFFERS, offers.map(o => o.id === offerId ? { ...o, status: 'converted', convertedToOrderId: newOrder.id } : o));
      
      api.addLog('system', 'Angebot umgewandelt', `Angebot ${offer.offerNumber} in Auftrag ${newOrder.id} umgewandelt.`);
      return simulateNetwork(newOrder);
  },
  createWorkOrder: async (o: WorkOrder) => {
      let list = storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []);
      let partsList = storage.get<InventoryItem[]>(DB_KEYS.PARTS, []);
      
      // Initialize paidAmount and balance if missing
      const orderToSave = {
          ...o,
          orderNumber: o.orderNumber || getNextNumber('order'),
          paidAmount: o.paidAmount ?? 0,
          balance: o.balance ?? (o.totalGross - (o.paidAmount ?? 0)),
          createdAt: o.createdAt || new Date().toISOString(),
          createdBy: o.createdBy || api.getCurrentUser()?.name || 'System'
      };

      if (list.some(ex => ex.id === orderToSave.id)) {
          // Already exists, update instead
          const oldOrder = list.find(ex => ex.id === orderToSave.id);
          const oldParts = new Map<string, number>();
          oldOrder?.interventions?.forEach(int => {
              int.additionalItems?.forEach(item => {
                  if (item.inventoryId) {
                      oldParts.set(item.inventoryId, (oldParts.get(item.inventoryId) || 0) + item.quantity);
                  }
              });
          });
          
          const newParts = new Map<string, number>();
          orderToSave.interventions?.forEach(int => {
              int.additionalItems?.forEach(item => {
                  if (item.inventoryId) {
                      newParts.set(item.inventoryId, (newParts.get(item.inventoryId) || 0) + item.quantity);
                  }
              });
          });
          
          partsList = partsList.map(part => {
              const oldQty = oldParts.get(part.id) || 0;
              const newQty = newParts.get(part.id) || 0;
              const diff = newQty - oldQty;
              if (diff !== 0) {
                  api.createStockMovement({
                    partId: part.id,
                    partName: part.name,
                    quantity: -diff,
                    type: diff > 0 ? 'out' : 'in',
                    referenceType: 'ORDER',
                    referenceNumber: orderToSave.orderNumber,
                    notes: `Korrektur Auftrag ${orderToSave.orderNumber}`
                  });
                  return { ...part, quantity: part.quantity - diff };
              }
              return part;
          });
          
          list = list.map(ex => ex.id === orderToSave.id ? orderToSave : ex);
          
          addAuditLog({
            action: 'UPDATE',
            entityType: 'WorkOrder',
            entityId: orderToSave.id,
            details: `Auftrag ${orderToSave.orderNumber} aktualisiert`
          });
      } else {
          // New order
          const newParts = new Map<string, number>();
          orderToSave.interventions?.forEach(int => {
              int.additionalItems?.forEach(item => {
                  if (item.inventoryId) {
                      newParts.set(item.inventoryId, (newParts.get(item.inventoryId) || 0) + item.quantity);
                  }
              });
          });
          
          partsList = partsList.map(part => {
              const qty = newParts.get(part.id) || 0;
              if (qty > 0) {
                  api.createStockMovement({
                    partId: part.id,
                    partName: part.name,
                    quantity: -qty,
                    type: 'out',
                    referenceType: 'ORDER',
                    referenceNumber: orderToSave.orderNumber,
                    notes: `Auftrag ${orderToSave.orderNumber}`
                  });
                  return { ...part, quantity: part.quantity - qty };
              }
              return part;
          });
          
          list.push(orderToSave);
          
          addAuditLog({
            action: 'CREATE',
            entityType: 'WorkOrder',
            entityId: orderToSave.id,
            newValues: orderToSave,
            details: `Auftrag ${orderToSave.orderNumber} erstellt`
          });
      }
      storage.set(DB_KEYS.PARTS, partsList);
      storage.set(DB_KEYS.ORDERS, list);

      // If order is invoiced, decrease customer balance (increase debt)
      if (orderToSave.status === 'invoiced' || orderToSave.status === 'paid' || orderToSave.status === 'partially_paid') {
          await api.updateCustomerBalance(orderToSave.customerId, -orderToSave.totalGross);
      }

      return simulateNetwork(orderToSave);
  },
  updateWorkOrder: async (id: string, data: Partial<WorkOrder>) => {
      let list = storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []);
      let partsList = storage.get<InventoryItem[]>(DB_KEYS.PARTS, []);
      
      const oldOrder = list.find(o => o.id === id);
      if (!oldOrder) return simulateNetwork(false);

      // Recalculate balance and status
      const finalPaidAmount = data.paidAmount ?? oldOrder.paidAmount ?? 0;
      const finalTotalGross = data.totalGross ?? oldOrder.totalGross;
      data.paidAmount = finalPaidAmount;
      data.balance = finalTotalGross - finalPaidAmount;

      if (data.balance <= 0 && (data.status || oldOrder.status) !== 'cancelled') {
          data.status = 'paid';
      } else if (finalPaidAmount > 0 && data.balance > 0 && (data.status || oldOrder.status) !== 'cancelled') {
          data.status = 'partially_paid';
      }

      // Handle balance change if status changes to invoiced/paid/partially_paid
      if (!['invoiced', 'paid', 'partially_paid'].includes(oldOrder.status) && ['invoiced', 'paid', 'partially_paid'].includes(data.status || '')) {
          const total = data.totalGross || oldOrder.totalGross;
          await api.updateCustomerBalance(oldOrder.customerId, -total);
      }

      if (oldOrder && data.interventions) {
          const oldParts = new Map<string, number>();
          oldOrder.interventions?.forEach(int => {
              int.additionalItems?.forEach(item => {
                  if (item.inventoryId) {
                      oldParts.set(item.inventoryId, (oldParts.get(item.inventoryId) || 0) + item.quantity);
                  }
              });
          });
          
          const newParts = new Map<string, number>();
          data.interventions?.forEach(int => {
              int.additionalItems?.forEach(item => {
                  if (item.inventoryId) {
                      newParts.set(item.inventoryId, (newParts.get(item.inventoryId) || 0) + item.quantity);
                  }
              });
          });
          
          partsList = partsList.map(part => {
              const oldQty = oldParts.get(part.id) || 0;
              const newQty = newParts.get(part.id) || 0;
              const diff = newQty - oldQty;
              if (diff !== 0) {
                  api.createStockMovement({
                    partId: part.id,
                    partName: part.name,
                    quantity: -diff,
                    type: diff > 0 ? 'out' : 'in',
                    referenceType: 'ORDER',
                    referenceNumber: oldOrder.orderNumber,
                    notes: `Korrektur Auftrag ${oldOrder.orderNumber}`
                  });
                  return { ...part, quantity: part.quantity - diff };
              }
              return part;
          });
          storage.set(DB_KEYS.PARTS, partsList);
      }
      
      const updatedOrder = { ...oldOrder, ...data, updatedAt: new Date().toISOString(), updatedBy: api.getCurrentUser()?.name || 'System' };
      storage.set(DB_KEYS.ORDERS, list.map(o => o.id === id ? updatedOrder : o));
      
      addAuditLog({
        action: 'UPDATE',
        entityType: 'WorkOrder',
        entityId: id,
        oldValues: oldOrder,
        newValues: updatedOrder,
        details: `Auftrag ${oldOrder.orderNumber} aktualisiert`
      });
      
      return simulateNetwork(true);
  },
  deleteWorkOrder: async (id: string) => {
    let list = storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []);
    let partsList = storage.get<InventoryItem[]>(DB_KEYS.PARTS, []);
    
    const oldOrder = list.find(o => o.id === id);
    if (oldOrder) {
        const oldParts = new Map<string, number>();
        oldOrder.interventions?.forEach(int => {
            int.additionalItems?.forEach(item => {
                if (item.inventoryId) {
                    oldParts.set(item.inventoryId, (oldParts.get(item.inventoryId) || 0) + item.quantity);
                }
            });
        });
        
        partsList = partsList.map(part => {
            const oldQty = oldParts.get(part.id) || 0;
            if (oldQty > 0) {
                api.createStockMovement({
                  partId: part.id,
                  partName: part.name,
                  quantity: oldQty,
                  type: 'in',
                  referenceType: 'ORDER',
                  referenceNumber: oldOrder.orderNumber,
                  notes: `Storno Auftrag ${oldOrder.orderNumber}`
                });
                return { ...part, quantity: part.quantity + oldQty };
            }
            return part;
        });
        storage.set(DB_KEYS.PARTS, partsList);
        
        const deletedOrder = { 
          ...oldOrder, 
          status: 'cancelled' as any, 
          deletedAt: new Date().toISOString(), 
          deletedBy: api.getCurrentUser()?.name || 'System' 
        };
        storage.set(DB_KEYS.ORDERS, list.map(o => o.id === id ? deletedOrder : o));
        
        addAuditLog({
          action: 'DELETE',
          entityType: 'WorkOrder',
          entityId: id,
          details: `Auftrag ${oldOrder.orderNumber} storniert`
        });
    }
    return simulateNetwork(true);
  },
  lockWorkOrder: async (id: string, userId: string) => {
      let list = storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []);
      const order = list.find(o => o.id === id);
      if (!order) return simulateNetwork(false);

      // Check if already locked by someone else
      if (order.lockedBy && order.lockedBy !== userId) {
          // Check if lock is stale (e.g., > 10 minutes)
          const lockTime = order.lockedAt ? new Date(order.lockedAt).getTime() : 0;
          const now = new Date().getTime();
          if (now - lockTime < 10 * 60 * 1000) {
              return simulateNetwork(false); // Still locked
          }
      }

      // Lock it
      order.lockedBy = userId;
      order.lockedAt = new Date().toISOString();
      storage.set(DB_KEYS.ORDERS, list);
      return simulateNetwork(true);
  },
  unlockWorkOrder: async (id: string) => {
      let list = storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []);
      const order = list.find(o => o.id === id);
      if (order) {
          order.lockedBy = undefined;
          order.lockedAt = undefined;
          storage.set(DB_KEYS.ORDERS, list);
      }
      return simulateNetwork(true);
  },
  reopenInvoice: async (id: string) => {
    let list = storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []);
    const order = list.find(o => o.id === id);
    if (order && (order.status === 'invoiced' || order.status === 'paid')) {
        // Revert balance change
        await api.updateCustomerBalance(order.customerId, order.totalGross);
    }
    storage.set(DB_KEYS.ORDERS, list.map(o => o.id === id ? { ...o, status: 'in_progress', invoiceNumber: undefined, completedAt: undefined } : o));
    return simulateNetwork(true);
  },
  updateLoanerStats: async (loanerId: string, mileage: number, fuel: number, damage: string) => {
      let settings = storage.get<SystemSettings>(`${DB_KEYS.SETTINGS}_${currentWorkshopId}`, getDefaultSettings('Werkstatt'));
      const cars = settings.loanerCars || [];
      const updatedCars = cars.map(c => c.id === loanerId ? { ...c, currentMileage: mileage, fuelLevel: fuel, damages: damage } : c);
      settings.loanerCars = updatedCars;
      storage.set(`${DB_KEYS.SETTINGS}_${currentWorkshopId}`, settings);
      return simulateNetwork(true);
  },
  getAppointments: async (dateStr?: string) => {
      const all = storage.get<Appointment[]>(DB_KEYS.APPOINTMENTS, []).filter(a => a.workshopId === currentWorkshopId);
      return simulateNetwork(dateStr ? all.filter(a => a.date === dateStr) : all);
  },
  createAppointment: async (a: Partial<Appointment>) => {
      let list = storage.get<Appointment[]>(DB_KEYS.APPOINTMENTS, []);
      const na = { ...a, id: `ap-${Date.now()}`, workshopId: currentWorkshopId } as Appointment;
      list.push(na);
      storage.set(DB_KEYS.APPOINTMENTS, list);
      return simulateNetwork(na);
  },
  updateAppointment: async (id: string, data: Partial<Appointment>) => {
      let list = storage.get<Appointment[]>(DB_KEYS.APPOINTMENTS, []);
      storage.set(DB_KEYS.APPOINTMENTS, list.map(a => a.id === id ? { ...a, ...data } : a));
      return simulateNetwork(true);
  },
  deleteAppointment: async (id: string) => {
      let list = storage.get<Appointment[]>(DB_KEYS.APPOINTMENTS, []);
      storage.set(DB_KEYS.APPOINTMENTS, list.filter(a => a.id !== id));
      return simulateNetwork(true);
  },
  generateReminderEmail: (appointment: Appointment, customSettings?: SystemSettings) => {
      const settings = customSettings || storage.get<SystemSettings>(DB_KEYS.SETTINGS, {} as SystemSettings);
      
      const defaultSubject = `Terminerinnerung: Ihr Werkstatt-Termin am [Datum]`;
      const defaultTemplate = `Sehr geehrte(r) [Kundenname],\n\ndies ist eine freundliche Erinnerung an Ihren bevorstehenden Werkstatt-Termin in unserem Hause:\n\nDatum: [Datum]\nUhrzeit: [Uhrzeit] Uhr\nFahrzeug: [Kennzeichen]\nLeistung: [Leistung]\n\nSollten Sie den Termin nicht wahrnehmen können, bitten wir um eine kurze Nachricht.\n\nWir freuen uns auf Ihren Besuch!\n\nMit freundlichen Grüßen\nIhr Werkstatt-Team`;

      let subject = settings.reminderEmailSubject || defaultSubject;
      let body = settings.reminderEmailTemplate || defaultTemplate;

      const replacements: Record<string, string> = {
          '[Kundenname]': appointment.customerName,
          '[Datum]': appointment.date,
          '[Uhrzeit]': appointment.startTime,
          '[Kennzeichen]': appointment.licensePlate || 'Unbekannt',
          '[Leistung]': appointment.title
      };

      Object.entries(replacements).forEach(([key, value]) => {
          subject = subject.replace(new RegExp(key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), value);
          body = body.replace(new RegExp(key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), value);
      });

      return { subject, body };
  },
  processAppointmentReminders: async () => {
      const all = storage.get<Appointment[]>(DB_KEYS.APPOINTMENTS, []);
      const settings = storage.get<SystemSettings>(DB_KEYS.SETTINGS, {} as SystemSettings);
      const now = new Date();
      let updated = false;
      
      // Default to 24 hours if not set
      const leadTimeHours = settings.reminderLeadTime || 24;
      
      const newList = all.map(a => {
          if (!a.reminderSent && a.status === 'scheduled') {
              const [hours, minutes] = a.startTime.split(':').map(Number);
              const apptDate = new Date(a.date);
              apptDate.setHours(hours, minutes, 0, 0);
              
              const diffMs = apptDate.getTime() - now.getTime();
              const diffHours = diffMs / (1000 * 60 * 60);
              
              if (diffHours > 0 && diffHours <= leadTimeHours) {
                  const { subject, body } = api.generateReminderEmail(a);
                  const logMsg = `Automatische Terminerinnerung an ${a.customerName} gesendet.`;
                  console.log(`[System] ${logMsg}\nBetreff: ${subject}\nInhalt:\n${body}`);
                  
                  // Add to system logs
                  api.addLog('system', 'Terminerinnerung', `${logMsg} (Betreff: ${subject})`);
                  
                  updated = true;
                  return { ...a, reminderSent: true };
              }
          }
          return a;
      });

      if (updated) {
          storage.set(DB_KEYS.APPOINTMENTS, newList);
      }
      return simulateNetwork(updated);
  },
  getTechnicians: async () => {
      let list = storage.get<Technician[]>(DB_KEYS.TECHNICIANS, []);
      const currentUser = api.getCurrentUser();
      const isSuperAdmin = currentUser?.role_id === 0;

      const initialTechs = [
        { id: 't1', name: 'Max (Meister)', color: '#ef4444', workshopId: 'W1', workingHours: defaultWorkingHours, liftId: 'lift-1', defaultPauseMinutes: 60 },
        { id: 't2', name: 'Lisa (Geselle)', color: '#f59e0b', workshopId: 'W1', workingHours: defaultWorkingHours, liftId: 'lift-2', defaultPauseMinutes: 60 },
        { id: 't3', name: 'Alex (Azubi)', color: '#10b981', workshopId: 'W1', workingHours: defaultWorkingHours, liftId: undefined, defaultPauseMinutes: 60 },
        { id: 't4', name: 'Bernd (Mechaniker)', color: '#3b82f6', workshopId: 'W1', workingHours: defaultWorkingHours, liftId: 'lift-3', defaultPauseMinutes: 60 },
        { id: 't5', name: 'Julia (Verkauf)', color: '#8b5cf6', workshopId: 'W1', workingHours: defaultWorkingHours, defaultPauseMinutes: 45 },
        { id: 't6', name: 'Peter (Service)', color: '#06b6d4', workshopId: 'W1', workingHours: defaultWorkingHours, defaultPauseMinutes: 45 },
        { id: 't7', name: 'Hans (Lager)', color: '#d97706', workshopId: 'W1', workingHours: defaultWorkingHours, defaultPauseMinutes: 45 },
        { id: 't_global', name: 'Global Admin', color: '#111827', workshopId: 'W1', workingHours: defaultWorkingHours, defaultPauseMinutes: 60 },
        { id: 't_admin', name: 'Admin (Chef)', color: '#4b5563', workshopId: 'W1', workingHours: defaultWorkingHours, defaultPauseMinutes: 60 },
        { id: 't_tom', name: 'Tom (Verkauf)', color: '#8b5cf6', workshopId: 'W1', workingHours: defaultWorkingHours, defaultPauseMinutes: 45 },
        { id: 't_anna', name: 'Anna (Service)', color: '#06b6d4', workshopId: 'W1', workingHours: defaultWorkingHours, defaultPauseMinutes: 45 },
        { id: 't_klaus', name: 'Klaus (Lager)', color: '#d97706', workshopId: 'W1', workingHours: defaultWorkingHours, defaultPauseMinutes: 45 }
      ];

      // Merge missing defaults
      let changed = false;
      initialTechs.forEach(def => {
          if (!list.find(t => t.id === def.id)) {
              list.push(def);
              changed = true;
          }
      });
      
      if (changed) {
          storage.set(DB_KEYS.TECHNICIANS, list);
      }

      return simulateNetwork(list.filter(t => t.workshopId === currentWorkshopId));
  },
  updateTechnician: async (id: string, data: Partial<Technician>) => {
      let list = storage.get<Technician[]>(DB_KEYS.TECHNICIANS, []);
      storage.set(DB_KEYS.TECHNICIANS, list.map(t => t.id === id ? { ...t, ...data } : t));
      return simulateNetwork(true);
  },
  createTechnician: async (data: Partial<Technician>) => {
      let list = storage.get<Technician[]>(DB_KEYS.TECHNICIANS, []);
      const nt = { 
          ...data, 
          id: `t-${Date.now()}`, 
          workshopId: data.workshopId || currentWorkshopId,
          workingHours: data.workingHours || defaultWorkingHours,
          vacationDaysPerYear: data.vacationDaysPerYear || 30,
          remainingVacationDays: data.remainingVacationDays || 30,
          absences: []
      } as Technician;
      list.push(nt);
      storage.set(DB_KEYS.TECHNICIANS, list);
      return simulateNetwork(nt);
  },
  deleteTechnician: async (id: string) => {
      let list = storage.get<Technician[]>(DB_KEYS.TECHNICIANS, []);
      storage.set(DB_KEYS.TECHNICIANS, list.map(t => t.id === id ? { ...t, active: false } : t));
      
      let userList = storage.get<SystemUser[]>(DB_KEYS.USERS, []);
      storage.set(DB_KEYS.USERS, userList.map(u => u.technicianId === id ? { ...u, active: false } : u));
      
      return simulateNetwork(true);
  },
  getSystemUsers: async () => {
      let list = storage.get<SystemUser[]>(DB_KEYS.USERS, []);
      
      // Ensure all mock users exist in the list
      let changed = false;
      MOCK_SYSTEM_USERS.forEach(mock => {
          const existing = list.find(u => u.id === mock.id);
          if (!existing) {
              list.push(mock);
              changed = true;
          } else if (!existing.technicianId || !existing.role_id) {
              // Update existing if missing critical fields
              const idx = list.indexOf(existing);
              list[idx] = { ...existing, technicianId: mock.technicianId, role_id: mock.role_id };
              changed = true;
          }
      });

      if (changed) {
          storage.set(DB_KEYS.USERS, list);
      }

      return simulateNetwork(list.filter(u => u.workshop_id === currentWorkshopId));
  },
  deleteSystemUser: async (id: number) => {
    let list = storage.get<SystemUser[]>(DB_KEYS.USERS, []);
    storage.set(DB_KEYS.USERS, list.filter(u => u.id !== id));
    return simulateNetwork(true);
  },
  updateSystemUser: async (id: number, data: Partial<SystemUser>) => {
    let list = storage.get<SystemUser[]>(DB_KEYS.USERS, []);
    storage.set(DB_KEYS.USERS, list.map(u => u.id === id ? { ...u, ...data } : u));
    return simulateNetwork(true);
  },
  createSystemUser: async (data: Partial<SystemUser>) => {
    let list = storage.get<SystemUser[]>(DB_KEYS.USERS, []);
    
    // Generate OTP if no password is provided
    const otp = data.password || Math.random().toString(36).slice(-8);
    
    const nu = { 
        ...data, 
        id: Date.now(),
        password: otp,
        mustChangePassword: true
    } as SystemUser;
    
    list.push(nu);
    storage.set(DB_KEYS.USERS, list);
    
    // Simulate sending email
    console.log(`[EMAIL SIMULATION] An: ${nu.email}`);
    console.log(`Betreff: Ihr neues Konto`);
    console.log(`Hallo ${nu.username},\n\nIhr Konto wurde erstellt. Ihr Einmalpasswort lautet: ${otp}\nBitte ändern Sie dieses nach dem ersten Login.`);
    
    // We can also show an alert to the user so they know the OTP for testing
    if (typeof window !== 'undefined') {
        alert(`Mitarbeiter angelegt!\n\nEinmalpasswort für ${nu.username}: ${otp}\n\n(In einer echten App würde dies per E-Mail an ${nu.email} gesendet werden)`);
    }

    return simulateNetwork(nu);
  },
  getShiftStatus: async (uid: number) => {
      const es = storage.get<TimeEntry[]>(DB_KEYS.TIME_ENTRIES, []);
      return simulateNetwork(es.find(e => e.userId === uid && e.type === 'shift' && !e.endTime));
  },
  clockIn: async (uid: number) => {
      let es = storage.get<TimeEntry[]>(DB_KEYS.TIME_ENTRIES, []);
      const now = new Date();
      const ne = { 
          id: `te-${Date.now()}`, 
          userId: uid, 
          date: format(now, 'yyyy-MM-dd'),
          startTime: now.toISOString(), 
          type: 'shift' 
      } as TimeEntry;
      es.push(ne);
      storage.set(DB_KEYS.TIME_ENTRIES, es);
      return simulateNetwork(ne);
  },
  clockOut: async (uid: number) => {
      let es = storage.get<TimeEntry[]>(DB_KEYS.TIME_ENTRIES, []);
      const e = es.find(x => x.userId === uid && !x.endTime);
      if(e) e.endTime = new Date().toISOString();
      storage.set(DB_KEYS.TIME_ENTRIES, es);
      return simulateNetwork(true);
  },
  getAllTimeEntries: async () => simulateNetwork(storage.get<TimeEntry[]>(DB_KEYS.TIME_ENTRIES, [])),
  createTimeEntry: async (entry: Partial<TimeEntry>) => {
      let list = storage.get<TimeEntry[]>(DB_KEYS.TIME_ENTRIES, []);
      const newEntry = { ...entry, id: `te-${Date.now()}` } as TimeEntry;
      list.push(newEntry);
      storage.set(DB_KEYS.TIME_ENTRIES, list);
      return simulateNetwork(newEntry);
  },
  updateTimeEntry: async (id: string, data: Partial<TimeEntry>) => {
      let list = storage.get<TimeEntry[]>(DB_KEYS.TIME_ENTRIES, []);
      storage.set(DB_KEYS.TIME_ENTRIES, list.map(e => e.id === id ? { ...e, ...data } : e));
      return simulateNetwork(true);
  },
  deleteTimeEntry: async (id: string) => {
      let list = storage.get<TimeEntry[]>(DB_KEYS.TIME_ENTRIES, []);
      storage.set(DB_KEYS.TIME_ENTRIES, list.filter(e => e.id !== id));
      return simulateNetwork(true);
  },
  getInventorySessions: async () => simulateNetwork(storage.get<InventorySession[]>(DB_KEYS.SESSIONS, []).filter(s => s.workshopId === currentWorkshopId)),
  
  isInventoryActive: async () => {
    const sessions = storage.get<InventorySession[]>(DB_KEYS.SESSIONS, []);
    return sessions.some(s => s.status === 'open' && s.workshopId === currentWorkshopId);
  },

  createInventorySession: async (season: SeasonType, user: string) => {
    const records = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []).filter(r => r.season === season && r.status !== StorageStatus.PICKED_UP && r.workshopId === currentWorkshopId);
    const ns: InventorySession = { 
      id: `sess-${Date.now()}`, 
      sessionNumber: getNextNumber('inventory'),
      name: `${season} ${new Date().getFullYear()}`, 
      token: Math.random().toString(36).substr(2, 12), 
      season, 
      createdAt: new Date().toISOString(), 
      validUntil: '2025-12-31', 
      createdBy: user, 
      status: 'open', 
      totalItems: records.length, 
      scannedItems: 0, 
      scannedRecordIds: [], 
      workshopId: currentWorkshopId 
    };
    let list = storage.get<InventorySession[]>(DB_KEYS.SESSIONS, []); 
    list.push(ns); 
    storage.set(DB_KEYS.SESSIONS, list); 
    
    addAuditLog({
      action: 'CREATE',
      entityType: 'InventorySession',
      entityId: ns.id,
      newValues: ns,
      details: `Inventur-Sitzung ${ns.sessionNumber} gestartet`
    });
    
    return simulateNetwork(ns);
  },
  closeInventorySession: async (id: string) => {
    let list = storage.get<InventorySession[]>(DB_KEYS.SESSIONS, []);
    storage.set(DB_KEYS.SESSIONS, list.map(s => s.id === id ? { ...s, status: 'closed' } : s));
    return simulateNetwork(true);
  },
  getInventoryByToken: async (token: string) => {
    const s = storage.get<InventorySession[]>(DB_KEYS.SESSIONS, []).find(x => x.token === token);
    if (!s) throw new Error("Ungültig");
    const r = storage.get<StorageRecord[]>(DB_KEYS.RECORDS, []).filter(x => x.season === s.season && x.workshopId === s.workshopId);
    return simulateNetwork({ session: s, records: r });
  },
  scanItem: async (token: string, recordId: string, scanned: boolean) => {
    let sessions = storage.get<InventorySession[]>(DB_KEYS.SESSIONS, []);
    const idx = sessions.findIndex(s => s.token === token);
    if (idx === -1) throw new Error("Not found");
    let s = { ...sessions[idx] };
    if (scanned) { if (!s.scannedRecordIds.includes(recordId)) s.scannedRecordIds.push(recordId); }
    else { s.scannedRecordIds = s.scannedRecordIds.filter(id => id !== recordId); }
    s.scannedItems = s.scannedRecordIds.length;
    sessions[idx] = s;
    storage.set(DB_KEYS.SESSIONS, sessions);
    return simulateNetwork(s);
  },
  getTransactions: async () => simulateNetwork(storage.get<CashTransaction[]>(DB_KEYS.TRANSACTIONS, [])),
  createTransaction: async (data: Partial<CashTransaction>) => {
    let list = storage.get<CashTransaction[]>(DB_KEYS.TRANSACTIONS, []);
    const nt = { ...data, id: `tx-${Date.now()}`, timestamp: new Date().toISOString(), user: api.getCurrentUser()?.name || 'System' } as CashTransaction;
    list.push(nt);
    storage.set(DB_KEYS.TRANSACTIONS, list);
    
    if (data.orderId && data.type === 'income') {
        let orders = storage.get<WorkOrder[]>(DB_KEYS.ORDERS, []);
        const orderIdx = orders.findIndex(o => o.id === data.orderId);
        if (orderIdx !== -1) {
            const order = { ...orders[orderIdx] };
            const paymentAmount = data.amount || 0;
            
            // Update paidAmount and balance
            order.paidAmount = Math.round(((order.paidAmount || 0) + paymentAmount) * 100) / 100;
            order.balance = Math.round((order.totalGross - order.paidAmount) * 100) / 100;
            
            // Update status based on balance
            if (order.balance <= 0) {
                order.status = 'paid';
            } else if (order.paidAmount > 0) {
                order.status = 'partially_paid';
            }
            
            orders[orderIdx] = order;
            storage.set(DB_KEYS.ORDERS, orders);
            
            // Update customer balance (payment reduces debt)
            await api.updateCustomerBalance(order.customerId, paymentAmount);
        }
    }
    return simulateNetwork(nt);
  },
  performCashOpening: async (balance: number, count: CashCount) => {
    const o: CashOpening = { id: `op-${Date.now()}`, timestamp: new Date().toISOString(), user: api.getCurrentUser()?.name || 'System', startBalance: balance, cashCount: count };
    let list = storage.get<CashOpening[]>(DB_KEYS.OPENINGS, []); list.unshift(o); storage.set(DB_KEYS.OPENINGS, list); storage.set(DB_KEYS.REG_STATUS, 'open'); return simulateNetwork(o);
  },
  performCashClosing: async (balance: number, count: CashCount) => {
    const txs = storage.get<CashTransaction[]>(DB_KEYS.TRANSACTIONS, []);
    const pending = txs.filter(t => !t.closingId);
    const inc = pending.filter(t => t.type === 'income').reduce((s,t) => s + t.amount, 0);
    const exp = pending.filter(t => t.type === 'expense').reduce((s,t) => s + t.amount, 0);
    const latestOp = storage.get<CashOpening[]>(DB_KEYS.OPENINGS, [])[0];
    const c: CashClosing = { id: `cl-${Date.now()}`, timestamp: new Date().toISOString(), user: api.getCurrentUser()?.name || 'System', startBalance: latestOp?.startBalance || 0, endBalance: balance, totalIncome: inc, totalExpense: exp, transactionIds: pending.map(t => t.id), cashCount: count };
    let list = storage.get<CashClosing[]>(DB_KEYS.CLOSINGS, []); list.unshift(c); storage.set(DB_KEYS.CLOSINGS, list); storage.set(DB_KEYS.REG_STATUS, 'closed');
    storage.set(DB_KEYS.TRANSACTIONS, txs.map(t => !t.closingId ? { ...t, closingId: c.id } : t));
    return simulateNetwork(c);
  },
  getRegisterStatus: async () => simulateNetwork(storage.get<'open' | 'closed'>(DB_KEYS.REG_STATUS, 'closed')),
  getCashClosings: async () => simulateNetwork(storage.get<CashClosing[]>(DB_KEYS.CLOSINGS, [])),
  getCashOpenings: async () => simulateNetwork(storage.get<CashOpening[]>(DB_KEYS.OPENINGS, [])),
  getUsers: async (): Promise<SystemUser[]> => {
    return simulateNetwork(storage.get<SystemUser[]>(DB_KEYS.USERS, []));
  },
  getNews: async () => {
    let list = storage.get<NewsEntry[]>(DB_KEYS.NEWS, []);
    if (list.length === 0) {
      list = [...MOCK_NEWS];
      storage.set(DB_KEYS.NEWS, list);
    }
    return simulateNetwork(list);
  },
  createNews: async (data: Partial<NewsEntry>) => {
    let list = storage.get<NewsEntry[]>(DB_KEYS.NEWS, []);
    const ne = { ...data, id: `n-${Date.now()}`, date: new Date().toISOString() } as NewsEntry;
    list.unshift(ne); storage.set(DB_KEYS.NEWS, list); return simulateNetwork(ne);
  }
};