import { Request, Response } from 'express';
import { UniResponse } from '../../lib/UniResponse';
import { asyncHandler } from '../../utils/asyncHandler';
import { LoggingService } from './LoggingService';
import { LogLevel } from '../../models/Logging';

interface AuthenticatedRequest extends Request {
  user?: {
    userId: string;
    email: string;
    role: string;
  };
}

/**
 * Logging Controller
 * Handles all HTTP requests for logging endpoints
 */
export class LoggingController {
  /**
   * Get logs with filtering options
   * GET /api/logging
   */
  public static getLogs = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const {
        module,
        level,
        admin_id,
        user_id,
        startDate,
        endDate,
        page,
        limit,
      } = req.query;

      // Parse query parameters
      const params: any = {};

      if (module && typeof module === 'string') {
        params.module = module;
      }

      if (level && typeof level === 'string' && ['INFO', 'WARN', 'ERROR', 'DEBUG', 'CRITICAL'].includes(level)) {
        params.level = level as LogLevel;
      }

      if (admin_id && typeof admin_id === 'string') {
        params.admin_id = admin_id;
      }

      if (user_id && typeof user_id === 'string') {
        params.user_id = user_id;
      }

      if (startDate) {
        params.startDate = new Date(startDate as string);
      }

      if (endDate) {
        params.endDate = new Date(endDate as string);
      }

      if (page) {
        params.page = parseInt(page as string, 10);
      }

      if (limit) {
        params.limit = parseInt(limit as string, 10);
      }

      const result = await LoggingService.getLogs(params);

      return res.status(200).json(
        UniResponse.Success('Logs retrieved successfully', result, 200)
      );
    }
  );

  /**
   * Create a manual log entry
   * POST /api/logging
   */
  public static createLog = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const { module, level, action, metadata, error_details } = req.body;

      // Validation
      if (!module || !level || !action) {
        return res.status(400).json(
          UniResponse.Error('Module, level, and action are required', null, 400)
        );
      }

      if (!['INFO', 'WARN', 'ERROR', 'DEBUG', 'CRITICAL'].includes(level)) {
        return res.status(400).json(
          UniResponse.Error('Invalid log level. Must be INFO, WARN, ERROR, DEBUG, or CRITICAL', null, 400)
        );
      }

      // Extract user info from request if authenticated
      const userId = req.user?.userId;
      const ip_address = req.ip || req.headers['x-forwarded-for'] || req.connection.remoteAddress;
      const user_agent = req.headers['user-agent'];






      const logData: any = {
        module,
        level: level as LogLevel,
        action,
        metadata,
        error_details,
        ip_address: typeof ip_address === 'string' ? ip_address : undefined,
        user_agent,
      };

      if (userId) {
        logData.user_id = userId;
      }

      const logEntry = await LoggingService.log(logData);

      return res.status(201).json(
        UniResponse.Success('Log entry created successfully', logEntry, 201)
      );
    }
  );

  /**
   * Get logs for specific admin
   * GET /api/logging/admin/:adminId
   */
  public static getLogsByAdminId = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const { adminId } = req.params;
      const {
        module,
        level,
        startDate,
        endDate,
        page,
        limit,
      } = req.query;

      const params: any = {};

      if (module && typeof module === 'string') {
        params.module = module;
      }

      if (level && typeof level === 'string' && ['INFO', 'WARN', 'ERROR', 'DEBUG', 'CRITICAL'].includes(level)) {
        params.level = level as LogLevel;
      }

      if (startDate) {
        params.startDate = new Date(startDate as string);
      }

      if (endDate) {
        params.endDate = new Date(endDate as string);
      }

      if (page) {
        params.page = parseInt(page as string, 10);
      }

      if (limit) {
        params.limit = parseInt(limit as string, 10);
      }

      const result = await LoggingService.getLogsByAdminId(adminId as any, params);

      return res.status(200).json(
        UniResponse.Success('Admin logs retrieved successfully', result, 200)
      );
    }
  );

  /**
   * Get logs for the default admin (694564d876661ff3f9b4887f)
   * GET /api/logging/admin
   */
  public static getDefaultAdminLogs = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const adminId = '694564d876661ff3f9b4887f';
      const {
        module,
        level,
        startDate,
        endDate,
        page,
        limit,
      } = req.query;

      const params: any = {};

      if (module && typeof module === 'string') {
        params.module = module;
      }

      if (level && typeof level === 'string' && ['INFO', 'WARN', 'ERROR', 'DEBUG', 'CRITICAL'].includes(level)) {
        params.level = level as LogLevel;
      }

      if (startDate) {
        params.startDate = new Date(startDate as string);
      }

      if (endDate) {
        params.endDate = new Date(endDate as string);
      }

      if (page) {
        params.page = parseInt(page as string, 10);
      }

      if (limit) {
        params.limit = parseInt(limit as string, 10);
      }

      const result = await LoggingService.getLogsByAdminId(adminId, params);

      return res.status(200).json(
        UniResponse.Success('Admin logs retrieved successfully', result, 200)
      );
    }
  );

  /**
   * Get log statistics
   * GET /api/logging/statistics
   */
  public static getStatistics = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const { startDate, endDate, module } = req.query;

      const params: any = {};

      if (startDate) {
        params.startDate = new Date(startDate as string);
      }

      if (endDate) {
        params.endDate = new Date(endDate as string);
      }

      if (module && typeof module === 'string') {
        params.module = module;
      }

      const statistics = await LoggingService.getStatistics(params);

      return res.status(200).json(
        UniResponse.Success('Log statistics retrieved successfully', statistics, 200)
      );
    }
  );
}
