import { Controller, Post, Body, Param, ParseIntPipe, HttpException, HttpStatus, Get, UseGuards, Logger, Put, Req, Delete } from '@nestjs/common';
import { ApiTags, ApiBody, ApiOperation, ApiResponse, ApiParam } from '@nestjs/swagger';
import { JwtAuthGuard } from 'common/guards/jwt-auth.guard';
import { Roles } from 'common/decorators/role.decorator';
import { UserRole } from 'common/enum/UserRole.enum';
import { CreateBreachCheckWebsiteDto } from './dto/create-breach-check-website.dto';
import { BreachCheckWebsiteResponseDto } from './dto/breach-check-website-response.dto';
import { BreachCheckResultListResponseDto } from './dto/breach-check-result-response.dto';
import { CreateBreachCheckOrganizationDto } from './dto/create-organization.dto';
import { BreachCheckOrganizationResponseDto } from './dto/organization-ressponse.dto';
import { UpdateBreachCheckOrganizationDto } from './dto/update-organization.dto';
import { UpdateBreachCheckWebsiteDto } from './dto/update-breach-check-website.dto';
import { BreachCheckAlertService } from './breach-check.service';

@ApiTags('Breach Check Alert')
@Controller({ path: 'breach-check-alert', version: '1' })
@UseGuards(JwtAuthGuard)
export class BreachCheckAlertController {
  private readonly logger = new Logger(BreachCheckAlertController.name);
  constructor(private readonly breachCheckService: BreachCheckAlertService) { }

  @Post('add-monitor-site')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Add a new monitored website' })
  @ApiBody({ type: CreateBreachCheckWebsiteDto, isArray: true })
  @ApiResponse({ status: 201, description: 'Website monitoring created successfully.', type: BreachCheckWebsiteResponseDto, isArray: true })
  @ApiResponse({ status: 400, description: 'Bad Request' })
  @ApiResponse({ status: 500, description: 'Internal Server Error' })
  async addMonitorSite(@Body() body: CreateBreachCheckWebsiteDto[]): Promise<BreachCheckWebsiteResponseDto[]> {
    this.logger.log('Adding monitored websites', body);
    return this.breachCheckService.addMonitoredWebsite(body);
  }

