/**
 * Interview & Media Prep Routes
 * API endpoints for interview coaching, media preparation, and communication training
 */

import express, { Request, Response } from 'express';
import { body, param, query, validationResult } from 'express-validator';
import { requireRole } from '../middleware/auth';
import { authenticateJwtOrApiToken } from '../middleware/dualAuth';
import { getModels } from '../models';
import { deriveSessionCreatedAtFromId } from '../utils/deriveSessionCreatedAt';
import { generateWithAI } from '../utils/aiProvider';
import { buildHarmonyContext, buildHarmonyTextContextBlock } from '../services/aiContext/harmonyContextService';

const router = express.Router();
router.use(authenticateJwtOrApiToken);

// ============================================
// ERROR HANDLER
// ============================================

const handleError = (res: Response, error: any) => {
  console.error('[InterviewMediaPrep] Error:', error);
  if (error.name === 'ValidationError') {
    res.status(400).json({
      error: error.message,
      details: Object.values(error.errors || {}).map((e: any) => e.message)
    });
    return;
  }
  if (error.code === 11000) {
    res.status(400).json({ error: 'Duplicate entry', message: 'This record already exists' });
    return;
  }
  res.status(500).json({ error: error.message || 'Internal server error' });
};

// ============================================
// GET ALL SESSIONS
// ============================================

router.get('/sessions', [
  query('companyId').notEmpty().withMessage('Company ID is required'),
  query('type').optional().isIn([
    'podcast', 'rapid-fire', 'interview', 'panel-discussion',
    'founder-interview', 'employee-interview', 'media-interview',
    'tv-interview', 'press-conference', 'journalist', 'investor-interview',
    'startup-interview', 'crisis-management', 'product-launch', 'custom'
  ]),
  query('status').optional().isIn(['draft', 'generating', 'completed', 'archived', 'failed']),
  query('page').optional().isInt({ min: 1 }),
  query('limit').optional().isInt({ min: 1, max: 100 }),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId, type, status, page = 1, limit = 50 } = req.query;
    const { InterviewMediaPrep } = getModels();

    let doc = await InterviewMediaPrep.findOne({ companyId: companyId as string });

    if (!doc) {
      res.json({ sessions: [], total: 0, page: Number(page), limit: Number(limit) });
      return;
    }

    let sessions = [...doc.sessions];

    // Recover createdAt for legacy rows written before the subschema declared the
    // field (strict mode dropped it then). The value is encoded in the session id,
    // so originals display consistently with duplicates without waiting on the
    // startup backfill. Read-only enrichment — the DB row is untouched here.
    sessions = sessions.map((s: any) => {
      if (s.createdAt) return s;
      const derived = deriveSessionCreatedAtFromId(s.id);
      return derived ? { ...(s.toObject?.() ?? s), createdAt: derived } : s;
    });

    // Filter by type
    if (type) {
      sessions = sessions.filter(s => s.type === type);
    }

    // Filter by status
    if (status) {
      sessions = sessions.filter(s => s.status === status);
    }

    // Sort by createdAt descending
    sessions.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());

    // Pagination
    const total = sessions.length;
    const offset = (Number(page) - 1) * Number(limit);
    const paginatedSessions = sessions.slice(offset, offset + Number(limit));

    res.json({
      sessions: paginatedSessions,
      total,
      page: Number(page),
      limit: Number(limit),
      totalPages: Math.ceil(total / Number(limit))
    });
  } catch (error: any) {
    handleError(res, error);
  }
});

// ============================================
// GET SESSION BY ID
// ============================================

router.get('/sessions/:sessionId', [
  query('companyId').notEmpty().withMessage('Company ID is required'),
  param('sessionId').notEmpty().withMessage('Session ID is required'),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId } = req.query;
    const { sessionId } = req.params;
    const { InterviewMediaPrep } = getModels();

    const doc = await InterviewMediaPrep.findOne({ companyId: companyId as string });

    if (!doc) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    const session = doc.sessions.find((s: any) => s.id === sessionId);

    if (!session) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    res.json({ session });
  } catch (error: any) {
    handleError(res, error);
  }
});

// ============================================
// CREATE SESSION
// ============================================

