import { Response, NextFunction } from 'express';
import { AuthenticatedRequest, ApiResponse, NotFoundError } from '../../shared/types/index.js';
import { BiometricsService } from './services/biometrics.service.js';

/**
 * BiometricsController - Controller de solo lectura para biometricos
 *
 * Endpoints GET only:
 * - GET /api/v1/biometrics/devices - Listar dispositivos del usuario
 * - GET /api/v1/biometrics/devices/:deviceId - Obtener dispositivo por ID
 * - GET /api/v1/biometrics/credentials - Listar credenciales del usuario
 * - GET /api/v1/biometrics/credentials/:credentialId - Obtener credencial por ID
 * - GET /api/v1/biometrics/enrollment/status - Estado de enrollment
 * - GET /api/v1/biometrics/sessions - Listar sesiones del usuario
 * - GET /api/v1/biometrics/sessions/active - Sesiones activas
 * - GET /api/v1/biometrics/activity - Log de actividad
 * - GET /api/v1/biometrics/activity/stats - Estadisticas de verificacion
 */
export class BiometricsController {
  constructor(private readonly biometricsService: BiometricsService) {}

  // ============================================
  // DEVICES
  // ============================================

  /**
   * GET /api/v1/biometrics/devices
   * Lista dispositivos del usuario autenticado
   */
  async getDevices(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const userId = req.user!.userId;
      const { platform, isActive, biometricEnabled, page = 1, limit = 20 } = req.query;

      const filters = {
        platform: platform as any,
        isActive: isActive === 'true' ? true : isActive === 'false' ? false : undefined,
        biometricEnabled:
          biometricEnabled === 'true' ? true : biometricEnabled === 'false' ? false : undefined,
      };

      const result = await this.biometricsService.findDevicesByUserId(userId, filters, {
        page: Number(page),
        limit: Number(limit),
      });

      const response: ApiResponse = {
        success: true,
        data: result.data,
        meta: {
          total: result.total,
          page: Number(page),
          limit: Number(limit),
          totalPages: Math.ceil(result.total / Number(limit)),
        },
      };
      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /api/v1/biometrics/devices/:deviceId
   * Obtiene un dispositivo por ID
   */
  async getDeviceById(
    req: AuthenticatedRequest,
    res: Response,
    next: NextFunction
  ): Promise<void> {
    try {
      const userId = req.user!.userId;
      const { deviceId } = req.params;

      const device = await this.biometricsService.findDeviceById(deviceId, userId);

      if (!device) {
        throw new NotFoundError('Dispositivo no encontrado');
      }

      const response: ApiResponse = {
        success: true,
        data: device,
      };
      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  // ============================================
  // CREDENTIALS
  // ============================================

  /**
   * GET /api/v1/biometrics/credentials
   * Lista credenciales biometricas del usuario
   */
  async getCredentials(
    req: AuthenticatedRequest,
    res: Response,
    next: NextFunction
  ): Promise<void> {
    try {
      const userId = req.user!.userId;
      const { biometricType, isActive, page = 1, limit = 20 } = req.query;

      const filters = {
        biometricType: biometricType as any,
        isActive: isActive === 'true' ? true : isActive === 'false' ? false : undefined,
      };

      const result = await this.biometricsService.findCredentialsByUserId(userId, filters, {
        page: Number(page),
        limit: Number(limit),
      });

      const response: ApiResponse = {
        success: true,
        data: result.data,
        meta: {
          total: result.total,
          page: Number(page),
          limit: Number(limit),
          totalPages: Math.ceil(result.total / Number(limit)),
        },
      };
      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /api/v1/biometrics/credentials/:credentialId
   * Obtiene una credencial por ID
   */
  async getCredentialById(
    req: AuthenticatedRequest,
    res: Response,
    next: NextFunction
  ): Promise<void> {
    try {
      const userId = req.user!.userId;
      const { credentialId } = req.params;

      const credential = await this.biometricsService.findCredentialById(credentialId, userId);

      if (!credential) {
        throw new NotFoundError('Credencial biometrica no encontrada');
      }

      const response: ApiResponse = {
        success: true,
        data: credential,
      };
      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  // ============================================
  // ENROLLMENT STATUS
  // ============================================

  /**
   * GET /api/v1/biometrics/enrollment/status
   * Obtiene el estado de enrollment biometrico del usuario
   */
  async getEnrollmentStatus(
    req: AuthenticatedRequest,
    res: Response,
    next: NextFunction
  ): Promise<void> {
    try {
      const userId = req.user!.userId;

      const status = await this.biometricsService.getEnrollmentStatus(userId);

      const response: ApiResponse = {
        success: true,
        data: status,
      };
      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  // ============================================
  // SESSIONS
  // ============================================

  /**
   * GET /api/v1/biometrics/sessions
   * Lista sesiones del usuario
   */
  async getSessions(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const userId = req.user!.userId;
      const { isActive, page = 1, limit = 20 } = req.query;

      const filters = {
        isActive: isActive === 'true' ? true : isActive === 'false' ? false : undefined,
      };

      const result = await this.biometricsService.findSessionsByUserId(userId, filters, {
        page: Number(page),
        limit: Number(limit),
      });

      const response: ApiResponse = {
        success: true,
        data: result.data,
        meta: {
          total: result.total,
          page: Number(page),
          limit: Number(limit),
          totalPages: Math.ceil(result.total / Number(limit)),
        },
      };
      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /api/v1/biometrics/sessions/active
   * Lista sesiones activas del usuario
   */
  async getActiveSessions(
    req: AuthenticatedRequest,
    res: Response,
    next: NextFunction
  ): Promise<void> {
    try {
      const userId = req.user!.userId;

      const sessions = await this.biometricsService.findActiveSessionsByUserId(userId);
      const count = await this.biometricsService.countActiveSessions(userId);

      const response: ApiResponse = {
        success: true,
        data: {
          sessions,
          count,
        },
      };
      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  // ============================================
  // ACTIVITY LOG
  // ============================================

  /**
   * GET /api/v1/biometrics/activity
   * Lista actividad del usuario
   */
  async getActivity(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const userId = req.user!.userId;
      const { activityType, activityStatus, startDate, endDate, page = 1, limit = 50 } = req.query;

      const filters = {
        activityType: activityType as any,
        activityStatus: activityStatus as any,
        startDate: startDate ? new Date(startDate as string) : undefined,
        endDate: endDate ? new Date(endDate as string) : undefined,
      };

      const result = await this.biometricsService.findActivityByUserId(userId, filters, {
        page: Number(page),
        limit: Number(limit),
      });

      const response: ApiResponse = {
        success: true,
        data: result.data,
        meta: {
          total: result.total,
          page: Number(page),
          limit: Number(limit),
          totalPages: Math.ceil(result.total / Number(limit)),
        },
      };
      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /api/v1/biometrics/activity/stats
   * Estadisticas de verificaciones biometricas
   */
  async getVerificationStats(
    req: AuthenticatedRequest,
    res: Response,
    next: NextFunction
  ): Promise<void> {
    try {
      const userId = req.user!.userId;
      const { startDate, endDate } = req.query;

      const stats = await this.biometricsService.getVerificationStats(
        userId,
        startDate ? new Date(startDate as string) : undefined,
        endDate ? new Date(endDate as string) : undefined
      );

      const response: ApiResponse = {
        success: true,
        data: stats,
      };
      res.json(response);
    } catch (error) {
      next(error);
    }
  }
}
