/**
 * BiometricSyncController - Controlador de Sincronizacion Biometrica
 *
 * Endpoints para sincronizacion de dispositivos y registros de asistencia.
 *
 * @module Biometrics
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { BiometricSyncService } from '../services';

export function createBiometricSyncController(dataSource: DataSource): Router {
  const router = Router();
  const service = new BiometricSyncService(dataSource);

  // ==================== DEVICE SYNC ====================

  /**
   * POST /device
   * Sincroniza un dispositivo con el servidor
   */
  router.post('/device', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      const result = await service.syncDevice(tenantId, req.body);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /devices/bulk
   * Sincroniza multiples dispositivos (operacion batch)
   */
  router.post('/devices/bulk', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { requests } = req.body;

      if (!requests || !Array.isArray(requests)) {
        res.status(400).json({ error: 'Se requiere un array de requests' });
        return;
      }

      const results = await service.bulkDeviceSync(tenantId, requests);

      // Convert Map to object for JSON serialization
      const response: Record<string, any> = {};
      results.forEach((value, key) => {
        response[key] = value;
      });

      res.json(response);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /user/:userId/force-sync
   * Fuerza sincronizacion de todos los dispositivos de un usuario
   */
  router.post('/user/:userId/force-sync', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      const result = await service.forceSyncUserDevices(tenantId, req.params.userId);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  // ==================== ATTENDANCE SYNC ====================

  /**
   * POST /attendance
   * Sincroniza registros de asistencia desde un dispositivo
   */
  router.post('/attendance', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { deviceId, records } = req.body;

      if (!deviceId) {
        res.status(400).json({ error: 'Se requiere deviceId' });
        return;
      }

      if (!records || !Array.isArray(records)) {
        res.status(400).json({ error: 'Se requiere un array de records' });
        return;
      }

      const result = await service.syncAttendanceRecords(tenantId, deviceId, records);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  // ==================== OFFLINE SUPPORT ====================

  /**
   * POST /offline/token
   * Genera un token para autenticacion offline
   */
  router.post('/offline/token', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { deviceId, credentialId } = req.body;

      if (!deviceId || !credentialId) {
        res.status(400).json({ error: 'Se requieren deviceId y credentialId' });
        return;
      }

      const token = await service.generateOfflineToken(tenantId, deviceId, credentialId);
      if (!token) {
        res.status(403).json({ error: 'El dispositivo no tiene permisos para autenticacion offline' });
        return;
      }

      res.json(token);
    } catch (error) {
      next(error);
    }
  });

  /**
   * POST /offline/validate
   * Valida una autenticacion offline
   */
  router.post('/offline/validate', async (req: Request, res: Response): Promise<void> => {
    try {
      const { deviceId, token, signature } = req.body;

      if (!deviceId || !token || !signature) {
        res.status(400).json({ error: 'Se requieren deviceId, token y signature' });
        return;
      }

      const result = await service.validateOfflineAuth(deviceId, token, signature);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  // ==================== HEALTH & DIAGNOSTICS ====================

  /**
   * GET /health
   * Obtiene el estado de salud del sistema de sincronizacion
   */
  router.get('/health', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      const health = await service.getSyncHealth(tenantId);
      res.json(health);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  return router;
}
