import { Controller, Get, Logger, Query, Req, Res, UseGuards } from '@nestjs/common';
import { IpService } from './ip.service';
import { Request, Response } from 'express';
import { ApiOperation, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger';
import { IpResponseDto } from './dto/ip.response.dto';
import { OptionalApiKeyGuard } from 'common/guards/optional-api-key.guard';

@ApiTags('ip')
@Controller({ path: 'api', version: '1' })
export class IpController {
  private readonly logger = new Logger(IpController.name);
  constructor(private readonly ipService: IpService) {}

  private getClientIp(req: Request): string {
    const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
    return Array.isArray(ip) ? ip[0] : ip;
  }

  private isWebsiteRequest(req: Request): boolean {
    // Method 1: Check the Referer header
    const referer = req.headers.referer;
    const allowedOrigins = process.env.CORS_ORIGIN?.split(',') || [];
    if (referer && allowedOrigins.some(origin => referer.includes(origin))) {
      return true;
    }

    // Method 2: Check for a session cookie that only your website would set
    const sessionCookie = req.cookies['Authentication']!;
    if (sessionCookie) {
      return true;
    }

    // Method 3: Custom header set by your website
    const websiteToken = req.headers['x-website-token'];
    if (websiteToken === process.env.WEBSITE_SECRET_TOKEN) {
      return true;
    }

    // Not identified as a website request
    return false;
  }

  // Feature 1: Get the client's own IP details
  @Get('get-my-ip')
  @UseGuards(OptionalApiKeyGuard)
  @ApiOperation({ summary: "Get details of the client's own IP address" })
  @ApiResponse({
    status: 200,
    description: 'Successfully retrieved the IP details',
    type: IpResponseDto,
  })
  @ApiResponse({ status: 400, description: 'Could not determine IP address' })
  @ApiResponse({ status: 401, description: 'Unauthorized access' })
  @ApiResponse({ status: 500, description: 'Error processing IP details' })
  async getMyIpDetails(@Req() req: Request, @Res() res: Response) {
    const clientIp = this.getClientIp(req);
    const userAgent = req.headers['user-agent'];

    if (!clientIp) {
      return res.status(400).send('Could not determine IP address');
    }

    try {
      // Determine if this is a website request
      const isWebsite = this.isWebsiteRequest(req);

      // Check if there's an authenticated API key
      const hasValidApiKey = req['apiKey'] != null;

      // Logic to determine access level
      let accessTier: 'free' | 'premium' | 'unauthorized';

      if (isWebsite) {
        accessTier = 'premium'; // Website users get premium access
      } else {
        // Third-party requests must have a valid API key
        if (!hasValidApiKey) {
          return res.status(401).send('API key is required');
        }
        accessTier = 'premium';
      }
      // Ge
      // t the IP details from the database
      const ipDetails = await this.ipService.getIpDetails(clientIp, accessTier, userAgent);

      return res.json(ipDetails);
    } catch (error) {
      this.logger.error('Error fetching IP details:', error);
      return res.status(500).send('Error processing IP details');
    }
  }

  // Feature 2: Get details for a specific IP address
  @Get('get-ip-details')
  @UseGuards(OptionalApiKeyGuard)
  @ApiOperation({ summary: 'Get details of a specific IP address' })
  @ApiQuery({ name: 'ip', required: true, description: 'The IP address to lookup' })
  @ApiResponse({
    status: 200,
    description: 'Successfully retrieved the IP details',
    type: IpResponseDto,
  })
  @ApiResponse({ status: 400, description: 'IP address is required' })
  @ApiResponse({ status: 401, description: 'Unauthorized access' })
  @ApiResponse({ status: 500, description: 'Error processing IP details' })
  async getSpecificIpDetails(@Req() req: Request, @Res() res: Response, @Query('ip') ip: string) {
    const userAgent = req.headers['user-agent'];

    if (!ip) {
      return res.status(400).send('IP address is required');
    }

    try {
      // Determine if this is a website request
      const isWebsite = this.isWebsiteRequest(req);

      // Check if there's an authenticated API key
      const hasValidApiKey = req['apiKey'] != null;

      // Logic to determine access level
      let accessTier: 'free' | 'premium' | 'unauthorized';

      if (isWebsite) {
        accessTier = 'premium'; // Website users get premium access
      } else {
        // Third-party requests must have a valid API key
        if (!hasValidApiKey) {
          return res.status(401).send('API key is required');
        }
        accessTier = 'premium';
      }

      // Get the IP details from the database
      const ipDetails = await this.ipService.getIpDetails(ip, accessTier, userAgent);

      return res.json(ipDetails);
    } catch (error) {
      this.logger.error('Error fetching IP details:', error);
      return res.status(500).send('Error processing IP details');
    }
  }
}
