import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import {
  CheckStatus,
  AlertSeverity,
  MonitoringCheckType,
  OperationalStatus,
  WebsiteCategory,
} from './enums/website-monitoring.enum';
import { fetchRenderedPageWithPuppeteer } from './helper/html-loader-puppeter';
import axios from 'axios';
import * as cheerio from 'cheerio';
import * as crypto from 'crypto';
import { AICheckResult, compareContentWithAI, ContentSignature } from './helper/ai-content-scanner';
import { ConfigService } from '@nestjs/config';
import { CrawlerService } from 'modules/crawler/crawler.service';
import { BreachCheckWebsites } from './entities/breach-check-website.entity';
import { BreachCheckWebsiteBaseline } from './entities/breach-check-website-baseline.entity';
import { BreachCheckResult } from './entities/breach-check-result.entity';
import { BreachCheckOrganization } from './entities/breach-check-organization.entity';
import { BreachCheckOrganizationResponseDto } from './dto/organization-ressponse.dto';
import { CreateBreachCheckOrganizationDto, SubscriptionTier } from './dto/create-organization.dto';
import { CreateBreachCheckWebsiteDto } from './dto/create-breach-check-website.dto';
import { BreachCheckWebsiteResponseDto } from './dto/breach-check-website-response.dto';
import { BreachCheckResultListResponseDto, BreachCheckResultResponseDto } from './dto/breach-check-result-response.dto';
import { UpdateBreachCheckOrganizationDto } from './dto/update-organization.dto';
import { UpdateBreachCheckWebsiteDto } from './dto/update-breach-check-website.dto';
import { UserRole } from 'common/enum/UserRole.enum';
import { SettingsService } from 'modules/settings/setting.services';

interface RouteChangeAnalysis {
  newRoutes: number;
  removedRoutes: number;
  modifiedRoutes: number;
  totalCurrentRoutes: number;
  totalBaselineRoutes: number;
  changedRoutes: Array<{
    path: string;
    changeType: 'new' | 'removed' | 'modified';
    oldHash?: string;
    newHash?: string;
  }>;
}

@Injectable()
export class BreachCheckAlertService {
  private readonly logger = new Logger(BreachCheckAlertService.name);
  private websites: BreachCheckWebsites[] = [];
  private isCheckRunning = false;
  private checkIntervals: Map<string, NodeJS.Timeout> = new Map();

  constructor(
    @InjectRepository(BreachCheckWebsites)
    private monitoredWebsiteRepository: Repository<BreachCheckWebsites>,

    @InjectRepository(BreachCheckWebsiteBaseline)
    private websiteBaselineRepository: Repository<BreachCheckWebsiteBaseline>,

    @InjectRepository(BreachCheckResult)
    private checkResultRepository: Repository<BreachCheckResult>,

    @InjectRepository(BreachCheckOrganization)
    private organizationRepository: Repository<BreachCheckOrganization>,

    private configService: ConfigService,
    private readonly crawlService: CrawlerService,
    private readonly settingsService: SettingsService,
  ) {
    this.websites = [];
  }

