import express = require('express');
import type { Request, Response } from 'express';
import multer = require('multer');
const { whisperClient, litellmClient } = require('../utils/ai');
const { transcribeWithAWS, isAWSTranscribeConfigured } = require('../utils/transcribeAWS');
const { transcribeWithLocal, isLocalWhisperConfigured } = require('../utils/transcribeLocal');
const { transcribeWithGemini, isGoogleSTTConfigured } = require('../utils/transcribeGoogle');
const { authMiddleware } = require('../middleware/auth');
const logger = require('../utils/logger');
const { gatewayUrl } = require('../utils/errors');

const router = express.Router();
const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 25 * 1024 * 1024 } });

// Provider priority (auto-detect):
// TRANSCRIBE_PROVIDER=google → Vertex AI / Gemini (direct, HIPAA eligible)
// TRANSCRIBE_PROVIDER=aws    → Amazon Transcribe (HIPAA eligible)
// TRANSCRIBE_PROVIDER=local  → local whisper.cpp / faster-whisper
// TRANSCRIBE_PROVIDER=openai → OpenAI Whisper (direct)
// TRANSCRIBE_PROVIDER=litellm→ LiteLLM proxy (explicit only — audio routing bugs)
// Auto: google > aws > openai
function getTranscribeProvider(): string {
  const env = process.env.TRANSCRIBE_PROVIDER;
  if (env === 'google') return 'google';
  if (env === 'aws') return 'aws';
  if (env === 'local') return 'local';
  if (env === 'openai') return 'openai';
  if (env === 'litellm') return 'litellm';
  if (isGoogleSTTConfigured()) return 'google';
  if (isAWSTranscribeConfigured()) return 'aws';
  return 'openai';
}

function isTranscribeAvailable(): boolean {
  if (isGoogleSTTConfigured()) return true;
  if (isLocalWhisperConfigured()) return true;
  if (isAWSTranscribeConfigured()) return true;
  if (litellmClient) return true;
  if (whisperClient) return true;
  return false;
}

const provider = getTranscribeProvider();
const medical = process.env.AWS_TRANSCRIBE_MEDICAL === 'true';
const available = isTranscribeAvailable();
console.log('🎙️  Transcribe provider:', provider +
  (provider === 'aws' && medical ? ' (Medical)' : '') +
  (provider === 'google' ? ' (model: ' + (process.env.GOOGLE_STT_MODEL || 'gemini-2.0-flash') + ')' : '') +
  (available ? '' : ' (NOT CONFIGURED — browser speech only)'));

router.get('/transcribe/status', authMiddleware, (_req: Request, res: Response) => {
  res.json({ available, provider: available ? provider : 'none' });
});

