import { Router } from 'express';
import multer from 'multer';
import { join } from 'path';
import { tmpdir } from 'os';
import { rm, writeFile } from 'fs';
import { promisify } from 'util';
import { whisperService } from '../services/whisper.service.js';
import { raspiService } from '../services/raspi.service.js';
import { llamacppService } from '../services/llama.service.js';
const unlinkAsync = promisify(rm);
const writeFileAsync = promisify(writeFile);

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}` });
  }
});

router.post('/upload', upload.single('file'), async (req, res) => {
  let tmpFile: string | undefined;
  let tmpTxt: 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);

    const transcription = await whisperService.transcribe(tmpFile);
    console.log(transcription);

    const txtPath = join(tmpdir(), `quibot-audio-${Date.now()}.txt`);
    tmpTxt = txtPath;
    await writeFileAsync(txtPath, transcription);

    const llmResponse = await llamacppService.chatWithPreamble(transcription).catch(
      (err: unknown) => {
        const msg = err instanceof Error ? err.message : String(err);
        console.error(`[audio] llama.cpp failed: ${msg}`);
        return undefined;
      },
    );

    res.json({
      transcription,
      llmResponse,
      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
      }
    }
    if (tmpTxt) {
      try {
        await unlinkAsync(tmpTxt);
      } catch {
        // ignore cleanup errors
      }
    }
  }
});

export default router;
