import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { PesEmailTracking } from './entities/pes-email-tracking.entity';
import { PesEmailEvent } from './entities/pes-email-event.entity';

@Injectable()
export class PesTrackingService {
  private readonly logger = new Logger(PesTrackingService.name);

  constructor(
    @InjectRepository(PesEmailTracking)
    private readonly emailTrackingRepo: Repository<PesEmailTracking>,
    @InjectRepository(PesEmailEvent)
    private readonly emailEventRepo: Repository<PesEmailEvent>,
  ) {}

  async createEmailTrackingRecord(email: string, campaignTrackingId: string): Promise<PesEmailTracking> {
    return this.emailTrackingRepo.save({
      email,
      campaignTrackingId,
      isOpened: false,
      openCount: 0,
      clickCount: 0,
    });
  }

  async recordEmailOpen(trackingId: string, ipAddress?: string, userAgent?: string): Promise<void> {
    const trackingRecord = await this.emailTrackingRepo.findOneBy({ campaignTrackingId: trackingId });

    if (!trackingRecord) {
      this.logger.warn(`No tracking record found for ID: ${trackingId}`);
      return;
    }

    // Record the event
    await this.emailEventRepo.save({
      type: 'OPEN',
      ipAddress,
      userAgent,
      emailTracking: trackingRecord,
    });

    // Update tracking record
    await this.emailTrackingRepo.update(trackingRecord.id, {
      isOpened: true,
      openCount: () => 'open_count + 1',
      firstOpenedAt: trackingRecord.firstOpenedAt || new Date(),
    });
  }

  async recordEmailClick(trackingId: string, originalUrl: string, ipAddress?: string, userAgent?: string): Promise<void> {
    const trackingRecord = await this.emailTrackingRepo.findOneBy({ campaignTrackingId: trackingId });

    if (!trackingRecord) {
      this.logger.warn(`No tracking record found for ID: ${trackingId}`);
      return;
    }

    // Record the event
    await this.emailEventRepo.save({
      type: 'CLICK',
      originalUrl,
      ipAddress,
      userAgent,
      emailTracking: trackingRecord,
    });

    // Update tracking record
    await this.emailTrackingRepo.update(trackingRecord.id, {
      clickCount: () => 'click_count + 1',
    });
  }

  async updateEmailTracking(trackingId: string, updates: Partial<PesEmailTracking>): Promise<PesEmailTracking> {
    try {
      const trackingRecord = await this.emailTrackingRepo.findOneBy({ campaignTrackingId: trackingId });

      if (!trackingRecord) {
        throw new Error(`No tracking record found for ID: ${trackingId}`);
      }

      // Update the tracking record with the provided updates
      Object.assign(trackingRecord, updates);
      return await this.emailTrackingRepo.save(trackingRecord);
    } catch (error) {
      this.logger.error(`Failed to update tracking record for ID: ${trackingId}`, error);
      throw new Error(`Failed to update tracking record: ${error.message}`);
    }
  }
}
