import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
import type { Incident, AutoFixResult } from './types.js';
import type { Logger } from './logger.js';

export class TaskQueue {
  private dir: string;

  constructor(incidentDir: string) {
    this.dir = incidentDir;
    fs.mkdirSync(this.dir, { recursive: true });
  }

  createIncident(
    serviceId: string,
    serviceName: string,
    error: string,
    critical: boolean,
    logger: Logger,
  ): string {
    const id = crypto.randomUUID();
    const incident: Incident = {
      id,
      serviceId,
      serviceName,
      status: 'open',
      severity: critical ? 'critical' : 'warning',
      error,
      firstFailureAt: new Date().toISOString(),
      autoFixAttempts: [],
      notifications: [],
    };

    const filename = `${this.formatTimestamp()}-${serviceId}.json`;
    const filepath = path.join(this.dir, filename);

    fs.writeFileSync(filepath, JSON.stringify(incident, null, 2));
    logger.info('Incident created', { id, serviceId, filepath });

    return id;
  }

  resolveIncident(incidentId: string, logger: Logger): void {
    const files = fs.readdirSync(this.dir).filter((f) => f.endsWith('.json'));

    for (const file of files) {
      const filepath = path.join(this.dir, file);
      try {
        const content = fs.readFileSync(filepath, 'utf-8');
        const incident: Incident = JSON.parse(content);

        if (incident.id === incidentId && incident.status === 'open') {
          incident.status = 'resolved';
          incident.resolvedAt = new Date().toISOString();
          fs.writeFileSync(filepath, JSON.stringify(incident, null, 2));
          logger.info('Incident resolved', { id: incidentId });
          return;
        }
      } catch {
        // Skip malformed files
      }
    }
  }

  addAutoFixAttempt(incidentId: string, result: AutoFixResult, logger: Logger): void {
    const files = fs.readdirSync(this.dir).filter((f) => f.endsWith('.json'));

    for (const file of files) {
      const filepath = path.join(this.dir, file);
      try {
        const content = fs.readFileSync(filepath, 'utf-8');
        const incident: Incident = JSON.parse(content);

        if (incident.id === incidentId) {
          incident.autoFixAttempts.push(result);
          fs.writeFileSync(filepath, JSON.stringify(incident, null, 2));
          return;
        }
      } catch {
        // Skip malformed files
      }
    }
  }

  addNotification(incidentId: string, type: string): void {
    const files = fs.readdirSync(this.dir).filter((f) => f.endsWith('.json'));

    for (const file of files) {
      const filepath = path.join(this.dir, file);
      try {
        const content = fs.readFileSync(filepath, 'utf-8');
        const incident: Incident = JSON.parse(content);

        if (incident.id === incidentId) {
          incident.notifications.push({ sentAt: new Date().toISOString(), type });
          fs.writeFileSync(filepath, JSON.stringify(incident, null, 2));
          return;
        }
      } catch {
        // Skip malformed files
      }
    }
  }

  cleanOldIncidents(maxAgeDays: number, logger: Logger): void {
    const maxAgeMs = maxAgeDays * 24 * 60 * 60 * 1000;
    const files = fs.readdirSync(this.dir).filter((f) => f.endsWith('.json'));

    for (const file of files) {
      const filepath = path.join(this.dir, file);
      try {
        const stat = fs.statSync(filepath);
        if (Date.now() - stat.mtimeMs > maxAgeMs) {
          const content = fs.readFileSync(filepath, 'utf-8');
          const incident: Incident = JSON.parse(content);
          if (incident.status === 'resolved') {
            fs.unlinkSync(filepath);
            logger.info('Cleaned old incident', { file });
          }
        }
      } catch {
        // Skip
      }
    }
  }

  private formatTimestamp(): string {
    return new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
  }
}
