import { Router } from 'express';
import multer from 'multer';
import { execFile } from 'child_process';
import { tmpdir } from 'os';
import { join } from 'path';
import { promisify } from 'util';
import { writeFile, unlink } from 'fs';
import { raspiService } from '../services/raspi.service.js';

const execFileAsync = promisify(execFile);
const writeFileAsync = promisify(writeFile);
const unlinkAsync = promisify(unlink);

const router = Router();

const upload = multer({ storage: multer.memoryStorage() });

router.get('/incoming', async (_req, res) => {
  try {
    const result = await raspiService.listIncomingAudio();
    res.json(result);
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : 'Unknown error';
    res.status(500).json({ error: `List incoming failed: ${message}` });
  }
});

router.post('/lock/:filename', async (req, res) => {
  try {
    const { filename } = req.params;
    const result = await raspiService.lockAudio({ filename });
    res.json(result);
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : 'Unknown error';
    res.status(500).json({ error: `Lock audio failed: ${message}` });
  }
});

router.post('/unlock/:filename', async (req, res) => {
  try {
    const { filename } = req.params;
    const result = await raspiService.unlockAudio({ filename });
    res.json(result);
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : 'Unknown error';
    res.status(500).json({ error: `Unlock audio failed: ${message}` });
  }
});

router.post('/cancel/:filename', async (req, res) => {
  try {
    const { filename } = req.params;
    const result = await raspiService.cancelAudio({ filename });
    res.json(result);
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : 'Unknown error';
    res.status(500).json({ error: `Cancel audio failed: ${message}` });
  }
});

router.post('/process/:filename', async (req, res) => {
  try {
    const { filename } = req.params;
    const result = await raspiService.processAudio({ filename });
    res.json(result);
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : 'Unknown error';
    res.status(500).json({ error: `Process audio failed: ${message}` });
  }
});

const whisperModel = process.env.WHISPER_MODEL ?? 'base';
const whisperLanguage = process.env.WHISPER_LANGUAGE ?? 'ca';

router.post('/upload', upload.single('file'), async (req, res) => {
  let tmpFile: string | undefined;
  try {
    if (!req.file) {
      return res.status(400).json({ error: 'No audio file provided' });
    }

    const ext = req.file.originalname.split('.').pop()?.toLowerCase() || 'wav';
    tmpFile = join(tmpdir(), `quibot-audio-${Date.now()}.${ext}`);
    await writeFileAsync(tmpFile, req.file.buffer);

    console.log(`[whisper] Model: ${whisperModel}, Language: ${whisperLanguage}, File: ${tmpFile}`);

    const { stdout, stderr } = await execFileAsync('whisper', [
      tmpFile,
      '--model', whisperModel,
      '--language', whisperLanguage,
      '--output_format', 'txt',
    ], { maxBuffer: 50 * 1024 * 1024 });

    if (stderr) {
      console.log(`[whisper] stderr: ${stderr}`);
    }

    const transcription = stdout.trim();

    res.json({
      transcription,
      originalFilename: req.file.originalname,
    });
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : 'Unknown error';
    res.status(500).json({ error: `Audio transcription failed: ${message}` });
  } finally {
    if (tmpFile) {
      try {
        await unlinkAsync(tmpFile);
      } catch {
        // ignore cleanup errors
      }
    }
  }
});

export default router;
