import { app, BrowserWindow, ipcMain, nativeImage, protocol } from 'electron';
import * as path from 'path';
import * as url from 'url';
import { fileURLToPath } from 'url';
import Store from 'electron-store';
import * as fs from 'fs';
import { getDatabaseService } from './database/database.service.js';

// Fix pour __dirname en ES modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const isDev = !app.isPackaged;

// Enregistrer le protocole app:// comme standard (avant app.whenReady)
if (!isDev) {
  protocol.registerSchemesAsPrivileged([
    {
      scheme: 'app',
      privileges: {
        standard: true,
        secure: true,
        supportFetchAPI: true,
        corsEnabled: true
      }
    }
  ]);
}

// Définir le nom de l'application
app.setName('ERitors Scribe');

// En dev et prod, __dirname pointe vers dist/electron/
const preloadPath = path.join(__dirname, 'preload.js');

// Icône de l'application
const iconPath = isDev
  ? path.join(__dirname, '../build/icon.png')
  : process.platform === 'darwin'
    ? path.join(process.resourcesPath, 'icon.icns')  // macOS utilise .icns
    : path.join(process.resourcesPath, 'app.asar/build/icon.png');  // Windows/Linux utilisent .png

// Store sécurisé pour le token
const store = new Store({
  encryptionKey: 'eritors-scribe-secure-key' // En production, utiliser une clé générée
});

let mainWindow: BrowserWindow | null = null;
let loginWindow: BrowserWindow | null = null;

function createLoginWindow(): void {
  loginWindow = new BrowserWindow({
    width: 500,
    height: 900,
    resizable: false,
    // Ne pas définir icon sur macOS - utilise l'icône de l'app bundle
    ...(process.platform !== 'darwin' && { icon: iconPath }),
    webPreferences: {
      preload: preloadPath,
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
    },
    frame: true,
    show: false,
  });

  if (isDev) {
    const devPort = process.env.PORT || '4000';
    loginWindow.loadURL(`http://localhost:${devPort}/login/login`);
    loginWindow.webContents.openDevTools();
  } else {
    loginWindow.loadURL('app://./login/login/index.html');
  }

  loginWindow.once('ready-to-show', () => {
    loginWindow?.show();
  });

  loginWindow.on('closed', () => {
    loginWindow = null;
  });
}