router.post('/sessions', [
  body('companyId').notEmpty().withMessage('Company ID is required'),
  body('name').notEmpty().withMessage('Session name is required'),
  body('type').isIn([
    'podcast', 'rapid-fire', 'interview', 'panel-discussion',
    'founder-interview', 'employee-interview', 'media-interview',
    'tv-interview', 'press-conference', 'journalist', 'investor-interview',
    'startup-interview', 'crisis-management', 'product-launch', 'custom'
  ]).withMessage('Valid preparation type is required'),
  body('speakerType').isIn(['founder', 'employee', 'ceo', 'manager', 'entrepreneur', 'student', 'other'])
    .withMessage('Valid speaker type is required'),
  body('speakerName').notEmpty().withMessage('Speaker name is required'),
  body('difficulty').optional().isIn(['beginner', 'intermediate', 'advanced', 'expert']),
  body('language').optional().isIn(['english', 'hindi', 'marathi']),
  body('audienceType').optional().isIn([
    'customers', 'investors', 'journalists', 'government',
    'students', 'business-owners', 'developers', 'general-public'
  ]),
  body('questionCount').optional().isInt({ min: 1, max: 100 }),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { InterviewMediaPrep } = getModels();
    const userId = req.user!.id;

    const {
      companyId,
      name,
      type,
      speakerType,
      speakerName,
      speakerPosition,
      speakerCompany,
      speakerIndustry,
      speakerDepartment,
      speakerBio,
      difficulty = 'intermediate',
      language = 'english',
      audienceType,
      questionCount = 10,
      includeExpertAnswers = true,
      includeFollowUps = true,
      includeCoachingTips = true,
      contextTopic,
      contextIndustry,
      contextAudience,
      contextInterviewType,
      linkedFounderId,
      linkedEmployeeId,
      linkedProductId,
      linkedBrandId,
      linkedIcpIds,
      linkedPersonaIds,
      dataSources,
      notes,
      tags
    } = req.body;

    // Generate unique session ID
    const sessionId = `imp_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;

    const newSession = {
      id: sessionId,
      name,
      type,
      status: 'draft' as const,
      speakerType,
      speakerName,
      speakerPosition,
      speakerCompany,
      speakerIndustry,
      speakerDepartment,
      speakerBio,
      difficulty,
      language,
      audienceType,
      questionCount,
      includeExpertAnswers,
      includeFollowUps,
      includeCoachingTips,
      contextTopic,
      contextIndustry,
      contextAudience,
      contextInterviewType,
      questions: [],
      coachingTips: [],
      aiGenerated: false,
      linkedFounderId,
      linkedEmployeeId,
      linkedProductId,
      linkedBrandId,
      linkedIcpIds: linkedIcpIds || [],
      linkedPersonaIds: linkedPersonaIds || [],
      dataSources: dataSources || {
        businessProfile: true,
        brand: true,
        brandStrategy: true,
        visualIdentity: true,
        brandGuidelines: true,
        icp: true,
        persona: true,
        founders: true,
      },
      version: 1,
      notes,
      tags: tags || [],
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    };

    let doc = await InterviewMediaPrep.findOne({ companyId });

    if (!doc) {
      doc = await InterviewMediaPrep.create({
        companyId,
        userId,
        sessions: [newSession],
        totalSessions: 1
      });
    } else {
      doc.sessions.push(newSession as any);
      doc.totalSessions = doc.sessions.length;
      await doc.save();
    }

    res.status(201).json({ session: newSession, documentId: doc._id });
  } catch (error: any) {
    handleError(res, error);
  }
});

// ============================================
// UPDATE SESSION
// ============================================

router.put('/sessions/:sessionId', [
  query('companyId').notEmpty().withMessage('Company ID is required'),
  param('sessionId').notEmpty().withMessage('Session ID is required'),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId } = req.query;
    const { sessionId } = req.params;
    const { InterviewMediaPrep } = getModels();

    const doc = await InterviewMediaPrep.findOne({ companyId: companyId as string });

    if (!doc) {
      res.status(404).json({ error: 'Document not found' });
      return;
    }

    const sessionIndex = doc.sessions.findIndex((s: any) => s.id === sessionId);

    if (sessionIndex === -1) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    // Update session fields
    const updates = req.body;
    const allowedUpdates = [
      'name', 'type', 'speakerType', 'speakerName', 'speakerPosition',
      'speakerCompany', 'speakerIndustry', 'speakerDepartment', 'speakerBio',
      'difficulty', 'language', 'audienceType', 'questionCount',
      'includeExpertAnswers', 'includeFollowUps', 'includeCoachingTips',
      'contextTopic', 'contextIndustry', 'contextAudience', 'contextInterviewType',
      'questions', 'coachingTips', 'status', 'notes', 'tags'
    ];

    for (const key of allowedUpdates) {
      if (updates[key] !== undefined) {
        (doc.sessions[sessionIndex] as any)[key] = updates[key];
      }
    }

    doc.sessions[sessionIndex].updatedAt = new Date().toISOString();
    await doc.save();

    res.json({ session: doc.sessions[sessionIndex] });
  } catch (error: any) {
    handleError(res, error);
  }
});

// ============================================
// CLEAR ALL SESSIONS (must come before :sessionId routes)
// ============================================

router.delete('/sessions/clear', [
  query('companyId').notEmpty().withMessage('Company ID is required'),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId } = req.query;
    const { InterviewMediaPrep } = getModels();

    const doc = await InterviewMediaPrep.findOne({ companyId: companyId as string });

    if (!doc) {
      res.json({ success: true, message: 'No sessions to clear', count: 0 });
      return;
    }

    const count = doc.sessions.length;
    doc.sessions = [];
    doc.totalSessions = 0;
    await doc.save();

    res.json({ success: true, message: 'All sessions cleared successfully', count });
  } catch (error: any) {
    handleError(res, error);
  }
});

// ============================================
// DELETE SESSION
// ============================================

router.delete('/sessions/:sessionId', [
  query('companyId').notEmpty().withMessage('Company ID is required'),
  param('sessionId').notEmpty().withMessage('Session ID is required'),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId } = req.query;
    const { sessionId } = req.params;
    const { InterviewMediaPrep } = getModels();

    const doc = await InterviewMediaPrep.findOne({ companyId: companyId as string });

    if (!doc) {
      res.status(404).json({ error: 'Document not found' });
      return;
    }

    const sessionIndex = doc.sessions.findIndex((s: any) => s.id === sessionId);

    if (sessionIndex === -1) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    doc.sessions.splice(sessionIndex, 1);
    doc.totalSessions = doc.sessions.length;
    await doc.save();

    res.json({ success: true, message: 'Session deleted successfully' });
  } catch (error: any) {
    handleError(res, error);
  }
});

// ============================================
// DUPLICATE SESSION
// ============================================

router.post('/sessions/:sessionId/duplicate', [
  query('companyId').notEmpty().withMessage('Company ID is required'),
  param('sessionId').notEmpty().withMessage('Session ID is required'),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId } = req.query;
    const { sessionId } = req.params;
    const { InterviewMediaPrep } = getModels();

    const doc = await InterviewMediaPrep.findOne({ companyId: companyId as string });

    if (!doc) {
      res.status(404).json({ error: 'Document not found' });
      return;
    }

    const originalSession = doc.sessions.find((s: any) => s.id === sessionId);

    if (!originalSession) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    // Create duplicate with new ID
    const newSessionId = `imp_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
    const duplicatedSession = {
      ...JSON.parse(JSON.stringify(originalSession)),
      id: newSessionId,
      name: `${originalSession.name} (Copy)`,
      status: 'draft' as const,
      version: 1,
      parentSessionId: sessionId,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    };

    doc.sessions.push(duplicatedSession as any);
    doc.totalSessions = doc.sessions.length;
    await doc.save();

    res.status(201).json({ session: duplicatedSession });
  } catch (error: any) {
    handleError(res, error);
  }
});