  @Post('websites/:id/check')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Check the status of a monitored website' })
  @ApiParam({ name: 'id', description: 'Website ID', type: 'number' })
  @ApiResponse({
    status: 200,
    description: 'Website check results',
    type: BreachCheckWebsiteResponseDto,
  })
  @ApiResponse({ status: 404, description: 'Website not found' })
  @ApiResponse({ status: 500, description: 'Server error' })
  async checkWebsite(@Param('id', ParseIntPipe) id: number): Promise<BreachCheckWebsiteResponseDto> {
    try {
      return await this.breachCheckService.checkWebsiteById(id);
    } catch (error) {
      if (error instanceof HttpException) {
        throw error;
      }
      throw new HttpException(`Failed to check website: ${error.message}`, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  @Post('websites/:id/check-now')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Trigger an immediate check for a website' })
  @ApiParam({ name: 'id', description: 'Website ID', type: 'number' })
  @ApiResponse({
    status: 201,
    description: 'Website check results',
    type: BreachCheckResultListResponseDto,
  })
  @ApiResponse({ status: 404, description: 'Website not found' })
  @ApiResponse({ status: 500, description: 'Server error' })
  async checkWebsiteNow(@Param('id', ParseIntPipe) id: number): Promise<BreachCheckResultListResponseDto> {
    try {
      return await this.breachCheckService.checkWebsiteNow(id);
    } catch (error) {
      if (error instanceof HttpException) {
        throw error;
      }
      throw new HttpException(`Failed to check website: ${error.message}`, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  @Post('create-org')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Create a new organization' })
  @ApiBody({ type: CreateBreachCheckOrganizationDto })
  @ApiResponse({ status: 201, description: 'Organization created successfully.', type: BreachCheckOrganizationResponseDto })
  @ApiResponse({ status: 400, description: 'Bad Request' })
  @ApiResponse({ status: 500, description: 'Internal Server Error' })
  async createOrganization(@Body() body: CreateBreachCheckOrganizationDto): Promise<BreachCheckOrganizationResponseDto> {
    this.logger.log('Creating organization', body);
    return this.breachCheckService.createOrganization(body);
  }

  @Get('organizations')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Get all organizations' })
  @ApiResponse({ status: 200, description: 'List of organizations', type: [BreachCheckOrganizationResponseDto] })
  @ApiResponse({ status: 500, description: 'Internal Server Error' })
  async getAllOrganizations(): Promise<BreachCheckOrganizationResponseDto[]> {
    this.logger.log('Fetching all organizations');
    return this.breachCheckService.getAllOrganizations();
  }

  @Get('organizations/:id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Get organization by ID' })
  @ApiParam({ name: 'id', description: 'Organization ID', type: 'number' })
  @ApiResponse({ status: 200, description: 'Organization details', type: BreachCheckOrganizationResponseDto })
  @ApiResponse({ status: 404, description: 'Organization not found' })
  @ApiResponse({ status: 500, description: 'Internal Server Error' })
  async getOrganizationById(@Param('id', ParseIntPipe) id: number): Promise<BreachCheckOrganizationResponseDto> {
    this.logger.log(`Fetching organization with ID: ${id}`);
    const organization = await this.breachCheckService.getOrganizationById(id);
    if (!organization) {
      throw new HttpException('Organization not found', HttpStatus.NOT_FOUND);
    }
    return organization;
  }

  @Put('organizations/:id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Update organization details' })
  @ApiParam({ name: 'id', description: 'Organization ID', type: 'number' })
  @ApiBody({ type: CreateBreachCheckOrganizationDto })
  @ApiResponse({ status: 200, description: 'Organization updated successfully', type: BreachCheckOrganizationResponseDto })
  @ApiResponse({ status: 404, description: 'Organization not found' })
  @ApiResponse({ status: 500, description: 'Internal Server Error' })
  async updateOrganization(
    @Req() req: any,
    @Param('id', ParseIntPipe) id: number,
    @Body() body: UpdateBreachCheckOrganizationDto,
  ): Promise<BreachCheckOrganizationResponseDto> {
    this.logger.log(`Updating organization with ID: ${id}`, body);
    const { user } = req;

    const updatedOrganization = await this.breachCheckService.updateOrganization(id, user, body);
    if (!updatedOrganization) {
      throw new HttpException('Organization not found', HttpStatus.NOT_FOUND);
    }
    return updatedOrganization;
  }


  @Delete('organizations/:id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Delete organization' })
  @ApiParam({ name: 'id', description: 'Organization ID', type: 'number' })
  @ApiResponse({ status: 200, description: 'Organization deleted successfully' })
  @ApiResponse({ status: 404, description: 'Organization not found' })
  @ApiResponse({ status: 500, description: 'Internal Server Error' })
  async deleteOrganization(@Param('id', ParseIntPipe) id: number): Promise<{ message: string }> {
    this.logger.log(`Deleting organization with ID: ${id}`);
    await this.breachCheckService.deleteOrganization(id);
    return { message: 'Organization deleted successfully' };
  }


  @Get('organizations/user/:userId')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Get organizations by user ID' })
  @ApiParam({ name: 'userId', description: 'User ID', type: 'number' })
  @ApiResponse({ status: 200, description: 'List of organizations for the user', type: [BreachCheckOrganizationResponseDto] })
  @ApiResponse({ status: 500, description: 'Internal Server Error' })
  async getOrganizationsByUserId(@Param('userId', ParseIntPipe) userId: number): Promise<BreachCheckOrganizationResponseDto[]> {
    this.logger.log(`Fetching organizations for user ID: ${userId}`);
    return this.breachCheckService.getOrganizationByUserId(userId);
  }

  @Put('websites/:id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Update monitored website details' })
  @ApiParam({ name: 'id', description: 'Website ID', type: 'number' })
  @ApiBody({ type: UpdateBreachCheckWebsiteDto })
  @ApiResponse({ status: 200, description: 'Website updated successfully', type: BreachCheckWebsiteResponseDto })
  @ApiResponse({ status: 404, description: 'Website not found' })
  @ApiResponse({ status: 500, description: 'Internal Server Error' })
  async updateBreachCheckWebsite(
    @Req() req: any,
    @Param('id', ParseIntPipe) id: number,
    @Body() body: UpdateBreachCheckWebsiteDto,
  ): Promise<BreachCheckWebsiteResponseDto> {
    this.logger.log(`Updating website with ID: ${id}`, body);
    const { user } = req;
    const updatedWebsite = await this.breachCheckService.updateBreachcheckWebsite(id, user, body);
    if (!updatedWebsite) {
      throw new HttpException('Website not found', HttpStatus.NOT_FOUND);
    }
    return updatedWebsite;
  }

  @Delete('websites/:id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.USER)
  @ApiOperation({ summary: 'Delete website' })
  @ApiParam({ name: 'id', description: 'Website ID', type: 'number' })
  @ApiResponse({ status: 200, description: 'Website deleted successfully' })
  @ApiResponse({ status: 404, description: 'Website not found' })
  @ApiResponse({ status: 500, description: 'Internal Server Error' })
  async deleteWebsite(@Param('id', ParseIntPipe) id: number): Promise<{ message: string }> {
    this.logger.log(`Deleting website with ID: ${id}`);
    await this.breachCheckService.deleteWebsite(id);
    return { message: 'Website deleted successfully' };
  }
}
