import { ipcMain } from 'electron';
import { createHandler } from '../database/LocalSystem.js';
import * as bcrypt from 'bcrypt';
import SecureStorage, { getSecureStorage } from '../storage/SecureStorage.js';
import { getDatabaseService } from '../database/database.service.js';

interface SetPinData {
  pin: string;
}

interface VerifyPinData {
  pin: string;
}

interface OfflineModeData {
  enabled: boolean;
  syncInterval?: number; // days
}

ipcMain.handle('offline:pin:set', async (_event, data: SetPinData) => {
  try {
    const storage: SecureStorage = getSecureStorage();
    const userId: string | null = storage.get<string>('userId');

    if (!userId) {
      return { success: false, error: 'No user logged in' };
    }
    
    const hashedPin: string = await bcrypt.hash(data.pin, 10);

    // Store hashed PIN
    storage.set(`pin-${userId}`, hashedPin);
    storage.save();
    return { success: true };
  } catch (error) {
    console.error('[Offline] Error setting PIN:', error);
    return { success: false, error: error instanceof Error ? error.message : 'Unknown error' };
  }
});

// Verify PIN for offline access
ipcMain.handle('offline:pin:verify', async (_event, data: VerifyPinData) => {
  try {
    const storage = getSecureStorage();

    // Try to get last known userId
    const lastUserId = storage.get<string>('lastUserId');
    if (!lastUserId) {
      return { success: false, error: 'No offline account found' };
    }

    const hashedPin = storage.get<string>(`pin-${lastUserId}`);
    if (!hashedPin) {
      return { success: false, error: 'No PIN configured' };
    }

    // Verify PIN
    const isValid = await bcrypt.compare(data.pin, hashedPin);

    if (isValid) {
      // Set userId for session
      storage.set('userId', lastUserId);

      // Initialize database for offline use
      const encryptionKey = storage.get<string>(`encryptionKey-${lastUserId}`);
      if (encryptionKey) {
        const db = getDatabaseService();
        db.initialize(lastUserId, encryptionKey);
      } else {
        console.error('[Offline] No encryption key found for user');
        return { success: false, error: 'No encryption key found' };
      }
      
      return {
        success: true,
        userId: lastUserId
      };
    }

    return { success: false, error: 'Invalid PIN' };
  } catch (error) {
    console.error('[Offline] Error verifying PIN:', error);
    return { success: false, error: error instanceof Error ? error.message : 'Unknown error' };
  }
});

// Set offline mode preference
ipcMain.handle('offline:mode:set', (_event, data: OfflineModeData) => {
  try {
    const storage = getSecureStorage();
    storage.set('offlineMode', data.enabled);

    if (data.syncInterval) {
      storage.set('syncInterval', data.syncInterval);
    }

    storage.save();

    return { success: true };
  } catch (error) {
    console.error('[Offline] Error setting mode:', error);
    return { success: false, error: error instanceof Error ? error.message : 'Unknown error' };
  }
});

// Get offline mode status
ipcMain.handle('offline:mode:get', () => {
  try {
    const storage = getSecureStorage();
    const offlineMode = storage.get<boolean>('offlineMode', false);
    const syncInterval = storage.get<number>('syncInterval', 30);
    const lastUserId = storage.get<string>('lastUserId');
    const hasPin = lastUserId ? !!storage.get<string>(`pin-${lastUserId}`) : false;

    return {
      enabled: offlineMode,
      syncInterval,
      hasPin,
      lastUserId
    };
  } catch (error) {
    console.error('[Offline] Error getting mode:', error);
    return {
      enabled: false,
      syncInterval: 30,
      hasPin: false
    };
  }
});

// Check if should sync
ipcMain.handle('offline:sync:check', () => {
  try {
    const storage = getSecureStorage();
    const lastSync = storage.get<string>('lastSync');
    const syncInterval = storage.get<number>('syncInterval', 30) || 30;

    if (!lastSync) {
      return { shouldSync: true };
    }

    const daysSinceSync = Math.floor(
      (Date.now() - new Date(lastSync).getTime()) / (1000 * 60 * 60 * 24)
    );

    return {
      shouldSync: daysSinceSync >= syncInterval,
      daysSinceSync,
      syncInterval
    };
  } catch (error) {
    console.error('[Offline] Error checking sync:', error);
    return { shouldSync: false };
  }
});