// ============================================
// GENERATE INTERVIEW CONTENT (AI)
// ============================================

router.post('/sessions/:sessionId/generate', [
  query('companyId').notEmpty().withMessage('Company ID is required'),
  param('sessionId').notEmpty().withMessage('Session ID is required'),
  body('regenerateQuestions').optional().isBoolean(),
  body('regenerateCoachingTips').optional().isBoolean(),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId } = req.query;
    const { sessionId } = req.params;
    // BUG #122: capture the requesting user so AI generation uses the
    // organization's configured provider/keys and honours subscription AI-model
    // access. Without these, generateWithAI fell back to the default/env provider
    // and regeneration produced no fresh content when the org relied on its own config.
    const userId = req.user!.id;
    const { regenerateQuestions = true, regenerateCoachingTips = true } = req.body;
    console.log('[InterviewMediaPrep] Generate request received:', { companyId, sessionId, regenerateQuestions, regenerateCoachingTips });

    const { InterviewMediaPrep } = getModels();

    // Use findOneAndUpdate to avoid version conflicts
    const doc = await InterviewMediaPrep.findOne({ companyId: companyId as string });

    if (!doc) {
      console.log('[InterviewMediaPrep] Document not found for companyId:', companyId);
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    const sessionIndex = doc.sessions.findIndex((s: any) => s.id === sessionId);

    if (sessionIndex === -1) {
      console.log('[InterviewMediaPrep] Session not found:', sessionId);
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    const session = doc.sessions[sessionIndex];
    console.log('[InterviewMediaPrep] Found session:', session.name, 'Type:', session.type);

    // Update status to generating using findOneAndUpdate to avoid version conflicts
    doc.sessions[sessionIndex].status = 'generating';
    await InterviewMediaPrep.updateOne(
      { companyId: companyId as string, 'sessions.id': sessionId },
      { $set: { 'sessions.$.status': 'generating' } }
    );

    try {
      // Build AI context from linked data
      console.log('[InterviewMediaPrep] Building harmony context...');
      console.log('[InterviewMediaPrep] Data sources:', session.dataSources);
      let harmonyContext;
      try {
        harmonyContext = await buildHarmonyContext(companyId as string, session.dataSources);
      } catch (ctxError: any) {
        console.error('[InterviewMediaPrep] Harmony context build failed:', ctxError);
        // Continue with empty context
        harmonyContext = { companyName: '' };
      }
      const harmonyBlock = buildHarmonyTextContextBlock(harmonyContext);
      console.log('[InterviewMediaPrep] Harmony context built successfully, length:', harmonyBlock.length);

      // Get prep type specific context
      const prepTypeContext = getPrepTypeContext(session.type);

      // Build speaker context
      const speakerContext = buildSpeakerContext(session);

      // Generate questions based on preparation type
      let generatedQuestions: any[] = [];
      let generatedCoachingTips: any[] = [];
      let aiModel = 'claude-3-5-sonnet';
      let aiProvider = 'claude';
      let tokensUsed = 0;

      if (regenerateQuestions) {
        console.log('[InterviewMediaPrep] Generating questions...');
        console.log('[InterviewMediaPrep] Question count:', session.questionCount, '| Language:', session.language);
        const questionsPrompt = buildQuestionsPrompt(session, prepTypeContext, speakerContext, harmonyBlock);
        console.log('[InterviewMediaPrep] Questions prompt length:', questionsPrompt.length);
        const languageInstruction = buildLanguageInstruction(session.language);

        try {
          const questionsResult = await generateWithAI(
            questionsPrompt,
            `You are an expert media trainer and interview coach. Generate comprehensive interview preparation content.${languageInstruction}`,
            16000,
            0.7,
            'json',
            undefined,
            undefined,
            userId,
            companyId as string
          );

          console.log('[InterviewMediaPrep] Questions result:', questionsResult ? 'received' : 'null');
          console.log('[InterviewMediaPrep] AI Provider:', questionsResult?.provider, '| Model:', questionsResult?.model);

          if (questionsResult?.content) {
            generatedQuestions = parseQuestionsFromAI(questionsResult.content, session.questionCount, session.type);
            console.log('[InterviewMediaPrep] Parsed questions:', generatedQuestions.length);
            aiModel = questionsResult.model || 'claude-3-5-sonnet';
            aiProvider = questionsResult.provider || 'claude';
            tokensUsed = questionsResult.tokenUsage?.totalTokens || 0;
          } else {
            console.log('[InterviewMediaPrep] No questions content received');
            throw new Error('AI returned empty content for questions');
          }
        } catch (genError: any) {
          console.error('[InterviewMediaPrep] Question generation failed:', genError.message);
          console.error('[InterviewMediaPrep] Stack:', genError.stack);
          throw new Error(`Failed to generate questions: ${genError.message}`);
        }
      } else {
        generatedQuestions = session.questions;
      }

      if (regenerateCoachingTips) {
        console.log('[InterviewMediaPrep] Generating coaching tips...');
        const coachingPrompt = buildCoachingTipsPrompt(session, prepTypeContext, speakerContext, harmonyBlock);
        console.log('[InterviewMediaPrep] Coaching prompt length:', coachingPrompt.length);
        const languageInstruction = buildLanguageInstruction(session.language);

        try {
          const coachingResult = await generateWithAI(
            coachingPrompt,
            `You are an expert media trainer and interview coach. Generate comprehensive coaching tips.${languageInstruction}`,
            8000,
            0.7,
            'json',
            undefined,
            undefined,
            userId,
            companyId as string
          );

          console.log('[InterviewMediaPrep] Coaching tips result:', coachingResult ? 'received' : 'null');
          console.log('[InterviewMediaPrep] AI Provider:', coachingResult?.provider, '| Model:', coachingResult?.model);

          if (coachingResult?.content) {
            generatedCoachingTips = parseCoachingTipsFromAI(coachingResult.content, session.type);
            console.log('[InterviewMediaPrep] Parsed coaching tips:', generatedCoachingTips.length);
          } else {
            console.log('[InterviewMediaPrep] No coaching tips content received');
            throw new Error('AI returned empty content for coaching tips');
          }
        } catch (coachError: any) {
          console.error('[InterviewMediaPrep] Coaching tips generation failed:', coachError.message);
          // Don't fail the whole request if coaching tips fail - just log the error
          console.warn('[InterviewMediaPrep] Continuing without coaching tips');
          generatedCoachingTips = [];
        }
      } else {
        generatedCoachingTips = session.coachingTips;
      }

      // Update session using findOneAndUpdate to avoid version conflicts
      const updateResult = await InterviewMediaPrep.findOneAndUpdate(
        { companyId: companyId as string, 'sessions.id': sessionId },
        {
          $set: {
            'sessions.$.questions': generatedQuestions,
            'sessions.$.coachingTips': generatedCoachingTips,
            'sessions.$.status': 'completed',
            'sessions.$.aiGenerated': true,
            'sessions.$.aiModel': aiModel,
            'sessions.$.aiProvider': aiProvider,
            'sessions.$.aiTokensUsed': tokensUsed,
            'sessions.$.aiGeneratedAt': new Date().toISOString(),
            'sessions.$.updatedAt': new Date().toISOString()
          }
        },
        { new: true }
      );

      if (!updateResult) {
        console.error('[InterviewMediaPrep] Failed to update session');
        res.status(500).json({ error: 'Failed to update session' });
        return;
      }

      const updatedSession = updateResult.sessions.find((s: any) => s.id === sessionId);
      console.log('[InterviewMediaPrep] Session saved successfully');

      res.json({
        success: true,
        session: updatedSession,
        tokensUsed: tokensUsed
      });
    } catch (aiError: any) {
      console.error('[InterviewMediaPrep] AI generation error:', aiError);
      // Revert status on AI error
      await InterviewMediaPrep.updateOne(
        { companyId: companyId as string, 'sessions.id': sessionId },
        { $set: { 'sessions.$.status': 'draft' } }
      );
      throw aiError;
    }
  } catch (error: any) {
    console.error('[InterviewMediaPrep] Generate endpoint error:', error);
    console.error('[InterviewMediaPrep] Error message:', error?.message);
    console.error('[InterviewMediaPrep] Error stack:', error?.stack);
    console.error('[InterviewMediaPrep] Error name:', error?.name);

    // Determine appropriate status code
    let statusCode = 500;
    let errorMessage = error?.message || 'Internal server error';

    if (error?.name === 'AbortError' || error?.message?.includes('timeout')) {
      statusCode = 408;
      errorMessage = 'Request timeout - AI generation took too long';
    } else if (error?.message?.includes('not configured')) {
      statusCode = 503;
      errorMessage = 'AI service not configured properly';
    } else if (error?.message?.includes('authentication') || error?.message?.includes('unauthorized')) {
      statusCode = 503;
      errorMessage = 'AI service authentication failed';
    }

    res.status(statusCode).json({
      success: false,
      error: errorMessage,
      details: process.env.NODE_ENV === 'development' ? error?.stack : undefined
    });
  }
});