function createMainWindow(): void {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    // Ne pas définir icon sur macOS - utilise l'icône de l'app bundle
    ...(process.platform !== 'darwin' && { icon: iconPath }),
    webPreferences: {
      preload: preloadPath,
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
    },
    show: false,
  });

  if (isDev) {
    const devPort = process.env.PORT || '4000';
    mainWindow.loadURL(`http://localhost:${devPort}`);
    mainWindow.webContents.openDevTools();
  } else {
    mainWindow.loadURL('app://./index.html');
  }

  mainWindow.once('ready-to-show', () => {
    mainWindow?.show();
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

// IPC Handlers pour la gestion du token
ipcMain.handle('get-token', () => {
  return store.get('authToken', null);
});

ipcMain.handle('set-token', (_event, token: string) => {
  store.set('authToken', token);
  return true;
});

ipcMain.handle('remove-token', () => {
  store.delete('authToken');
  return true;
});

ipcMain.on('login-success', (_event, token: string) => {
  store.set('authToken', token);

  if (loginWindow) {
    loginWindow.close();
  }

  createMainWindow();
});

ipcMain.on('logout', () => {
  store.delete('authToken');

  // Close database connection
  const db = getDatabaseService();
  db.close();

  if (mainWindow) {
    mainWindow.close();
  }

  createLoginWindow();
});

// ========== DATABASE IPC HANDLERS ==========

/**
 * Generate user encryption key
 */
ipcMain.handle('generate-encryption-key', async (_event, userId: string) => {
  try {
    // Import encryption module dynamically
    const { generateUserEncryptionKey } = await import('./database/encryption.js');
    const key = generateUserEncryptionKey(userId);
    return { success: true, key };
  } catch (error) {
    console.error('Failed to generate encryption key:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Get or generate user encryption key
 */
ipcMain.handle('get-user-encryption-key', (_event, userId: string) => {
  const key = store.get(`encryptionKey-${userId}`, null);
  return key;
});

/**
 * Store user encryption key
 */
ipcMain.handle('set-user-encryption-key', (_event, userId: string, encryptionKey: string) => {
  store.set(`encryptionKey-${userId}`, encryptionKey);
  return true;
});

/**
 * Initialize database for user
 */
ipcMain.handle('db-initialize', (_event, userId: string, encryptionKey: string) => {
  try {
    const db = getDatabaseService();
    db.initialize(userId, encryptionKey);
    return { success: true };
  } catch (error) {
    console.error('Failed to initialize database:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Get all books
 */
ipcMain.handle('db-get-books', () => {
  try {
    const db = getDatabaseService();
    const books = db.getBooks();
    return { success: true, data: books };
  } catch (error) {
    console.error('Failed to get books:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Get single book with all data
 */
ipcMain.handle('db-get-book', (_event, bookId: string) => {
  try {
    const db = getDatabaseService();
    const book = db.getBook(bookId);
    return { success: true, data: book };
  } catch (error) {
    console.error('Failed to get book:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Save book
 */
ipcMain.handle('db-save-book', (_event, book: any, authorId?: string) => {
  try {
    const db = getDatabaseService();
    db.saveBook(book, authorId);
    return { success: true };
  } catch (error) {
    console.error('Failed to save book:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Delete book
 */
ipcMain.handle('db-delete-book', (_event, bookId: string) => {
  try {
    const db = getDatabaseService();
    db.deleteBook(bookId);
    return { success: true };
  } catch (error) {
    console.error('Failed to delete book:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Save chapter
 */
ipcMain.handle('db-save-chapter', (_event, chapter: any, bookId: string, contentId?: string) => {
  try {
    const db = getDatabaseService();
    db.saveChapter(chapter, bookId, contentId);
    return { success: true };
  } catch (error) {
    console.error('Failed to save chapter:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Get characters for a book
 */
ipcMain.handle('db-get-characters', (_event, bookId: string) => {
  try {
    const db = getDatabaseService();
    const characters = db.getCharacters(bookId);
    return { success: true, data: characters };
  } catch (error) {
    console.error('Failed to get characters:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Save character
 */
ipcMain.handle('db-save-character', (_event, character: any, bookId: string) => {
  try {
    const db = getDatabaseService();
    db.saveCharacter(character, bookId);
    return { success: true };
  } catch (error) {
    console.error('Failed to save character:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Get AI conversations for a book
 */
ipcMain.handle('db-get-conversations', (_event, bookId: string) => {
  try {
    const db = getDatabaseService();
    const conversations = db.getConversations(bookId);
    return { success: true, data: conversations };
  } catch (error) {
    console.error('Failed to get conversations:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Save AI conversation
 */
ipcMain.handle('db-save-conversation', (_event, conversation: any, bookId: string) => {
  try {
    const db = getDatabaseService();
    db.saveConversation(conversation, bookId);
    return { success: true };
  } catch (error) {
    console.error('Failed to save conversation:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Get sync status
 */
ipcMain.handle('db-get-sync-status', () => {
  try {
    const db = getDatabaseService();
    const status = db.getSyncStatus();
    return { success: true, data: status };
  } catch (error) {
    console.error('Failed to get sync status:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

/**
 * Get pending changes
 */
ipcMain.handle('db-get-pending-changes', (_event, limit: number = 100) => {
  try {
    const db = getDatabaseService();
    const changes = db.getPendingChanges(limit);
    return { success: true, data: changes };
  } catch (error) {
    console.error('Failed to get pending changes:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
});

app.whenReady().then(() => {
  console.log('App ready, isDev:', isDev);
  console.log('resourcesPath:', process.resourcesPath);
  console.log('isPackaged:', app.isPackaged);

  // Enregistrer le protocole custom app:// pour servir les fichiers depuis out/
  if (!isDev) {
    const outPath = path.join(process.resourcesPath, 'app.asar.unpacked/out');

    protocol.handle('app', async (request) => {
      // Enlever app:// et ./
      let filePath = request.url.replace('app://', '').replace(/^\.\//, '');
      const fullPath = path.normalize(path.join(outPath, filePath));

      // Vérifier que le chemin est bien dans out/ (sécurité)
      if (!fullPath.startsWith(outPath)) {
        console.error('Security: Attempted to access file outside out/:', fullPath);
        return new Response('Forbidden', { status: 403 });
      }

      try {
        const data = await fs.promises.readFile(fullPath);
        const ext = path.extname(fullPath).toLowerCase();
        const mimeTypes: Record<string, string> = {
          '.html': 'text/html',
          '.css': 'text/css',
          '.js': 'application/javascript',
          '.json': 'application/json',
          '.png': 'image/png',
          '.jpg': 'image/jpeg',
          '.svg': 'image/svg+xml',
          '.ico': 'image/x-icon',
          '.woff': 'font/woff',
          '.woff2': 'font/woff2',
          '.ttf': 'font/ttf',
        };

        return new Response(data, {
          headers: { 'Content-Type': mimeTypes[ext] || 'application/octet-stream' }
        });
      } catch (error) {
        console.error('Failed to load:', fullPath, error);
        return new Response('Not found', { status: 404 });
      }
    });
  }

  // Définir l'icône du Dock sur macOS
  if (process.platform === 'darwin' && app.dock) {
    const icon = nativeImage.createFromPath(iconPath);
    app.dock.setIcon(icon);
  }

  // Vérifier si un token existe
  const token = store.get('authToken');
  console.log('Token exists:', !!token);

  if (token) {
    // Token existe, ouvrir la fenêtre principale
    createMainWindow();
  } else {
    // Pas de token, ouvrir la fenêtre de login
    createLoginWindow();
  }

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      const token = store.get('authToken');
      if (token) {
        createMainWindow();
      } else {
        createLoginWindow();
      }
    }
  });
});

app.on('window-all-closed', () => {
  // Quitter l'application quand toutes les fenêtres sont fermées
  app.quit();
});
