// supersep.ts — SuperSep stem separation route (proxy to ace-server)
//
// Routes:
//   POST /api/supersep/separate — start separation (reads file from disk)
//   GET  /api/supersep/:jobId/progress — poll job progress
//   GET  /api/supersep/:jobId/result — get stem list metadata
//   GET  /api/supersep/:jobId/stem/:index — download individual stem WAV
//   POST /api/supersep/recombine — remix stems with volume/mute controls

import { Router } from 'express';
import { config } from '../config.js';
import { ensureEngineFormat } from '../services/audioConvert.js';
import path from 'path';

const router = Router();

const ACE_URL = config.aceServer.url;

// POST /api/supersep/separate
// Body (JSON): { audioUrl: "/references/uuid.flac" }
// Query: level=0..3 (BASIC/VOCAL_SPLIT/FULL/MAXIMUM)
// Reads the file from disk, converts non-WAV/MP3 to WAV, forwards to ace-server.
router.post('/separate', async (req, res) => {
  try {
    const level = parseInt(String(req.query.level ?? '0'), 10);
    const { audioUrl } = req.body || {};

    if (!audioUrl || typeof audioUrl !== 'string') {
      return res.status(400).json({ error: 'audioUrl required in request body' });
    }

    // Resolve server-side file path from URL
    // audioUrl is like "/references/uuid.flac" → data/references/uuid.flac
    const basename = path.basename(audioUrl);
    let filePath: string;
    if (audioUrl.startsWith('/references/')) {
      filePath = path.join(config.data.dir, 'references', basename);
    } else if (audioUrl.startsWith('/audio/')) {
      filePath = path.join(config.data.audioDir, basename);
    } else {
      // Fallback: try in references
      filePath = path.join(config.data.dir, 'references', basename);
    }

    console.log(`[SuperSep] separate: level=${level}, file=${filePath}`);

    // Read and convert to engine-compatible format (WAV/MP3)
    let audioBody: Buffer;
    try {
      audioBody = ensureEngineFormat(filePath);
    } catch (err: any) {
      console.error(`[SuperSep] Format conversion failed:`, err.message);
      return res.status(400).json({ error: `Audio conversion failed: ${err.message}` });
    }

    console.log(`[SuperSep] Forwarding ${audioBody.length} bytes to ace-server`);

    // Forward WAV/MP3 body to ace-server
    const aceRes = await fetch(
      `${ACE_URL}/supersep/separate?level=${level}`,
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/octet-stream' },
        body: audioBody,
      }
    );

    if (!aceRes.ok) {
      const err = await aceRes.text();
      console.error(`[SuperSep] ace-server returned ${aceRes.status}: ${err}`);
      return res.status(aceRes.status).json({ error: err });
    }

    const data = await aceRes.json();
    res.json(data);
  } catch (err: any) {
    console.error('[SuperSep] separate error:', err.message);
    res.status(500).json({ error: err.message });
  }
});

// GET /api/supersep/:jobId/progress
router.get('/:jobId/progress', async (req, res) => {
  try {
    const aceRes = await fetch(
      `${ACE_URL}/supersep/progress?id=${req.params.jobId}`
    );
    const data = await aceRes.json();
    res.json(data);
  } catch (err: any) {
    res.status(500).json({ error: err.message });
  }
});

// GET /api/supersep/:jobId/result
router.get('/:jobId/result', async (req, res) => {
  try {
    const aceRes = await fetch(
      `${ACE_URL}/supersep/result?id=${req.params.jobId}`
    );
    if (!aceRes.ok) {
      return res.status(aceRes.status).json(await aceRes.json());
    }
    const data = await aceRes.json();
    res.json(data);
  } catch (err: any) {
    res.status(500).json({ error: err.message });
  }
});

// GET /api/supersep/:jobId/stem/:index — proxy WAV download
router.get('/:jobId/stem/:index', async (req, res) => {
  try {
    const aceRes = await fetch(
      `${ACE_URL}/supersep/serve?id=${req.params.jobId}&stem=${req.params.index}`
    );
    if (!aceRes.ok) {
      return res.status(aceRes.status).json({ error: 'Failed to fetch stem' });
    }
    const buf = Buffer.from(await aceRes.arrayBuffer());
    res.set('Content-Type', 'audio/wav');
    res.set('Content-Disposition', `attachment; filename="stem_${req.params.index}.wav"`);
    res.send(buf);
  } catch (err: any) {
    res.status(500).json({ error: err.message });
  }
});

// POST /api/supersep/recombine — remix stems and return WAV
router.post('/recombine', async (req, res) => {
  try {
    const aceRes = await fetch(`${ACE_URL}/supersep/recombine`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(req.body),
    });
    if (!aceRes.ok) {
      return res.status(aceRes.status).json(await aceRes.json());
    }
    const buf = Buffer.from(await aceRes.arrayBuffer());
    res.set('Content-Type', 'audio/wav');
    res.send(buf);
  } catch (err: any) {
    res.status(500).json({ error: err.message });
  }
});

export default router;