// ============================================
// REGENERATE SINGLE QUESTION
// ============================================

router.post('/sessions/:sessionId/questions/:questionId/regenerate', [
  query('companyId').notEmpty().withMessage('Company ID is required'),
  param('sessionId').notEmpty().withMessage('Session ID is required'),
  param('questionId').notEmpty().withMessage('Question ID is required'),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId } = req.query;
    const { sessionId, questionId } = req.params;
    // BUG #122: use the organization's AI configuration for single-question regen too.
    const userId = req.user!.id;
    const { InterviewMediaPrep } = getModels();

    const doc = await InterviewMediaPrep.findOne({ companyId: companyId as string });

    if (!doc) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    const session = doc.sessions.find((s: any) => s.id === sessionId);

    if (!session) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    const questionIndex = session.questions.findIndex((q: any) => q.id === questionId);

    if (questionIndex === -1) {
      res.status(404).json({ error: 'Question not found' });
      return;
    }

    const question = session.questions[questionIndex];

    // Build context and regenerate
    const harmonyContext = await buildHarmonyContext(companyId as string);
    const harmonyBlock = buildHarmonyTextContextBlock(harmonyContext);
    const prepTypeContext = getPrepTypeContext(session.type);
    const speakerContext = buildSpeakerContext(session);
    const languageInstruction = buildLanguageInstruction(session.language);

    const prompt = `Generate a new ${question.category} question for ${session.type} preparation.

Speaker: ${session.speakerName}${session.speakerPosition ? `, ${session.speakerPosition}` : ''}
Company: ${session.speakerCompany || 'N/A'}
Difficulty: ${session.difficulty}
${languageInstruction}

${prepTypeContext}

${speakerContext}

${harmonyBlock}

Original question category: ${question.category}
Generate a DIFFERENT question in the same category with:
1. The question
2. A suggested answer
3. An expert answer (more detailed)
4. A short version (key points)
5. A long version (comprehensive)
6. A high confidence version (assertive)
7. A media-friendly version (soundbite ready)
8. 2-3 follow-up questions
9. Coaching tips
10. Risk level (low/medium/high)
11. Response strategy

Format as JSON.`;

    const result = await generateWithAI(
      prompt,
      `You are an expert media trainer. Generate interview content.${languageInstruction}`,
      4000,
      0.8,
      'json',
      undefined,
      undefined,
      userId,
      companyId as string
    );

    if (result?.content) {
      const newQuestion = parseSingleQuestionFromAI(result.content, question.category, question.order);
      session.questions[questionIndex] = newQuestion;
      session.updatedAt = new Date().toISOString();
      await doc.save();
    }

    res.json({ question: session.questions[questionIndex] });
  } catch (error: any) {
    handleError(res, error);
  }
});

