import {
  Controller,
  Get,
  Param,
  Query,
  UseGuards,
  Request,
  BadRequestException,
} from '@nestjs/common';

import { SecurityIpLogService, DateRange } from './security-ip-log.service';
import { SecurityAuditLogService } from './security-audit-log.service';
import { AdminGuard } from './guards/admin.guard';

interface AuthenticatedRequest {
  user: {
    id: string;
    email?: string;
    role?: string;
  };
}

interface QueryParams {
  start?: string;
  end?: string;
}

/**
 * SecurityIpLogController - Admin-only endpoints for security IP log access
 *
 * RESTRICTED ACCESS:
 * - Requires admin authentication
 * - Every query is logged to security_audit_log
 * - Used for law enforcement requests and fraud investigation
 *
 * All endpoints audit:
 * - Who accessed the data
 * - What query was performed
 * - When the access occurred
 */
@Controller('admin/security-ip-log')
@UseGuards(AdminGuard)
export class SecurityIpLogController {
  constructor(
    private readonly service: SecurityIpLogService,
    private readonly auditService: SecurityAuditLogService,
  ) {}

  /**
   * Find logs by IP address.
   *
   * Requires date range to prevent unbounded queries.
   * Common use case: law enforcement provides IP and time window.
   */
  @Get('by-ip/:ip')
  async findByIp(
    @Param('ip') ip: string,
    @Query() query: QueryParams,
    @Request() req: AuthenticatedRequest,
  ) {
    const dateRange = this.parseDateRange(query);

    // Audit every access
    await this.auditService.logAccess({
      action: 'SECURITY_IP_LOG_QUERY_BY_IP',
      adminId: req.user.id,
      adminEmail: req.user.email,
      details: {
        searchedIp: ip,
        dateRange: {
          start: dateRange.start.toISOString(),
          end: dateRange.end.toISOString(),
        },
      },
    });

    return this.service.findByIp(ip, dateRange);
  }

  /**
   * Find logs by session ID.
   *
   * Correlates an analytics session to its IP history.
   * Useful when session ID is known from other investigation.
   */
  @Get('by-session/:sessionId')
  async findBySessionId(
    @Param('sessionId') sessionId: string,
    @Request() req: AuthenticatedRequest,
  ) {
    // Audit every access
    await this.auditService.logAccess({
      action: 'SECURITY_IP_LOG_QUERY_BY_SESSION',
      adminId: req.user.id,
      adminEmail: req.user.email,
      details: { searchedSessionId: sessionId },
    });

    return this.service.findBySessionId(sessionId);
  }

  /**
   * Find logs by user ID.
   *
   * Retrieves all IP addresses used by a specific user.
   * Optional date range to narrow results.
   */
  @Get('by-user/:userId')
  async findByUserId(
    @Param('userId') userId: string,
    @Query() query: QueryParams,
    @Request() req: AuthenticatedRequest,
  ) {
    const dateRange = query.start && query.end ? this.parseDateRange(query) : undefined;

    // Audit every access
    await this.auditService.logAccess({
      action: 'SECURITY_IP_LOG_QUERY_BY_USER',
      adminId: req.user.id,
      adminEmail: req.user.email,
      details: {
        searchedUserId: userId,
        dateRange: dateRange
          ? {
              start: dateRange.start.toISOString(),
              end: dateRange.end.toISOString(),
            }
          : 'all time',
      },
    });

    return this.service.findByUserId(userId, dateRange);
  }

  /**
   * Get log count for monitoring.
   *
   * Lightweight endpoint for dashboard metrics.
   */
  @Get('count')
  async getCount(
    @Query() query: QueryParams,
    @Request() req: AuthenticatedRequest,
  ) {
    const dateRange = query.start && query.end ? this.parseDateRange(query) : undefined;

    // Audit even count queries for complete visibility
    await this.auditService.logAccess({
      action: 'SECURITY_IP_LOG_COUNT',
      adminId: req.user.id,
      adminEmail: req.user.email,
      details: {
        dateRange: dateRange
          ? {
              start: dateRange.start.toISOString(),
              end: dateRange.end.toISOString(),
            }
          : 'all time',
      },
    });

    const count = await this.service.getLogCount(dateRange);
    return { count };
  }

  /**
   * Parse and validate date range from query parameters.
   */
  private parseDateRange(query: QueryParams): DateRange {
    if (!query.start || !query.end) {
      throw new BadRequestException('start and end date parameters are required');
    }

    const start = new Date(query.start);
    const end = new Date(query.end);

    if (isNaN(start.getTime()) || isNaN(end.getTime())) {
      throw new BadRequestException('Invalid date format. Use ISO 8601 format.');
    }

    if (start > end) {
      throw new BadRequestException('Start date must be before end date');
    }

    // Limit query range to 90 days to prevent excessive data retrieval
    const maxRangeMs = 90 * 24 * 60 * 60 * 1000;
    if (end.getTime() - start.getTime() > maxRangeMs) {
      throw new BadRequestException('Date range cannot exceed 90 days');
    }

    return { start, end };
  }
}
