import { Injectable, Logger, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { SignalService } from './signal.service';
import { MessagesService } from './messages.service';

@Injectable()
export class SignalPollingService implements OnModuleInit, OnModuleDestroy {
  private readonly logger = new Logger(SignalPollingService.name);
  private pollingInterval: NodeJS.Timeout | null = null;
  private isPolling = false;

  // Poll every 5 seconds
  private readonly POLL_INTERVAL_MS = 5000;

  constructor(
    private readonly signalService: SignalService,
    private readonly messagesService: MessagesService,
  ) {}

  onModuleInit() {
    this.startPolling();
  }

  onModuleDestroy() {
    this.stopPolling();
  }

  private startPolling() {
    this.logger.log('Starting Signal message polling...');
    this.pollingInterval = setInterval(() => this.pollMessages(), this.POLL_INTERVAL_MS);
    // Also poll immediately on startup
    this.pollMessages();
  }

  private stopPolling() {
    if (this.pollingInterval) {
      clearInterval(this.pollingInterval);
      this.pollingInterval = null;
      this.logger.log('Stopped Signal message polling');
    }
  }

  private async pollMessages() {
    // Prevent concurrent polling
    if (this.isPolling) {
      return;
    }

    this.isPolling = true;

    try {
      const linkedNumber = await this.signalService.getLinkedNumber();
      if (!linkedNumber) {
        // No account linked, skip polling
        return;
      }

      const messages = await this.signalService.receiveMessages(linkedNumber);

      if (messages && messages.length > 0) {
        this.logger.log(`Received ${messages.length} message(s) from Signal`);

        for (const msg of messages) {
          await this.processMessage(msg);
        }
      }
    } catch (error: any) {
      // Only log errors that aren't connection issues (Signal CLI might not be ready)
      if (!error.message?.includes('ECONNREFUSED')) {
        this.logger.error(`Error polling messages: ${error.message}`);
      }
    } finally {
      this.isPolling = false;
    }
  }

  private async processMessage(msg: any) {
    try {
      // Signal CLI returns messages in various formats
      // We're looking for envelope.dataMessage.message
      const envelope = msg.envelope;

      if (!envelope) {
        return;
      }

      // Get the sender's phone number
      const fromNumber = envelope.sourceNumber || envelope.source;

      // Check for data message (regular text message)
      const dataMessage = envelope.dataMessage;
      if (dataMessage?.message) {
        const content = dataMessage.message;
        const timestamp = dataMessage.timestamp?.toString();

        this.logger.debug(`Processing message from ${fromNumber}: ${content.substring(0, 50)}...`);

        await this.messagesService.processIncomingMessage(
          fromNumber,
          content,
          timestamp,
        );
      }

      // Also handle sync messages (messages sent from other linked devices)
      const syncMessage = envelope.syncMessage;
      if (syncMessage?.sentMessage?.message) {
        // This is a message we sent from another device, we can ignore it
        // or store it if needed
        this.logger.debug('Received sync message (sent from another device)');
      }
    } catch (error: any) {
      this.logger.error(`Error processing message: ${error.message}`);
    }
  }
}