// ============================================
// EXPORT SESSION
// ============================================

router.post('/sessions/:sessionId/export', [
  query('companyId').notEmpty().withMessage('Company ID is required'),
  param('sessionId').notEmpty().withMessage('Session ID is required'),
  body('format').optional().isIn(['json', 'pdf', 'docx', 'txt']),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId } = req.query;
    const { sessionId } = req.params;
    const { format = 'json' } = req.body;
    const { InterviewMediaPrep } = getModels();

    const doc = await InterviewMediaPrep.findOne({ companyId: companyId as string });

    if (!doc) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    const session = doc.sessions.find((s: any) => s.id === sessionId);

    if (!session) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }

    if (format === 'json') {
      res.json({ session, exportedAt: new Date().toISOString() });
      return;
    }

    // For other formats, return structured data for frontend processing
    res.json({
      session,
      format,
      exportedAt: new Date().toISOString(),
      downloadUrl: `/api/interview-media-prep/sessions/${sessionId}/download/${format}`
    });
  } catch (error: any) {
    handleError(res, error);
  }
});

// ============================================
// GENERATE DESCRIPTION
// ============================================

router.post('/generate-description', [
  body('companyId').notEmpty().withMessage('Company ID is required'),
  body('prepType').isIn([
    'podcast', 'rapid-fire', 'interview', 'panel-discussion',
    'founder-interview', 'employee-interview', 'media-interview',
    'tv-interview', 'press-conference', 'journalist', 'investor-interview',
    'startup-interview', 'crisis-management', 'product-launch', 'custom'
  ]).withMessage('Valid preparation type is required'),
  body('speakerName').notEmpty().withMessage('Speaker name is required'),
], async (req: Request, res: Response) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      res.status(400).json({ errors: errors.array() });
      return;
    }

    const { companyId, prepType, speakerName, speakerPosition, speakerCompany, speakerBio, difficulty, questionCount, dataSources } = req.body;
    console.log('[InterviewMediaPrep] Generate description request:', { companyId, prepType, speakerName });

    // Build harmony context with data sources filter (with error handling)
    let harmonyBlock = '';
    try {
      const harmonyContext = await buildHarmonyContext(companyId, dataSources);
      harmonyBlock = buildHarmonyTextContextBlock(harmonyContext);
    } catch (harmonyError: any) {
      console.warn('[InterviewMediaPrep] Failed to build harmony context, continuing without:', harmonyError.message);
      // Continue without harmony context
    }

    // Get prep type context
    const prepTypeContext = getPrepTypeContext(prepType);

    // Build the prompt for generating description
    const prompt = `Generate a compelling description for a ${prepTypeContext}

SPEAKER CONTEXT:
- Name: ${speakerName}
${speakerPosition ? `- Position: ${speakerPosition}` : ''}
${speakerCompany ? `- Company: ${speakerCompany}` : ''}
${speakerBio ? `- Bio: ${speakerBio}` : ''}
- Difficulty: ${difficulty || 'intermediate'}
- Number of Questions: ${questionCount || 10}

BRAND & BUSINESS CONTEXT:
${harmonyBlock || 'No brand context available'}

REQUIREMENTS:
1. Write a 2-3 paragraph description of what this interview/podcast session will cover
2. Include the main topics and themes that will be discussed
3. Mention the target audience and objectives
4. Make it engaging and professional
5. Use the brand voice and tone if available from context

Generate only the description text, no additional formatting or labels.`;

    console.log('[InterviewMediaPrep] Calling AI for description generation...');

    let description = '';

    try {
      const result = await generateWithAI(
        prompt,
        'You are an expert content writer specializing in interview and media preparation descriptions.',
        1000,
        0.7,
        'text' // Use text format instead of JSON
      );

      console.log('[InterviewMediaPrep] AI result:', result ? 'received' : 'null');
      description = result?.content?.trim() || '';
    } catch (aiError: any) {
      console.warn('[InterviewMediaPrep] AI generation failed, using fallback:', aiError.message);
      // Continue with fallback description
    }

    if (!description) {
      console.log('[InterviewMediaPrep] Using fallback description');
      // Return a fallback description based on the context
      const speakerInfo = [speakerName, speakerPosition, speakerCompany].filter(Boolean).join(' - ');
      description = `${prepTypeContext}

Speaker: ${speakerInfo || 'Guest Speaker'}
${speakerBio ? `\nAbout the Speaker: ${speakerBio}` : ''}
${difficulty ? `\nDifficulty Level: ${difficulty}` : ''}

This session will include ${questionCount || 10} carefully crafted questions designed to help the speaker prepare for ${prepType === 'podcast' ? 'podcast interviews' : prepType === 'media-interview' ? 'media appearances' : 'professional interviews'}. The questions will cover key topics relevant to the speaker's expertise and background.`;
    }

    // Strip any JSON formatting if the AI returned JSON instead of plain text
    if (description.startsWith('{') && description.includes('"description"')) {
      try {
        const parsed = JSON.parse(description);
        if (parsed.description && typeof parsed.description === 'string') {
          description = parsed.description;
        }
      } catch {
        // If parsing fails, use the original content
      }
    }

    // Clean AI internal drafting markers (*Drafting P1:*, *Thinking:*, etc.)
    description = cleanAiMarkers(description);

    res.json({ description });
  } catch (error: any) {
    console.error('[InterviewMediaPrep] Generate description error:', error);
    console.error('[InterviewMediaPrep] Error stack:', error.stack);

    // Return a more specific error message
    const errorMessage = error.message || 'Internal server error';
    const isAIError = errorMessage.includes('AI') || errorMessage.includes('provider') || errorMessage.includes('key');

    res.status(500).json({
      error: isAIError
        ? 'AI generation failed. Please check AI provider configuration.'
        : errorMessage,
      details: process.env.NODE_ENV === 'development' ? error.stack : undefined
    });
  }
});

