import type { Pool } from 'pg';
import { unlink } from 'fs/promises';

const NTFY_URL = process.env.NTFY_URL || '';
const NTFY_TOPIC = process.env.NTFY_TOPIC || 'muzick';
const SYSTEM_USER_ID = '00000000-0000-0000-0000-000000000000';

async function sendNtfy(title: string, message: string): Promise<void> {
  if (!NTFY_URL) return;
  try {
    await fetch(`${NTFY_URL}/${NTFY_TOPIC}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ title, message, priority: 3 }),
    });
  } catch (err) {
    console.warn('[Cleanup] ntfy send failed:', err);
  }
}

export class CleanupSweepService {
  constructor(private pgClient: Pool) {}

  async runSweep(): Promise<{ warned: number; deleted: number }> {
    const warned = await this.advanceToWarned();
    const deleted = await this.finalizeDeleted();
    return { warned, deleted };
  }

  /**
   * Find HIDDEN dislikes past their grace period → send ntfy warning, mark WARNED.
   */
  private async advanceToWarned(): Promise<number> {
    const res = await this.pgClient.query<{ track_id: string; track_title: string; track_artist: string }>(
      `SELECT d.track_id, t.title AS track_title, t.artist AS track_artist
       FROM dislikes d
       JOIN tracks t ON t.id = d.track_id
       WHERE d.state = 'HIDDEN'
         AND NOW() > d.disliked_at + (d.grace_hours || ' hours')::interval`
    );

    for (const row of res.rows) {
      await this.pgClient.query(
        `UPDATE dislikes SET warned_at = NOW(), state = 'WARNED' WHERE track_id = $1`,
        [row.track_id]
      );
      await sendNtfy(
        'Track scheduled for deletion',
        `"${row.track_title}" by ${row.track_artist} will be permanently deleted in 24 hours. Restore it from Quarantine to keep it.`
      );
      console.log(`[Cleanup] Warned: ${row.track_title} (${row.track_id})`);
    }

    return res.rows.length;
  }

  /**
   * Find WARNED dislikes where 24h has passed since warned_at → delete file + DB record.
   */
  private async finalizeDeleted(): Promise<number> {
    const res = await this.pgClient.query<{ track_id: string; track_path: string; track_title: string }>(
      `SELECT d.track_id, t.path AS track_path, t.title AS track_title
       FROM dislikes d
       JOIN tracks t ON t.id = d.track_id
       WHERE d.state = 'WARNED'
         AND NOW() > d.warned_at + INTERVAL '24 hours'`
    );

    let deleted = 0;
    for (const row of res.rows) {
      try {
        await unlink(row.track_path);
      } catch (err: any) {
        if (err.code !== 'ENOENT') {
          console.error(`[Cleanup] Failed to delete file ${row.track_path}:`, err);
          continue;
        }
      }

      try {
        await this.pgClient.query('BEGIN');
        await this.pgClient.query(
          `INSERT INTO feedback (user_id, track_id, action) VALUES ($1, $2, 'deleted_permanent')`,
          [SYSTEM_USER_ID, row.track_id]
        );
        await this.pgClient.query('DELETE FROM tracks WHERE id = $1', [row.track_id]);
        await this.pgClient.query('COMMIT');
        deleted++;
        console.log(`[Cleanup] Permanently deleted: ${row.track_title} (${row.track_id})`);
      } catch (err) {
        await this.pgClient.query('ROLLBACK');
        console.error(`[Cleanup] DB deletion failed for ${row.track_id}:`, err);
      }
    }

    return deleted;
  }
}
