import { db } from '../../database/db';
import { NetworkDriverFactory } from '../network/driver.factory';
import { SubscriberDTO } from '../network/driver.interface';

export interface DisconnectionRunReport {
  timestamp: string;
  subscribersScanned: number;
  expiredCount: number;
  disconnectedSubscribers: Array<{
    username: string;
    driver_type: string;
    expiredAt: string;
    actionResult: any;
  }>;
}

export class DisconnectionWorker {
  private static isRunning = false;

  /**
   * Scans database subscription states.
   * Upon matching expiration bounds (expiration_date <= NOW()), status changes to 'expired'.
   * Issues RADIUS CoA packet or MikroTik profile switch to walled-garden address list.
   */
  public static async executeScan(): Promise<DisconnectionRunReport> {
    if (this.isRunning) {
      return {
        timestamp: new Date().toISOString(),
        subscribersScanned: db.subscribers.length,
        expiredCount: 0,
        disconnectedSubscribers: []
      };
    }

    this.isRunning = true;
    const now = new Date();
    const disconnectedList: DisconnectionRunReport['disconnectedSubscribers'] = [];

    try {
      for (const subscriber of db.subscribers) {
        const expiryTime = new Date(subscriber.expiration_date).getTime();
        
        // If expired and not yet suspended/walled_garden
        if (expiryTime <= now.getTime() && subscriber.status === 'active') {
          subscriber.status = 'expired';
          subscriber.updated_at = now.toISOString();

          const pkg = db.packages.find(p => p.id === subscriber.package_id);
          const subscriberDTO: SubscriberDTO = {
            id: subscriber.id,
            username: subscriber.username,
            driver_type: subscriber.driver_type,
            ip_address: subscriber.ip_address,
            mac_address: subscriber.mac_address,
            speed_mbps: pkg?.speed_mbps || 20,
            mikrotik_profile: pkg?.mikrotik_profile_name,
            radius_group: pkg?.radius_group_name,
            status: 'expired'
          };

          // Execute driver suspension & walled-garden redirection
          const driverResult = await NetworkDriverFactory.executeAction(
            'suspendUser',
            subscriberDTO,
            `Automated Disconnection Scan: Expiration date (${subscriber.expiration_date}) reached`
          );

          disconnectedList.push({
            username: subscriber.username,
            driver_type: subscriber.driver_type,
            expiredAt: subscriber.expiration_date,
            actionResult: driverResult
          });

          db.logAudit('WORKER', 'DISCONNECTION_ENGINE', 'SUBSCRIBER_DROPPED_TO_WALLED_GARDEN', {
            username: subscriber.username,
            driver: subscriber.driver_type,
            expiredAt: subscriber.expiration_date,
            driverResult
          });
        }
      }

      db.persist();

      return {
        timestamp: now.toISOString(),
        subscribersScanned: db.subscribers.length,
        expiredCount: disconnectedList.length,
        disconnectedSubscribers: disconnectedList
      };
    } finally {
      this.isRunning = false;
    }
  }

  /**
   * Start 5-minute interval timer loop
   */
  public static startScheduler(intervalMs = 5 * 60 * 1000) {
    console.log(`[DisconnectionWorker] Initialized 5-minute subscription expiration scanner.`);
    setInterval(async () => {
      try {
        const report = await this.executeScan();
        if (report.expiredCount > 0) {
          console.log(`[DisconnectionWorker] Dropped ${report.expiredCount} expired subscribers to walled-garden.`);
        }
      } catch (err) {
        console.error('[DisconnectionWorker] Scan error:', err);
      }
    }, intervalMs);
  }
}