// ============================================
// HELPER FUNCTIONS
// ============================================

function getPrepTypeContext(type: string): string {
  const contexts: Record<string, string> = {
    'podcast': 'Podcast interview preparation focusing on storytelling, personal journey, business insights, and engaging long-form conversation.',
    'rapid-fire': 'Quick-fire questions preparation for fun, personality-revealing segments with short punchy answers.',
    'interview': 'General interview preparation covering professional topics, behavioral questions, and situational responses.',
    'panel-discussion': 'Panel discussion preparation with moderator questions, counter-arguments, and expert commentary.',
    'founder-interview': 'Founder-focused interview covering startup journey, vision, challenges, funding, and leadership.',
    'employee-interview': 'Employee interview preparation for HR questions, technical assessments, and behavioral interviews.',
    'media-interview': 'Media interview preparation for press, radio, and online media with PR-friendly messaging.',
    'tv-interview': 'TV interview preparation focusing on on-camera presence, concise soundbites, and visual communication.',
    'press-conference': 'Press conference preparation for group media interactions with challenging journalist questions.',
    'journalist': 'Journalist Q&A preparation for handling tough questions, controversial topics, and maintaining message control.',
    'investor-interview': 'Investor interview preparation covering financials, growth metrics, market opportunity, and funding.',
    'startup-interview': 'Startup interview preparation for accelerator applications, pitch competitions, and demo days.',
    'crisis-management': 'Crisis management preparation for handling negative press, product failures, and reputation protection.',
    'product-launch': 'Product launch interview preparation for announcements, demos, and media tours.',
    'custom': 'Custom interview preparation tailored to specific requirements.'
  };
  return contexts[type] || contexts['interview'];
}

function buildSpeakerContext(session: any): string {
  let context = `Speaker: ${session.speakerName}\n`;

  if (session.speakerPosition) context += `Position: ${session.speakerPosition}\n`;
  if (session.speakerCompany) context += `Company: ${session.speakerCompany}\n`;
  if (session.speakerIndustry) context += `Industry: ${session.speakerIndustry}\n`;
  if (session.speakerDepartment) context += `Department: ${session.speakerDepartment}\n`;
  if (session.speakerBio) context += `Bio: ${session.speakerBio}\n`;
  if (session.contextTopic) context += `Topic: ${session.contextTopic}\n`;
  if (session.contextAudience) context += `Audience: ${session.contextAudience}\n`;

  context += `Difficulty Level: ${session.difficulty}\n`;
  context += `Number of Questions: ${session.questionCount}\n`;

  return context;
}

// ============================================
// LANGUAGE INSTRUCTION BUILDER
// Follows the same pattern as Case Studies, FAQ Bank, etc.
// ============================================

function buildLanguageInstruction(language?: string): string {
  if (!language || language.toLowerCase() === 'english') {
    return '';
  }
  const langLower = language.toLowerCase();
  if (langLower === 'hindi') {
    return '\n\nIMPORTANT LANGUAGE REQUIREMENT: Generate ALL content (questions, answers, expert answers, follow-up questions, coaching tips, suggested answers, short answers, long answers, high-confidence answers, media-friendly answers, response strategies, and any other text) entirely in Hindi using Devanagari script (हिंदी देवनागरी लिपि). Do NOT use English anywhere except for JSON field names. All text values must be natural, fluent Hindi appropriate for interview preparation contexts in India.';
  }
  if (langLower === 'marathi') {
    return '\n\nIMPORTANT LANGUAGE REQUIREMENT: Generate ALL content (questions, answers, expert answers, follow-up questions, coaching tips, suggested answers, short answers, long answers, high-confidence answers, media-friendly answers, response strategies, and any other text) entirely in Marathi using Devanagari script (मराठी देवनागरी लिपि). Do NOT use English anywhere except for JSON field names. All text values must be natural, fluent Marathi appropriate for interview preparation contexts in Maharashtra, India.';
  }
  return `\n\nIMPORTANT LANGUAGE REQUIREMENT: Generate ALL content in ${language}. All text values (questions, answers, tips, strategies, etc.) must be in the specified language. Only JSON field names should remain in English.`;
}