router.post('/transcribe', authMiddleware, upload.single('audio'), async (req: Request, res: Response) => {
  try {
    if (!req.file) return res.status(400).json({ error: 'No audio' });
    const startTime = Date.now();
    const fileSize = req.file.size;

    const db = require('../db/database');
    const userPrefs = await db.get('SELECT stt_model FROM users WHERE id = ?', [req.user!.id]);
    const userModel = userPrefs?.stt_model;
    const adminSttModel: string = (await db.getSetting('stt.model')) || '';

    console.log('[Transcribe] Received ' + (fileSize / 1024).toFixed(0) + 'KB audio (' + (req.file.mimetype || 'unknown') + ') via ' + provider + (userModel ? ' (user model: ' + userModel + ')' : ''));

    if (provider === 'google') {
      const model = userModel || adminSttModel || process.env.GOOGLE_STT_MODEL || 'gemini-2.0-flash';
      const text = await transcribeWithGemini(req.file.buffer, req.file.mimetype || 'audio/webm', model);
      console.log('[Transcribe] Google/' + model + ' done in ' + (Date.now() - startTime) + 'ms');
      logger.audit(req.user!.id, 'transcribe', 'Transcribed audio via google', req, { category: 'clinical' });
      return res.json({ success: true, text, provider: 'google-' + model, duration: Date.now() - startTime });
    }

    if (provider === 'local') {
      const text = await transcribeWithLocal(req.file.buffer, req.file.mimetype || 'audio/webm');
      console.log('[Transcribe] Local done in ' + (Date.now() - startTime) + 'ms');
      logger.audit(req.user!.id, 'transcribe', 'Transcribed audio via local', req, { category: 'clinical' });
      return res.json({ success: true, text, provider: 'local-whisper', duration: Date.now() - startTime });
    }

    if (provider === 'aws') {
      if (!isAWSTranscribeConfigured()) return res.status(400).json({ error: 'AWS Transcribe not configured.' });
      const text = await transcribeWithAWS(req.file.buffer, req.file.mimetype || 'audio/webm');
      console.log('[Transcribe] AWS done in ' + (Date.now() - startTime) + 'ms');
      logger.audit(req.user!.id, 'transcribe', 'Transcribed audio via aws', req, { category: 'clinical' });
      return res.json({ success: true, text, provider: 'aws-transcribe', duration: Date.now() - startTime });
    }

    if (provider === 'litellm') {
      if (!process.env.LITELLM_API_BASE) return res.status(400).json({ error: 'LITELLM_API_BASE not set.' });
      const sttModel: string = userModel || adminSttModel || process.env.LITELLM_STT_MODEL || 'gemini-2.0-flash';
      const axios = require('axios');
      const mimeType = req.file.mimetype || 'audio/webm';

      const isTranscriptionModel = /whisper|deepgram|nova|groq|scribe|elevenlabs|transcri/i.test(sttModel);

      if (isTranscriptionModel) {
        const ext = mimeType.split('/')[1] || 'webm';
        const file = new File([new Uint8Array(req.file.buffer)], 'audio.' + ext, { type: mimeType });
        const form = new FormData();
        form.append('file', file);
        form.append('model', sttModel);
        const fetchHeaders: Record<string, string> = {};
        if (process.env.LITELLM_API_KEY) fetchHeaders['Authorization'] = 'Bearer ' + process.env.LITELLM_API_KEY;

        const sttResp = await fetch(gatewayUrl('/audio/transcriptions'), {
          method: 'POST', headers: fetchHeaders, body: form,
        }).then(r => r.json().then((d: any) => ({ data: d })));
        const text: string = sttResp.data && sttResp.data.text ? sttResp.data.text : '';
        console.log('[Transcribe] LiteLLM/' + sttModel + ' done in ' + (Date.now() - startTime) + 'ms');
        logger.audit(req.user!.id, 'transcribe', 'Transcribed audio via litellm', req, { category: 'clinical' });
        return res.json({ success: true, text: text.trim(), provider: 'litellm/' + sttModel, duration: Date.now() - startTime });
      }

      const base64audio = req.file.buffer.toString('base64');
      const headers: Record<string, string> = { 'Content-Type': 'application/json' };
      if (process.env.LITELLM_API_KEY) headers['Authorization'] = 'Bearer ' + process.env.LITELLM_API_KEY;

      const sttResp = await axios.post(gatewayUrl('/chat/completions'), {
        model: sttModel,
        messages: [{
          role: 'user',
          content: [
            { type: 'input_audio', input_audio: { data: base64audio, format: mimeType.split('/')[1] || 'webm' } },
            { type: 'text', text: 'Transcribe this audio of a medical encounter. Output the spoken words only, exactly as heard. No commentary, no formatting.' },
          ],
        }],
      }, { headers, timeout: 120000 });

      let text = '';
      if (sttResp.data && sttResp.data.choices && sttResp.data.choices[0]) {
        const msg = sttResp.data.choices[0].message;
        text = msg && msg.content ? msg.content : '';
      }
      console.log('[Transcribe] LiteLLM/' + sttModel + ' done in ' + (Date.now() - startTime) + 'ms');
      logger.audit(req.user!.id, 'transcribe', 'Transcribed audio via litellm', req, { category: 'clinical' });
      return res.json({ success: true, text: text.trim(), provider: 'litellm/' + sttModel, duration: Date.now() - startTime });
    }

    if (!whisperClient) return res.status(400).json({ error: 'Whisper not configured. Set OPENAI_API_KEY.' });
    const file = new File([new Uint8Array(req.file.buffer)], 'audio.webm', { type: req.file.mimetype || 'audio/webm' });
    const result = await whisperClient.audio.transcriptions.create({
      file, model: 'whisper-1', language: 'en',
      response_format: 'text',
      prompt: 'Medical patient encounter. Pediatric. Clinical terms, diagnoses, medications.',
    });
    const text = typeof result === 'string' ? result : result.text;
    console.log('[Transcribe] Whisper done in ' + (Date.now() - startTime) + 'ms');
    logger.audit(req.user!.id, 'transcribe', 'Transcribed audio via openai', req, { category: 'clinical' });
    res.json({ success: true, text, provider: 'openai-whisper', duration: Date.now() - startTime });
  } catch (err: any) {
    const detail = err.response && err.response.data
      ? JSON.stringify(err.response.data).substring(0, 500)
      : err.message;
    console.error('[Transcribe] Error (' + provider + '):', detail);
    res.status(500).json({ error: detail });
  }
});

export = router;