  async createOrganization(createOrganizationDto: CreateBreachCheckOrganizationDto): Promise<BreachCheckOrganizationResponseDto> {
    this.logger.log('Creating organization:', createOrganizationDto);
    try {
      const { userId } = createOrganizationDto;

      const maxOrgs = await this.settingsService.getLimitForUser(userId, 'MAX_ORGS_PER_USER', 5);

      const existingOrganizationsCount = await this.organizationRepository.count({
        where: { userId },
      });

      if (existingOrganizationsCount >= maxOrgs) {
        throw new HttpException(`Your organization limit (${maxOrgs}) has been reached.`, HttpStatus.BAD_REQUEST);
      }
      const newOrganization = this.organizationRepository.create(createOrganizationDto);
      const savedOrganization = await this.organizationRepository.save(newOrganization);
      this.logger.log('Organization created successfully:', savedOrganization);
      return {
        id: savedOrganization.id,
        orgName: savedOrganization.orgName,
        contactEmail: savedOrganization.contactEmail,
        isActive: savedOrganization.isActive,
        userId: savedOrganization.userId,
        createdAt: savedOrganization.createdAt,
        subscriptionTier: savedOrganization.subscriptionTier as SubscriptionTier,
        updatedAt: savedOrganization.updatedAt
      };
    } catch (error) {
      this.logger.error('Error creating organization', error);
      throw new HttpException('Error creating organization', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async getAllOrganizations(): Promise<BreachCheckOrganizationResponseDto[]> {
    this.logger.log('Fetching all organizations');
    try {
      const organizations = await this.organizationRepository.find();
      this.logger.log(`Fetched ${organizations.length} organizations successfully`);
      return organizations.map(org => ({
        id: org.id,
        orgName: org.orgName,
        contactEmail: org.contactEmail,
        isActive: org.isActive,
        userId: org.userId,
        createdAt: org.createdAt,
        subscriptionTier: org.subscriptionTier as SubscriptionTier,
        updatedAt: org.updatedAt,
        websites: org.websites.map(website => ({
          id: website.id,
          url: website.url,
          category: website.category,
          alertThreshold: website.alertThreshold,
          monitoringFrequencyMinutes: website.monitoringFrequencyMinutes,
          operationalStatus: website.operationalStatus as OperationalStatus,
          lastMonitoredAt: website.lastMonitoredAt,
          enabledChecks: website.enabledChecks as MonitoringCheckType[],
          isFalsePositive: website.isFalsePositive,
          receiveAlerts: website.receiveAlerts,
          notes: website.notes,
          tags: website.tags,
          name: website.name,
          organizationId: website.organizationId,
          stage: website.stage,
          createdAt: website.createdAt,
          updatedAt: website.updatedAt,
        })),
      }));
    } catch (error) {
      this.logger.error('Error fetching organizations', error);
      throw new HttpException('Error fetching organizations', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async getOrganizationById(id: number): Promise<BreachCheckOrganizationResponseDto> {
    this.logger.log(`Fetching organization with ID: ${id}`);
    try {
      const organization = await this.organizationRepository.findOne({ where: { id } });
      if (!organization) {
        throw new HttpException('Organization not found', HttpStatus.NOT_FOUND);
      }

      this.logger.log('Organization found:', organization);
      return {
        id: organization.id,
        orgName: organization.orgName,
        contactEmail: organization.contactEmail,
        isActive: organization.isActive,
        userId: organization.userId,
        createdAt: organization.createdAt,
        subscriptionTier: organization.subscriptionTier as SubscriptionTier,
        updatedAt: organization.updatedAt,
        websites: organization.websites.map(website => ({
          id: website.id,
          url: website.url,
          category: website.category,
          alertThreshold: website.alertThreshold,
          monitoringFrequencyMinutes: website.monitoringFrequencyMinutes,
          operationalStatus: website.operationalStatus as OperationalStatus,
          lastMonitoredAt: website.lastMonitoredAt,
          enabledChecks: website.enabledChecks as MonitoringCheckType[],
          isFalsePositive: website.isFalsePositive,
          receiveAlerts: website.receiveAlerts,
          notes: website.notes,
          tags: website.tags,
          name: website.name,
          organizationId: website.organizationId,
          stage: website.stage,
          createdAt: website.createdAt,
          updatedAt: website.updatedAt,
        })),
      };
    } catch (error) {
      this.logger.error('Error fetching organization', error);
      throw new HttpException('Error fetching organization', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async deleteOrganization(id: number): Promise<void> {
    this.logger.log(`Deleting organization with ID: ${id}`);
    try {
      const organization = await this.organizationRepository.findOne({ where: { id } });
      if (!organization) {
        throw new HttpException('Organization not found', HttpStatus.NOT_FOUND);
      }

      await this.organizationRepository.delete(id);
      this.logger.log(`Organization with ID ${id} deleted successfully`);
    } catch (error) {
      this.logger.error('Error deleting organization', error);
      throw new HttpException('Error deleting organization', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async addMonitoredWebsite(createMonitoredWebsite: CreateBreachCheckWebsiteDto[]): Promise<BreachCheckWebsiteResponseDto[]> {
    this.logger.log('Adding monitored websites:', createMonitoredWebsite);
    try {
      const websites: BreachCheckWebsites[] = [];
      for (const website of createMonitoredWebsite) {
        const organization = await this.organizationRepository.findOne({
          where: { id: website.organizationId },
        });

        if (!organization) {
          throw new HttpException(`Organization with ID ${website.organizationId} not found for website "${website.name}"`, HttpStatus.NOT_FOUND);
        }

        const { userId } = organization;
        this.logger.log(`Checking website limit for org ${organization.id}, user ${userId}`);

        const maxWebsites = await this.settingsService.getLimitForUser(userId, 'MAX_WEBSITES_PER_ORG', 5);
        const existingWebsitesCount = await this.monitoredWebsiteRepository.count({
          where: { organizationId: website.organizationId },
        });

        if (existingWebsitesCount >= maxWebsites) {
          throw new HttpException(`The website limit (${maxWebsites}) for organization "${organization.orgName}" has been reached. Cannot add "${website.name}".`, HttpStatus.BAD_REQUEST);
        }
        const websiteData = {
          ...website,
          organizationId: website.organizationId ? parseInt(website.organizationId.toString(), 10) : null,
        };

        const existingWebsites = await this.monitoredWebsiteRepository.count({
          where: { organizationId: website.organizationId },
        });

        if (existingWebsites >= maxWebsites) {
          throw new HttpException(`Maximum website limit (${maxWebsites}) reached for this organization`, HttpStatus.BAD_REQUEST);
        }
        const newWebsite = this.monitoredWebsiteRepository.create(websiteData);
        newWebsite.operationalStatus = OperationalStatus.UNKNOWN;
        newWebsite.enabledChecks = [MonitoringCheckType.AVAILABILITY, MonitoringCheckType.DEFACEMENT];
        newWebsite.category = website.category || WebsiteCategory.OTHER;
        newWebsite.monitoringFrequencyMinutes = website.monitoringFrequencyMinutes || 60;
        newWebsite.lastMonitoredAt = null;
        const savedWebsite = await this.monitoredWebsiteRepository.save(newWebsite);
        websites.push(savedWebsite);
      }
      this.logger.log('Monitored websites added successfully:', websites);
      return websites.map(website => ({
        id: website.id,
        url: website.url,
        category: website.category,
        alertThreshold: website.alertThreshold,
        monitoringFrequencyMinutes: website.monitoringFrequencyMinutes,
        operationalStatus: website.operationalStatus as OperationalStatus,
        lastMonitoredAt: website.lastMonitoredAt,
        enabledChecks: website.enabledChecks as MonitoringCheckType[],
        isFalsePositive: website.isFalsePositive,
        receiveAlerts: website.receiveAlerts,
        notes: website.notes,
        tags: website.tags,
        name: website.name,
        organizationId: website.organizationId,
        stage: website.stage,
        checkContentWithAI: website.checkContentWithAI,
        createdAt: website.createdAt,
        updatedAt: website.updatedAt,
      }));
    } catch (error) {
      this.logger.error('Error adding monitored website', error);
      throw new HttpException('Error adding monitored website', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async deleteWebsite(id: number): Promise<void> {
    this.logger.log(`Deleting website with ID: ${id}`);
    try {
      const website = await this.monitoredWebsiteRepository.findOne({ where: { id } });
      if (!website) {
        throw new HttpException('Website not found', HttpStatus.NOT_FOUND);
      }

      await this.monitoredWebsiteRepository.delete(id);
      this.logger.log(`Website with ID ${id} deleted successfully`);
    } catch (error) {
      this.logger.error('Error deleting website', error);
      throw new HttpException('Error deleting website', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async checkWebsiteById(id: number): Promise<BreachCheckWebsiteResponseDto> {
    this.logger.log(`Checking website with ID: ${id}`);
    try {
      const website = await this.monitoredWebsiteRepository.findOne({
        where: { id },
        relations: ['organization', 'checkResults'],
      });
      if (!website) {
        throw new HttpException('Website not found', HttpStatus.NOT_FOUND);
      }

      this.logger.log('Website found:', website);

      return {
        id: website.id,
        url: website.url,
        category: website.category,
        alertThreshold: website.alertThreshold,
        monitoringFrequencyMinutes: website.monitoringFrequencyMinutes,
        operationalStatus: website.operationalStatus as OperationalStatus,
        lastMonitoredAt: website.lastMonitoredAt,
        enabledChecks: website.enabledChecks as MonitoringCheckType[],
        isFalsePositive: website.isFalsePositive,
        receiveAlerts: website.receiveAlerts,
        notes: website.notes,
        tags: website.tags,
        name: website.name,
        organizationId: website.organizationId,
        stage: website.stage,
        createdAt: website.createdAt,
        updatedAt: website.updatedAt,
        organization: {
          id: website.organization?.id,
          orgName: website.organization?.orgName,
          contactEmail: website.organization?.contactEmail,
          isActive: website.organization?.isActive,
          userId: website.organization?.userId,
          createdAt: website.organization?.createdAt,
          subscriptionTier: website.organization?.subscriptionTier as SubscriptionTier,
          updatedAt: website.organization?.updatedAt,
        },
      };
    } catch (error) {
      this.logger.error('Error checking website', error);
      throw new HttpException('Error checking website', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async getOrganizationByUserId(userId: number): Promise<BreachCheckOrganizationResponseDto[]> {
    this.logger.log(`Fetching organizations for user ID: ${userId}`);
    try {
      const organizations = await this.organizationRepository.find({
        where: { userId },
        relations: ['websites']
      });

      this.logger.log(`Found ${organizations.length} organizations for user ${userId}`);
      return organizations.map(org => ({
        id: org.id,
        orgName: org.orgName,
        contactEmail: org.contactEmail,
        isActive: org.isActive,
        userId: org.userId,
        createdAt: org.createdAt,
        subscriptionTier: org.subscriptionTier as SubscriptionTier,
        updatedAt: org.updatedAt,
        websites: org.websites?.map(website => ({
          id: website.id,
          url: website.url,
          category: website.category,
          alertThreshold: website.alertThreshold,
          monitoringFrequencyMinutes: website.monitoringFrequencyMinutes,
          operationalStatus: website.operationalStatus as OperationalStatus,
          lastMonitoredAt: website.lastMonitoredAt,
          enabledChecks: website.enabledChecks as MonitoringCheckType[],
          isFalsePositive: website.isFalsePositive,
          receiveAlerts: website.receiveAlerts,
          notes: website.notes,
          tags: website.tags,
          name: website.name,
          organizationId: website.organizationId,
          stage: website.stage,
          createdAt: website.createdAt,
          updatedAt: website.updatedAt,
        })) || [],
      }));
    } catch (error) {
      this.logger.error('Error fetching organizations by user ID', error);
      throw new HttpException('Error fetching organizations by user ID', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async startBreachCheck(): Promise<void> {
    this.logger.log('Starting attack check');
    if (this.isCheckRunning) {
      this.logger.warn('Attack check is already running');
      return;
    }
    try {
      this.websites.forEach(website => {
        this.scheduleChecks(website);
      });
    } catch (error) {
      this.logger.error('Error starting attack check', error);
      throw new HttpException('Error starting attack check', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async stopBreachCheck(): Promise<void> {
    this.logger.log('Stopping attack check');
    if (!this.isCheckRunning) {
      this.logger.warn('Attack check is not running');
      return;
    }
    this.isCheckRunning = false;

    // Clear all intervals
    this.logger.log('Clearing all intervals');
    this.websites.forEach(website => {
      const interval = this.checkIntervals.get(website.url);
      if (interval) {
        clearInterval(interval);
        this.checkIntervals.delete(website.url);
      }
    });

    this.checkIntervals.clear();
    this.logger.log('All intervals cleared');
  }

  private scheduleChecks(website: BreachCheckWebsites): void {
    this.logger.log(`Scheduling checks for ${website.url}`);
    if (this.checkIntervals.has(website.url)) {
      this.logger.warn(`Check interval already exists for ${website.url}`);
      return;
    }

    // Schedule the check
    this.logger.log(`Scheduling check for ${website.url} every ${website.monitoringFrequencyMinutes} minutes`);
    const interval = setInterval(
      async () => {
        try {
          const results = await this.performCheck(website);
          this.logger.debug(`Scheduled check completed for ${website.url}`);
          // Handle results as needed
        } catch (error) {
          this.logger.error(`Error during scheduled check for ${website.url}: ${error.message}`, error.stack);
        }
      },
      website.monitoringFrequencyMinutes * 60 * 1000,
    );

    // Store the interval in the map
    this.logger.debug(`Storing interval for ${website.url}`);
    this.checkIntervals.set(website.url, interval);
  }

  public async checkWebsiteNow(websiteId: number, page: number = 1, limit: number = 10): Promise<BreachCheckResultListResponseDto> {
    this.logger.log(`Checking website now with ID: ${websiteId}`);

    const website = await this.monitoredWebsiteRepository.findOne({ where: { id: websiteId } });

    if (!website) {
      throw new HttpException('Website not found', HttpStatus.NOT_FOUND);
    }

    try {
      const allResults = await this.performCheck(website);
      const total = allResults.length;
      const totalPages = Math.ceil(total / limit);

      // Ensure the page value is within range
      const safePage = Math.max(1, Math.min(page, totalPages));

      // Slice the data for the requested page
      const paginatedResults = allResults.slice((safePage - 1) * limit, safePage * limit);

      this.logger.log(`Website check completed for ${website.url}`);

      return {
        results: paginatedResults,
        page: safePage,
        total: total,
        totalPages: totalPages,
        limit: limit,
        hasNext: safePage < totalPages,
        hasPrev: safePage > 1,
      };
    } catch (error) {
      this.logger.error(`Error checking website ${website.url}: ${error.message}`, error.stack);
      throw new HttpException(`Error checking website ${website.url}`, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async updateOrganization(id: number, user: any, updateDto: UpdateBreachCheckOrganizationDto): Promise<BreachCheckOrganizationResponseDto> {
    this.logger.log(`Updating organization with ID: ${id}`);
    try {
      const organization = await this.organizationRepository.findOne({ where: { id } });

      if (user.role === UserRole.USER && organization.userId !== user.id) {
        this.logger.warn(`User ${user.id} is not authorized to update organization ${id}`);
        throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
      }

      if (!organization) {
        throw new HttpException('Organization not found', HttpStatus.NOT_FOUND);
      }

      // Update organization properties
      Object.assign(organization, updateDto);
      const updatedOrganization = await this.organizationRepository.save(organization);

      this.logger.log('Organization updated successfully:', updatedOrganization);
      return {
        id: updatedOrganization.id,
        orgName: updatedOrganization.orgName,
        contactEmail: updatedOrganization.contactEmail,
        isActive: updatedOrganization.isActive,
        userId: updatedOrganization.userId,
        createdAt: updatedOrganization.createdAt,
        subscriptionTier: updatedOrganization.subscriptionTier as SubscriptionTier,
        updatedAt: updatedOrganization.updatedAt,
      };
    } catch (error) {
      this.logger.error('Error updating organization', error);
      throw new HttpException('Error updating organization', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async updateBreachcheckWebsite(id: number, user: any, updateDto: UpdateBreachCheckWebsiteDto): Promise<BreachCheckWebsiteResponseDto> {
    this.logger.log(`Updating breach check website with ID: ${id}`, updateDto);
    try {
      const website = await this.monitoredWebsiteRepository.findOne({ where: { id: id } });

      // find organization first and then user uservalidation for role user
      const organization = await this.organizationRepository.findOne({
        where: { id: website.organizationId },
      });

      // Check if the user is authorized to update the website
      if (user.role === UserRole.USER && organization.userId !== user.id) {
        this.logger.warn(`User  ${user.id} is not authorized to update website ${id}`);
        throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
      }

      if (!website) {
        throw new HttpException('Website not found', HttpStatus.NOT_FOUND);
      }

      // Update website properties
      Object.assign(website, updateDto);
      const updatedWebsite = await this.monitoredWebsiteRepository.save(website);

      this.logger.log('Breach check website updated successfully:', updatedWebsite);
      return {
        id: updatedWebsite.id,
        url: updatedWebsite.url,
        category: updatedWebsite.category,
        alertThreshold: updatedWebsite.alertThreshold,
        monitoringFrequencyMinutes: updatedWebsite.monitoringFrequencyMinutes,
        operationalStatus: updatedWebsite.operationalStatus as OperationalStatus,
        lastMonitoredAt: updatedWebsite.lastMonitoredAt,
        enabledChecks: updatedWebsite.enabledChecks as MonitoringCheckType[],
        isFalsePositive: updatedWebsite.isFalsePositive,
        receiveAlerts: updatedWebsite.receiveAlerts,
        notes: updatedWebsite.notes,
        tags: updatedWebsite.tags,
        name: updatedWebsite.name,
        organizationId: updatedWebsite.organizationId,
        stage: updatedWebsite.stage,
        createdAt: updatedWebsite.createdAt,
        updatedAt: updatedWebsite.updatedAt,
      };
    } catch (error) {
      this.logger.error('Error updating breach check website', error);
      throw new HttpException('Error updating breach check website', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  private async performCheck(website: BreachCheckWebsites): Promise<BreachCheckResultResponseDto[]> {
    this.logger.log(`Performing checks for ${website.url}`);
    const results: BreachCheckResultResponseDto[] = [];

    try {
      for (const checkType of website.enabledChecks) {
        try {
          const result = await this.performSingleCheck(website, checkType);
          results.push(result);

          // Store the check result in the database
          await this.storeCheckResult(
            website.id,
            result.checkType as MonitoringCheckType,
            result.status as CheckStatus,
            result.severity,
            result.details,
            result.alertGenerated,
            result.rawData,
            result.responseTimeMs,
          );
        } catch (error) {
          this.logger.error(`Error performing check ${checkType} for ${website.url}: ${error.message}`, error.stack);

          const checkResult: BreachCheckResultResponseDto = {
            id: null, // This will be set by the database
            websiteId: website.id,
            checkType: checkType,
            timestamp: new Date(),
            severity: AlertSeverity.CRITICAL,
            status: CheckStatus.ERROR,
            details: { error: error.message },
            alertGenerated: false,
            rawData: null,
            responseTimeMs: null,
          };

          results.push(checkResult);

          // Store the error result in the database
          this.logger.debug(`Storing error check result for ${website.url} - ${checkType}: ${checkResult.status}`);
          await this.storeCheckResult(
            website.id,
            checkResult.checkType as MonitoringCheckType,
            checkResult.status as CheckStatus,
            checkResult.severity,
            checkResult.details,
            checkResult.alertGenerated,
            checkResult.rawData,
          );
        }
      }

      return results;
    } catch (error) {
      this.logger.error(`Error performing checks for ${website.url}: ${error.message}`, error.stack);
      return results;
    }
  }

  private async performSingleCheck(website: BreachCheckWebsites, checkType: MonitoringCheckType): Promise<BreachCheckResultResponseDto> {
    this.logger.log(`Performing single check for ${website.url} - ${checkType}`);
    switch (checkType) {
      case MonitoringCheckType.AVAILABILITY:
        return this.checkAvailability(website);
      case MonitoringCheckType.DEFACEMENT:
        return this.checkDefacement(website);
      default:
        throw new Error(`Unknown check type: ${checkType}`);
    }
  }

  private async checkAvailability(website: BreachCheckWebsites): Promise<BreachCheckResultResponseDto> {
    this.logger.log(`Checking availability for ${website.url}`);
    try {
      const startTime = Date.now();
      const response = await axios.get(website.url, {
        timeout: 15000,
        validateStatus: () => true, // Accept all status codes to handle them manually
      });
      const responseTime = Date.now() - startTime;

      // Check status code and response time
      let status: CheckStatus = CheckStatus.PASS;
      const details: Record<string, any> = {
        statusCode: response.status,
        responseTime: responseTime,
      };

      if (response.status >= 500) {
        status = CheckStatus.FAIL;
      } else if (response.status >= 400 || responseTime > 5000) {
        status = CheckStatus.WARNING;
      }

      this.logger.debug(`Availability check for ${website.url} - Status: ${response.status}, Response Time: ${responseTime}ms`);
      return {
        id: null, // This will be set when saved to the database
        websiteId: website.id,
        checkType: MonitoringCheckType.AVAILABILITY,
        timestamp: new Date(),
        severity: status === CheckStatus.FAIL ? AlertSeverity.CRITICAL : status === 'WARNING' ? AlertSeverity.MEDIUM : AlertSeverity.INFO,
        status,
        details,
        alertGenerated: false,
        rawData: null,
        responseTimeMs: responseTime,
      };
    } catch (error) {
      this.logger.error(`Error checking availability for ${website.url}: ${error.message}`, error.stack);
      const details: Record<string, any> = {
        error: error.message,
      };
      return {
        id: null, // This will be set when saved to the database
        websiteId: website.id,
        checkType: MonitoringCheckType.AVAILABILITY,
        timestamp: new Date(),
        severity: AlertSeverity.CRITICAL,
        status: CheckStatus.ERROR,
        details,
        alertGenerated: false,
        rawData: null,
        responseTimeMs: null,
      };
    }
  }

  // Enhanced checkDefacement method with AI integration
  private async checkDefacement(website: BreachCheckWebsites): Promise<BreachCheckResultResponseDto> {
    const startTime = Date.now();
    this.logger.log(`Checking defacement for ${website.url}`);
    try {
      // Use Puppeteer instead of axios
      const { html, httpData } = await fetchRenderedPageWithPuppeteer(website.url);
      const $ = cheerio.load(html);

      // Extract content components
      const title = $('title').text().trim();
      const headings = $('h1, h2, h3')
        .map((_, el) => $(el).text().trim())
        .get()
        .join('|')
        .substring(0, 500);
      const metaDesc = $('meta[name="description"]').attr('content') || '';
      const bodyText = $('body').text().trim().substring(0, 2000);

      // Create content signature
      const contentSignature: ContentSignature = {
        title,
        metaDesc,
        headings,
        bodyTextSample: bodyText,
        linkCount: $('a').length,
        imageCount: $('img').length,
        scriptCount: $('script').length,
        cssCount: $('link[rel="stylesheet"]').length,
        httpStatus: httpData.status,
      };

      // ===== STEP 2: CREATE HASHES =====
      // Primary hash for instant comparison
      const mainContentHash = crypto.createHash('md5').update(`${title}|${headings}|${metaDesc}|${bodyText}`).digest('hex');

      // Detailed component hashes
      const titleHash = crypto.createHash('md5').update(title).digest('hex');
      const metaDescHash = crypto.createHash('md5').update(metaDesc).digest('hex');
      const bodyTextHash = crypto.createHash('md5').update(bodyText).digest('hex');
      const structureHash = crypto
        .createHash('md5')
        .update(`${$('head').children().length}|${$('body').children().length}|${$('script').length}|${$('img').length}`)
        .digest('hex');

      // Load the baseline
      const baseline = await this.websiteBaselineRepository.findOne({ where: { websiteId: website.id } });

      // Handle the case of first check (no baseline exists)
      if (!baseline) {
        return await this.createInitialBaseline(
          website,
          contentSignature,
          mainContentHash,
          titleHash,
          metaDescHash,
          bodyTextHash,
          structureHash,
          httpData,
        );
      }

      // === OPTIMIZED HASH-FIRST COMPARISON ===
      this.logger.debug('Starting hash-first comparison');

      // ===== STEP 5: HASH-FIRST COMPARISON =====
      const mainContentChanged = baseline.mainContentHash !== mainContentHash;

      // Early return if nothing changed
      if (!mainContentChanged) {
        this.logger.debug(`No changes detected for ${website.url} - returning early`);

        return {
          id: null, // This will be set when saved to the database
          websiteId: website.id,
          checkType: MonitoringCheckType.DEFACEMENT,
          timestamp: new Date(),
          severity: AlertSeverity.INFO,
          status: CheckStatus.PASS,
          details: {
            message: 'No changes detected',
            differenceScore: 0,
            optimized: true,
            hashComparison: {
              mainContentChanged: false,
            },
            baselineVersion: baseline.baselineVersion,
          },
          alertGenerated: false,
          rawData: null,
          responseTimeMs: Date.now() - startTime,
          website: {
            id: website.id,
            url: website.url,
            category: website.category,
            alertThreshold: website.alertThreshold,
            monitoringFrequencyMinutes: website.monitoringFrequencyMinutes,
            operationalStatus: website.operationalStatus as OperationalStatus,
            lastMonitoredAt: website.lastMonitoredAt,
            enabledChecks: website.enabledChecks as MonitoringCheckType[],
            isFalsePositive: website.isFalsePositive,
            receiveAlerts: website.receiveAlerts,
            notes: website.notes,
            tags: website.tags,
            name: website.name,
            checkContentWithAI: website.checkContentWithAI,
            organizationId: website.organizationId,
            stage: website.stage,
            createdAt: website.createdAt,
            updatedAt: website.updatedAt,
          },
        };
      }

      // ===== STEP 6: DETAILED ANALYSIS FOR CHANGES =====
      return await this.performDetailedAnalysis(
        website,
        baseline,
        contentSignature,
        mainContentHash,
        titleHash,
        metaDescHash,
        bodyTextHash,
        structureHash,
        httpData,
        mainContentChanged,
        startTime,
      );
    } catch (error) {
      this.logger.error(`Error in defacement check for ${website.url}: ${error.message}`, error.stack);

      return {
        id: null, // This will be set when saved to the database
        websiteId: website.id,
        checkType: MonitoringCheckType.DEFACEMENT,
        timestamp: new Date(),
        severity: AlertSeverity.CRITICAL,
        status: CheckStatus.ERROR,
        details: {
          error: error.message,
          timestamp: new Date(),
        },
        alertGenerated: true,
        rawData: null,
        responseTimeMs: Date.now() - startTime,
        website: {
          id: website.id,
          url: website.url,
          category: website.category,
          alertThreshold: website.alertThreshold,
          monitoringFrequencyMinutes: website.monitoringFrequencyMinutes,
          operationalStatus: website.operationalStatus as OperationalStatus,
          lastMonitoredAt: website.lastMonitoredAt,
          enabledChecks: website.enabledChecks as MonitoringCheckType[],
          isFalsePositive: website.isFalsePositive,
          receiveAlerts: website.receiveAlerts,
          notes: website.notes,
          tags: website.tags,
          name: website.name,
          organizationId: website.organizationId,
          stage: website.stage,
          createdAt: website.createdAt,
          updatedAt: website.updatedAt,
        },
      };
    }
  }

  /**
   * Creates initial baseline for first-time website monitoring
   */
  private async createInitialBaseline(
    website: BreachCheckWebsites,
    contentSignature: ContentSignature,
    mainContentHash: string,
    titleHash: string,
    metaDescHash: string,
    bodyTextHash: string,
    structureHash: string,
    httpData: any,
  ): Promise<BreachCheckResultResponseDto> {
    this.logger.debug(`Creating initial baseline for ${website.url}`);

    // Perform initial crawling
    let discoveredRoutes: Array<{
      path: string;
      contentHash: string;
      lastChecked: Date;
      status: 'active' | 'inactive' | 'changed';
      httpStatus?: number;
    }> = [];
    let routesHash: string | null = null;

    try {
      const crawledUrls = await this.crawlService.crawlWebsite(website.url, 2, 20);
      this.logger.debug(`Initial crawl discovered ${crawledUrls.length} URLs for ${website.url}`);

      for (const url of crawledUrls) {
        try {
          const { html: routeHtml, httpData: routeHttpData } = await fetchRenderedPageWithPuppeteer(url);
          const routeContentHash = crypto.createHash('md5').update(routeHtml).digest('hex');
          const urlObj = new URL(url);
          const path = urlObj.pathname + urlObj.search;

          discoveredRoutes.push({
            path,
            contentHash: routeContentHash,
            lastChecked: new Date(),
            status: 'active',
            httpStatus: routeHttpData?.status || 200,
          });
        } catch (routeError) {
          this.logger.warn(`Failed to process route ${url}: ${routeError.message}`);
        }
      }

      if (discoveredRoutes.length > 0) {
        const routesString = discoveredRoutes
          .map(route => `${route.path}:${route.contentHash}`)
          .sort()
          .join('|');
        routesHash = crypto.createHash('md5').update(routesString).digest('hex');
      }
    } catch (error) {
      this.logger.error(`Error during initial crawling for ${website.url}: ${error.message}`);
    }

    // Create new baseline
    const newBaseline = this.websiteBaselineRepository.create({
      website: website,
      contentSnapshot: JSON.stringify(contentSignature),
      aiAnalysisEnabled: true,
      baselineVersion: 1,
      mainContentHash: mainContentHash,
      titleHash: titleHash,
      bodyTextHash: bodyTextHash,
      crawlingEnabled: true,
      createdAt: new Date(),
      discoveredRoutes: discoveredRoutes,
      httpStatusBaseline: httpData.status,
      lastContentUpdate: new Date(),
      lastCrawlUpdate: new Date(),
      structureHash: structureHash,
      updatedAt: new Date(),
      maxCrawlDepth: 2,
      maxCrawlUrls: 20,
      metaDescHash: metaDescHash,
      routesHash: routesHash,
      sensitivityLevel: 50, // Default sensitivity level
    });

    await this.websiteBaselineRepository.save(newBaseline);

    this.logger.log(`Created baseline for ${website.url} with ${discoveredRoutes.length} routes`);

    return {
      id: null, // This will be set when saved to the database
      websiteId: website.id,
      checkType: MonitoringCheckType.DEFACEMENT,
      timestamp: new Date(),
      severity: AlertSeverity.INFO,
      status: CheckStatus.PASS,
      details: {
        message: 'Initial baseline created successfully',
        routesDiscovered: discoveredRoutes.length,
        baselineVersion: 1,
        mainContentHash,
      },
      alertGenerated: false,
      rawData: null,
      responseTimeMs: Date.now() - newBaseline.createdAt.getTime(),
    };
  }

  /**
   * Performs detailed analysis when changes are detected
   */
  private async performDetailedAnalysis(
    website: BreachCheckWebsites,
    baseline: BreachCheckWebsiteBaseline,
    contentSignature: ContentSignature,
    mainContentHash: string,
    titleHash: string,
    metaDescHash: string,
    bodyTextHash: string,
    structureHash: string,
    httpData: any,
    mainContentChanged: boolean,
    startTime: number,
  ): Promise<BreachCheckResultResponseDto> {
    this.logger.debug(`Performing detailed analysis for ${website.url}`);

    let differenceScore = 0;
    let routeAnalysis: RouteChangeAnalysis | null = null;
    let aiResult: AICheckResult | null = null;

    // Parse baseline content signature
    let baselineSignature: ContentSignature;
    try {
      baselineSignature = JSON.parse(baseline.contentSnapshot || '{}');
    } catch (e) {
      this.logger.warn(`Failed to parse baseline content signature for ${website.url}: ${e.message}`);
      baselineSignature = {
        title: '',
        headings: '',
        metaDesc: '',
        bodyTextSample: '',
        linkCount: 0,
        imageCount: 0,
        scriptCount: 0,
        cssCount: 0,
        httpStatus: baseline.httpStatusBaseline || 200,
      };
    }

    // ===== CONTENT ANALYSIS (only if main content changed) =====
    if (mainContentChanged) {
      this.logger.debug('Analyzing content changes');

      // Component-level changes
      if (baseline.titleHash !== titleHash) {
        differenceScore += 10;
        this.logger.debug('Title changed');
      }

      if (baseline.metaDescHash !== metaDescHash) {
        differenceScore += 5;
        this.logger.debug('Meta description changed');
      }

      if (baseline.bodyTextHash !== bodyTextHash) {
        differenceScore += 10;
        this.logger.debug('Body text changed');
      }

      if (baseline.structureHash !== structureHash) {
        differenceScore += 15;
        this.logger.debug('Page structure changed');
      }

      // Element count changes (conservative thresholds)
      const linkChangePct =
        baselineSignature.linkCount > 0 ? Math.abs(baselineSignature.linkCount - contentSignature.linkCount) / baselineSignature.linkCount : 0;
      const imageChangePct =
        baselineSignature.imageCount > 0 ? Math.abs(baselineSignature.imageCount - contentSignature.imageCount) / baselineSignature.imageCount : 0;
      const scriptChangePct =
        baselineSignature.scriptCount > 0
          ? Math.abs(baselineSignature.scriptCount - contentSignature.scriptCount) / baselineSignature.scriptCount
          : 0;

      if (linkChangePct > 0.6) differenceScore += 6;
      if (imageChangePct > 0.6) differenceScore += 4;
      if (scriptChangePct > 0.4) differenceScore += 10; // Scripts are critical

      // HTTP status change
      if (baseline.httpStatusBaseline && baseline.httpStatusBaseline !== httpData.status) {
        if (httpData.status >= 400) {
          differenceScore += 20; // Error status is significant
        } else {
          differenceScore += 5; // Other status changes
        }
      }
    }

    // ===== OPTIMIZED ROUTE ANALYSIS =====
    if (baseline.crawlingEnabled && baseline.discoveredRoutes && baseline.discoveredRoutes.length > 0) {
      routeAnalysis = await this.analyzeRouteChanges(website, baseline, differenceScore);
      differenceScore += routeAnalysis.newRoutes * 3 + routeAnalysis.removedRoutes * 8 + routeAnalysis.modifiedRoutes * 5;
    }

    // ===== CONDITIONAL AI ANALYSIS =====
    const CHECK_CONTENT_WITH_AI = website.checkContentWithAI;
    console.log(`AI analysis enabled: ${CHECK_CONTENT_WITH_AI}`);

    if (CHECK_CONTENT_WITH_AI && baseline.aiAnalysisEnabled) {
      this.logger.debug('Running AI analysis for significant changes');
      try {
        aiResult = await compareContentWithAI(contentSignature, baselineSignature);

        // Conservative AI integration
        if (aiResult.isHacked && aiResult.confidence >= 85) {
          differenceScore = Math.max(differenceScore, 75);
        } else if (aiResult.isHacked && aiResult.confidence >= 70) {
          differenceScore = Math.max(differenceScore, 55);
        } else if (aiResult.isHacked && aiResult.confidence >= 50) {
          differenceScore += 15;
        } else if (!aiResult.isHacked && aiResult.confidence >= 80 && differenceScore < 50) {
          // AI is confident it's not hacked - reduce score to avoid false positives
          this.logger.debug('AI analysis indicates no hacking with high confidence');
          differenceScore = Math.max(differenceScore * 0.7, 5);
        }
      } catch (error) {
        this.logger.warn(`AI analysis failed: ${error.message}`);
      }
    }

    // ===== DETERMINE SEVERITY =====
    const sensitivity = baseline.sensitivityLevel || 50;
    const criticalThreshold = Math.max(55, 90 - sensitivity * 0.3);
    const warningThreshold = Math.max(30, criticalThreshold - 25);
    const lowThreshold = Math.max(10, warningThreshold - 15);

    let severity: AlertSeverity;
    let status: CheckStatus;
    let alertGenerated = false;
    let message: string;

    if (differenceScore >= criticalThreshold) {
      severity = AlertSeverity.CRITICAL;
      status = CheckStatus.FAIL;
      alertGenerated = true;
      message =
        aiResult?.isHacked && aiResult.confidence >= 70
          ? `AI-confirmed defacement: ${aiResult.reason}`
          : 'Critical changes detected - possible website compromise';
    } else if (differenceScore >= warningThreshold) {
      severity = AlertSeverity.MEDIUM;
      status = CheckStatus.FAIL;
      alertGenerated = true;
      message = aiResult?.isHacked ? `Significant changes with security concerns: ${aiResult.reason}` : 'Significant website changes detected';
    } else if (differenceScore >= lowThreshold) {
      severity = AlertSeverity.LOW;
      status = CheckStatus.WARNING;
      alertGenerated = true;
      message = 'Minor website changes detected';
    } else {
      severity = AlertSeverity.INFO;
      status = CheckStatus.PASS;
      alertGenerated = false;
      message = 'Website changes within normal parameters';
    }

    // ===== SMART BASELINE UPDATE =====
    await this.updateBaselineIfNeeded(
      baseline,
      contentSignature,
      mainContentHash,
      titleHash,
      metaDescHash,
      bodyTextHash,
      structureHash,
      httpData,
      mainContentChanged,
      differenceScore,
      warningThreshold,
      aiResult,
      routeAnalysis,
    );

    return {
      id: null, // This will be set when saved to the database
      websiteId: website.id,
      checkType: MonitoringCheckType.DEFACEMENT,
      timestamp: new Date(),
      severity,
      status,
      details: {
        message,
        differenceScore,
        thresholds: {
          critical: criticalThreshold,
          warning: warningThreshold,
          low: lowThreshold,
        },
        changes: {
          mainContentChanged,
          titleChanged: mainContentChanged && baseline.titleHash !== titleHash,
          bodyTextChanged: mainContentChanged && baseline.bodyTextHash !== bodyTextHash,
          structureChanged: mainContentChanged && baseline.structureHash !== structureHash,
          httpStatusChanged: baseline.httpStatusBaseline !== httpData.status,
        },
        routeAnalysis,
        aiAnalysis: aiResult
          ? {
            isHacked: aiResult.isHacked,
            confidence: aiResult.confidence,
            reason: aiResult.reason,
          }
          : null,
        baselineVersion: baseline.baselineVersion,
        optimized: true,
      },
      alertGenerated,
      rawData: JSON.stringify({
        contentSignature,
        mainContentHash,
        titleHash,
        metaDescHash,
        bodyTextHash,
        structureHash,
        httpData,
      }),
    };
  }

  /**
   * Analyzes route changes efficiently - only checking routes that actually changed
   */
  private async analyzeRouteChanges(
    website: BreachCheckWebsites,
    baseline: BreachCheckWebsiteBaseline,
    currentScore: number,
  ): Promise<RouteChangeAnalysis> {
    this.logger.debug(`Analyzing route changes for ${website.url}`);

    try {
      const currentCrawledUrls = await this.crawlService.crawlWebsite(website.url, baseline.maxCrawlDepth || 2, baseline.maxCrawlUrls || 20);

      const baselineRoutes = baseline.discoveredRoutes || [];
      const baselineRoutesMap = new Map(baselineRoutes.map(route => [route.path, route.contentHash]));
      const currentRoutesMap = new Map<string, string>();
      const changedRoutes: Array<{
        path: string;
        changeType: 'new' | 'removed' | 'modified';
        oldHash?: string;
        newHash?: string;
      }> = [];

      // Process current routes - only fetch content for routes that existed before
      for (const url of currentCrawledUrls) {
        try {
          const urlObj = new URL(url);
          const path = urlObj.pathname + urlObj.search;

          if (baselineRoutesMap.has(path)) {
            // Route existed in baseline - check if it changed
            const { html: routeHtml } = await fetchRenderedPageWithPuppeteer(url);
            const routeContentHash = crypto.createHash('md5').update(routeHtml).digest('hex');
            currentRoutesMap.set(path, routeContentHash);

            const oldHash = baselineRoutesMap.get(path);
            if (oldHash !== routeContentHash) {
              changedRoutes.push({
                path,
                changeType: 'modified',
                oldHash,
                newHash: routeContentHash,
              });
            }
          } else {
            // New route discovered
            changedRoutes.push({
              path,
              changeType: 'new',
            });
            // For new routes, we still need to get the hash for future comparisons
            try {
              const { html: routeHtml } = await fetchRenderedPageWithPuppeteer(url);
              const routeContentHash = crypto.createHash('md5').update(routeHtml).digest('hex');
              currentRoutesMap.set(path, routeContentHash);
            } catch (error) {
              this.logger.warn(`Failed to hash new route ${url}: ${error.message}`);
            }
          }
        } catch (error) {
          this.logger.warn(`Failed to process route ${url}: ${error.message}`);
        }
      }

      // Check for removed routes
      const currentPaths = new Set([
        ...Array.from(currentRoutesMap.keys()),
        ...currentCrawledUrls.map(url => {
          const urlObj = new URL(url);
          return urlObj.pathname + urlObj.search;
        }),
      ]);

      for (const baselineRoute of baselineRoutes) {
        if (!currentPaths.has(baselineRoute.path)) {
          changedRoutes.push({
            path: baselineRoute.path,
            changeType: 'removed',
            oldHash: baselineRoute.contentHash,
          });
        }
      }

      const analysis: RouteChangeAnalysis = {
        newRoutes: changedRoutes.filter(r => r.changeType === 'new').length,
        removedRoutes: changedRoutes.filter(r => r.changeType === 'removed').length,
        modifiedRoutes: changedRoutes.filter(r => r.changeType === 'modified').length,
        totalCurrentRoutes: currentCrawledUrls.length,
        totalBaselineRoutes: baselineRoutes.length,
        changedRoutes: changedRoutes.slice(0, 20), // Limit for response size
      };

      this.logger.debug(
        `Route analysis complete - New: ${analysis.newRoutes}, Removed: ${analysis.removedRoutes}, Modified: ${analysis.modifiedRoutes}`,
      );

      return analysis;
    } catch (error) {
      this.logger.error(`Route analysis failed for ${website.url}: ${error.message}`);
      return {
        newRoutes: 0,
        removedRoutes: 0,
        modifiedRoutes: 0,
        totalCurrentRoutes: 0,
        totalBaselineRoutes: baseline.discoveredRoutes?.length || 0,
        changedRoutes: [],
      };
    }
  }

  /**
   * Updates baseline intelligently based on changes and conditions
   */
  private async updateBaselineIfNeeded(
    baseline: BreachCheckWebsiteBaseline,
    contentSignature: ContentSignature,
    mainContentHash: string,
    titleHash: string,
    metaDescHash: string,
    bodyTextHash: string,
    structureHash: string,
    httpData: any,
    mainContentChanged: boolean,
    differenceScore: number,
    warningThreshold: number,
    aiResult: AICheckResult | null,
    routeAnalysis: RouteChangeAnalysis | null,
  ): Promise<void> {
    this.logger.debug(`Updating baseline for ${baseline.websiteId} if needed`);
    // Only update if significant changes detected
    if (differenceScore < warningThreshold && !mainContentChanged) {
      this.logger.debug(`No significant changes for ${baseline.websiteId} - skipping baseline update`);
      return;
    }
    this.logger.debug(`Significant changes detected for ${baseline.websiteId} - updating baseline`);
    // Update the baseline with new data
    baseline.mainContentHash = mainContentHash;
    baseline.contentSnapshot = JSON.stringify(contentSignature);
    baseline.titleHash = titleHash;
    baseline.metaDescHash = metaDescHash;
    baseline.bodyTextHash = bodyTextHash;
    baseline.structureHash = structureHash;
    baseline.httpStatusBaseline = httpData.status;
    baseline.lastContentUpdate = new Date();
    baseline.lastUpdated = new Date();
    baseline.baselineVersion += 1;
    baseline.discoveredRoutes = routeAnalysis?.changedRoutes.map(route => ({
      path: route.path,
      contentHash: route.newHash || route.oldHash || '',
      lastChecked: new Date(),
      status: route.changeType === 'modified' ? 'changed' : route.changeType === 'new' ? 'active' : 'inactive',
      httpStatus: undefined,
    }));
    baseline.routesHash = routeAnalysis
      ? crypto
        .createHash('md5')
        .update(
          routeAnalysis.changedRoutes
            .map(route => `${route.path}:${route.newHash || route.oldHash || ''}`)
            .sort()
            .join('|'),
        )
        .digest('hex')
      : baseline.routesHash;
    baseline.lastCrawlUpdate = new Date();
    baseline.aiAnalysisEnabled = aiResult ? true : baseline.aiAnalysisEnabled; // Only enable if AI analysis was performed
    baseline.crawlingEnabled = routeAnalysis ? true : baseline.crawlingEnabled; // Only enable crawling if routes were analyzed
    baseline.sensitivityLevel = Math.max(10, Math.min(100, baseline.sensitivityLevel || 50)); // Ensure sensitivity is within bounds
    baseline.maxCrawlDepth = Math.max(1, Math.min(5, baseline.maxCrawlDepth || 2)); // Ensure depth is reasonable
    baseline.maxCrawlUrls = Math.max(10, Math.min(100, baseline.maxCrawlUrls || 20)); // Ensure URL limit is reasonable
    // Save the updated baseline
    await this.websiteBaselineRepository.save(baseline);
    this.logger.log(`Baseline updated for ${baseline.websiteId} - version ${baseline.baselineVersion}`);
  }

  private async storeCheckResult(
    websiteId: number,
    checkType: MonitoringCheckType,
    status: CheckStatus,
    severity: AlertSeverity,
    details: Record<string, any>,
    alertGenerated: boolean,
    rawData: string | null = null,
    responseTimeMs: number | null = null,
    timestamp: Date = new Date(),
  ): Promise<void> {
    this.logger.debug(`Storing check result for website ID ${websiteId} - Check Type: ${checkType}, Status: ${status}`);
    const checkResult = this.checkResultRepository.create({
      websiteId,
      checkType,
      status,
      severity,
      details,
      alertGenerated,
      rawData,
      responseTimeMs,
      timestamp,
    });
    await this.checkResultRepository.save(checkResult);
  }
}