function buildQuestionsPrompt(session: any, prepTypeContext: string, speakerContext: string, harmonyBlock: string): string {
  const languageInstruction = buildLanguageInstruction(session.language);

  return `Generate ${session.questionCount} interview questions for ${session.type} preparation.

${prepTypeContext}

${speakerContext}

COMPANY CONTEXT:
${harmonyBlock}

REQUIREMENTS:
1. Generate questions appropriate for ${session.difficulty} difficulty level
${session.audienceType ? `2. Target audience: ${session.audienceType}` : ''}${languageInstruction}

For EACH question, provide:
{
  "id": "unique_id",
  "question": "The interview question",
  "category": "Category (e.g., 'introductory', 'business', 'personal', 'technical', 'behavioral')",
  "difficulty": "${session.difficulty}",
  "suggestedAnswer": "A well-structured suggested answer",
  "expertAnswer": "A more comprehensive expert-level answer",
  "shortAnswer": "Concise key points version",
  "longAnswer": "Comprehensive detailed version",
  "highConfidenceAnswer": "Assertive, confident version",
  "mediaFriendlyAnswer": "Soundbite-ready version for media",
  "followUpQuestions": ["Follow-up question 1", "Follow-up question 2"],
  "coachingTips": ["Tip 1", "Tip 2"],
  "riskLevel": "low/medium/high",
  "responseStrategy": "Brief strategy for handling this question",
  "confidenceScore": 85
}

Return as a JSON array of ${session.questionCount} questions.`;
}

function buildCoachingTipsPrompt(session: any, prepTypeContext: string, speakerContext: string, harmonyBlock: string): string {
  const languageInstruction = buildLanguageInstruction(session.language);

  return `Generate comprehensive coaching tips for ${session.type} preparation.

${prepTypeContext}

${speakerContext}

COMPANY CONTEXT:
${harmonyBlock}

Generate coaching tips covering:
1. Speaking tips (vocal variety, pace, clarity)
2. Confidence tips (body language, mindset)
3. Body language tips (posture, gestures, eye contact)
4. Voice modulation tips (tone, emphasis, pauses)
5. Camera presence tips (for TV/video interviews)
6. Common mistakes to avoid
${languageInstruction}

For EACH coaching category, provide:
{
  "id": "unique_id",
  "category": "Category name",
  "title": "Coaching area title",
  "description": "Brief description",
  "tips": ["Actionable tip 1", "Actionable tip 2"],
  "commonMistakes": ["Mistake 1", "Mistake 2"],
  "confidenceTips": ["Confidence-building tip 1"],
  "bodyLanguageTips": ["Body language tip 1"],
  "voiceModulationTips": ["Voice tip 1"],
  "cameraPresenceTips": ["Camera presence tip 1"]
}

Return as a JSON array.`;
}

function parseQuestionsFromAI(content: string, count: number, type: string): any[] {
  console.log('[InterviewMediaPrep] Parsing questions from AI content, length:', content?.length);
  try {
    // Try to extract JSON from the content
    const jsonMatch = content.match(/\[[\s\S]*\]/);
    if (jsonMatch) {
      const parsed = JSON.parse(jsonMatch[0]);
      console.log('[InterviewMediaPrep] Parsed JSON array with', parsed.length, 'items');
      const questions = parsed.slice(0, count).map((q: any, index: number) => ({
        id: q.id || `q_${Date.now()}_${index}`,
        question: q.question || '',
        category: q.category || 'general',
        difficulty: q.difficulty || 'intermediate',
        suggestedAnswer: q.suggestedAnswer || '',
        expertAnswer: q.expertAnswer || '',
        shortAnswer: q.shortAnswer || '',
        longAnswer: q.longAnswer || '',
        highConfidenceAnswer: q.highConfidenceAnswer || '',
        mediaFriendlyAnswer: q.mediaFriendlyAnswer || '',
        followUpQuestions: q.followUpQuestions || [],
        coachingTips: q.coachingTips || [],
        riskLevel: q.riskLevel || 'low',
        responseStrategy: q.responseStrategy || '',
        confidenceScore: q.confidenceScore || 80,
        order: index + 1
      }));
      console.log('[InterviewMediaPrep] Returning', questions.length, 'parsed questions');
      return questions;
    } else {
      console.log('[InterviewMediaPrep] No JSON array found in content');
    }
  } catch (e) {
    console.error('[InterviewMediaPrep] Error parsing questions:', e);
    console.error('[InterviewMediaPrep] Content preview:', content?.substring(0, 500));
  }

  // Return default questions if parsing fails
  console.log('[InterviewMediaPrep] Returning default questions');
  return Array.from({ length: Math.min(count, 5) }, (_, i) => ({
    id: `q_${Date.now()}_${i}`,
    question: `Sample interview question ${i + 1} for ${type} preparation`,
    category: 'general',
    difficulty: 'intermediate',
    suggestedAnswer: 'Please try regenerating for AI-powered answers.',
    expertAnswer: 'Please try regenerating for expert-level answers.',
    shortAnswer: 'Sample short answer.',
    longAnswer: 'Sample comprehensive answer.',
    highConfidenceAnswer: 'Sample confident answer.',
    mediaFriendlyAnswer: 'Sample media-friendly soundbite.',
    followUpQuestions: ['What else would you like to know?'],
    coachingTips: ['Practice this question multiple times'],
    riskLevel: 'low',
    responseStrategy: 'Be authentic and confident',
    confidenceScore: 70,
    order: i + 1
  }));
}

function parseCoachingTipsFromAI(content: string, type: string): any[] {
  console.log('[InterviewMediaPrep] Parsing coaching tips from AI content, length:', content?.length);
  try {
    const jsonMatch = content.match(/\[[\s\S]*\]/);
    if (jsonMatch) {
      const parsed = JSON.parse(jsonMatch[0]);
      console.log('[InterviewMediaPrep] Parsed', parsed.length, 'coaching tips');
      return parsed.map((tip: any) => ({
        id: tip.id || `tip_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
        category: tip.category || 'general',
        title: tip.title || 'Interview Coaching Tip',
        description: tip.description || '',
        tips: tip.tips || [],
        commonMistakes: tip.commonMistakes || [],
        confidenceTips: tip.confidenceTips || [],
        bodyLanguageTips: tip.bodyLanguageTips || [],
        voiceModulationTips: tip.voiceModulationTips || [],
        cameraPresenceTips: tip.cameraPresenceTips || []
      }));
    } else {
      console.log('[InterviewMediaPrep] No JSON array found in coaching tips content');
    }
  } catch (e) {
    console.error('[InterviewMediaPrep] Error parsing coaching tips:', e);
    console.error('[InterviewMediaPrep] Content preview:', content?.substring(0, 500));
  }

  // Return default coaching tips if parsing fails
  console.log('[InterviewMediaPrep] Returning default coaching tips');
  return [
    {
      id: `tip_${Date.now()}_1`,
      category: 'speaking',
      title: 'Speaking Tips',
      description: 'Improve your verbal communication for interviews',
      tips: ['Speak clearly and at a moderate pace', 'Use pauses effectively for emphasis', 'Avoid filler words']
    },
    {
      id: `tip_${Date.now()}_2`,
      category: 'confidence',
      title: 'Confidence Building',
      description: 'Build your confidence before the interview',
      tips: ['Practice your answers multiple times', 'Focus on your strengths', 'Take deep breaths to stay calm']
    },
    {
      id: `tip_${Date.now()}_3`,
      category: 'body-language',
      title: 'Body Language',
      description: 'Non-verbal communication tips',
      tips: ['Maintain good posture', 'Make appropriate eye contact', 'Use hand gestures naturally']
    }
  ];
}

function parseSingleQuestionFromAI(content: string, category: string, order: number): any {
  try {
    const jsonMatch = content.match(/\{[\s\S]*\}/);
    if (jsonMatch) {
      const parsed = JSON.parse(jsonMatch[0]);
      return {
        id: `q_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
        question: parsed.question || '',
        category: parsed.category || category,
        difficulty: parsed.difficulty || 'intermediate',
        suggestedAnswer: parsed.suggestedAnswer || '',
        expertAnswer: parsed.expertAnswer || '',
        shortAnswer: parsed.shortAnswer || '',
        longAnswer: parsed.longAnswer || '',
        highConfidenceAnswer: parsed.highConfidenceAnswer || '',
        mediaFriendlyAnswer: parsed.mediaFriendlyAnswer || '',
        followUpQuestions: parsed.followUpQuestions || [],
        coachingTips: parsed.coachingTips || [],
        riskLevel: parsed.riskLevel || 'low',
        responseStrategy: parsed.responseStrategy || '',
        confidenceScore: parsed.confidenceScore || 80,
        order
      };
    }
  } catch (e) {
    console.error('[InterviewMediaPrep] Error parsing single question:', e);
  }

  // Return a basic question object if parsing fails
  return {
    id: `q_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
    question: '',
    category,
    difficulty: 'intermediate',
    order
  };
}

/**
 * Clean AI internal drafting markers from generated content
 * Removes labels like *Drafting P1:*, *Thinking:*, *Reasoning:*, etc.
 */
function cleanAiMarkers(content: string): string {
  if (!content) return content;

  let cleaned = content;

  // Remove AI drafting markers in various formats
  // Patterns: *Drafting P1:*, *Drafting P2:*, *Drafting P3:*, *Thinking:*, *Reasoning:*, *Planning:*, etc.
  const markerPatterns = [
    // *Drafting P1:*, *Drafting P2:*, *Drafting P3:* (with or without space after colon)
    /\*Drafting\s*(?:P[1-9]|P\d+|Paragraph\s*\d+):?\s*/gi,
    // *Thinking:*, *Reasoning:*, *Planning:*, *Note:*, *Analysis:*
    /\*(?:Thinking|Reasoning|Planning|Note|Analysis|Draft|Thought|Process|Step|Context|Explanation):?\s*/gi,
    // <thinking>, <drafting>, etc. (XML-style tags)
    /<(?:thinking|reasoning|planning|draft|note|analysis|thought|process|step|context|explanation)[^>]*>[\s\S]*?<\/(?:thinking|reasoning|planning|draft|note|analysis|thought|process|step|context|explanation)>/gi,
    // [Drafting], [Thinking], etc.
    /\[(?:Drafting|Thinking|Reasoning|Planning|Note|Analysis|Draft|Thought|Process|Step|Context|Explanation):?\s*\]/gi,
    // **Drafting**, **Thinking**, etc. followed by content
    /\*\*(?:Drafting|Thinking|Reasoning|Planning|Note|Analysis|Draft|Thought|Process|Step|Context|Explanation):?\*\*[\s]*/gi,
  ];

  for (const pattern of markerPatterns) {
    cleaned = cleaned.replace(pattern, '');
  }

  // Clean up multiple consecutive line breaks (more than 2)
  cleaned = cleaned.replace(/\n{3,}/g, '\n\n');

  // Clean up leading/trailing whitespace
  cleaned = cleaned.trim();

  return cleaned;
}

export default router;