/**
 * WhatsApp Message Controller
 * API endpoints for WhatsApp message management
 *
 * @module WhatsApp
 * @prefix /api/v1/whatsapp/messages
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  WhatsAppMessageService,
  SendTextMessageDto,
  SendTemplateMessageDto,
  SendMediaMessageDto,
  SendInteractiveMessageDto,
  ServiceContext,
} from '../services';

const router = Router();
const messageService = new WhatsAppMessageService();

function getServiceContext(req: Request): ServiceContext {
  const tenantId = req.headers['x-tenant-id'] as string;
  const userId = (req as any).user?.id;
  return { tenantId, userId };
}

/**
 * GET /api/v1/whatsapp/messages
 * List messages with filters
 */
router.get('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { accountId, contactId, conversationId, direction, messageType, status, page, limit } = req.query;

    const result = await messageService.findAll(
      ctx,
      {
        accountId: accountId as string,
        contactId: contactId as string,
        conversationId: conversationId as string,
        direction: direction as any,
        messageType: messageType as any,
        status: status as any,
      },
      {
        page: page ? parseInt(page as string) : undefined,
        limit: limit ? parseInt(limit as string) : undefined,
      }
    );

    return res.json({
      success: true,
      data: result.data,
      total: result.total,
      page: page ? parseInt(page as string) : 1,
      limit: limit ? parseInt(limit as string) : 50,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/messages/conversation/:conversationId
 * Get messages by conversation
 */
router.get('/conversation/:conversationId', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { page, limit } = req.query;
    const result = await messageService.findByConversation(
      ctx,
      req.params.conversationId,
      {
        page: page ? parseInt(page as string) : undefined,
        limit: limit ? parseInt(limit as string) : undefined,
      }
    );

    return res.json({
      success: true,
      data: result.data,
      total: result.total,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/messages/contact/:contactId
 * Get messages by contact
 */
router.get('/contact/:contactId', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { page, limit } = req.query;
    const result = await messageService.findByContact(
      ctx,
      req.params.contactId,
      {
        page: page ? parseInt(page as string) : undefined,
        limit: limit ? parseInt(limit as string) : undefined,
      }
    );

    return res.json({
      success: true,
      data: result.data,
      total: result.total,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/messages/contact/:contactId/recent
 * Get recent messages for contact
 */
router.get('/contact/:contactId/recent', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { limit } = req.query;
    const messages = await messageService.getRecentMessages(
      ctx,
      req.params.contactId,
      limit ? parseInt(limit as string) : 20
    );

    return res.json({ success: true, data: messages });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/messages/statistics
 * Get message statistics
 */
router.get('/statistics', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { accountId, dateFrom, dateTo } = req.query;
    const stats = await messageService.getStatistics(
      ctx,
      accountId as string,
      dateFrom ? new Date(dateFrom as string) : undefined,
      dateTo ? new Date(dateTo as string) : undefined
    );

    return res.json({ success: true, data: stats });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/messages/:id
 * Get message by ID
 */
router.get('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const message = await messageService.findById(ctx, req.params.id);
    if (!message) {
      return res.status(404).json({ error: 'Message not found' });
    }

    return res.json({ success: true, data: message });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/whatsapp/messages/text
 * Send text message
 */
router.post('/text', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const data: SendTextMessageDto = req.body;

    if (!data.accountId || !data.contactId || !data.content) {
      return res.status(400).json({ error: 'accountId, contactId, and content are required' });
    }

    const message = await messageService.sendTextMessage(ctx, data);
    return res.status(201).json({ success: true, data: message });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/whatsapp/messages/template
 * Send template message
 */
router.post('/template', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const data: SendTemplateMessageDto = req.body;

    if (!data.accountId || !data.contactId || !data.templateId || !data.templateName) {
      return res.status(400).json({
        error: 'accountId, contactId, templateId, and templateName are required',
      });
    }

    const message = await messageService.sendTemplateMessage(ctx, data);
    return res.status(201).json({ success: true, data: message });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/whatsapp/messages/media
 * Send media message
 */
router.post('/media', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const data: SendMediaMessageDto = req.body;

    if (!data.accountId || !data.contactId || !data.messageType || !data.mediaUrl) {
      return res.status(400).json({
        error: 'accountId, contactId, messageType, and mediaUrl are required',
      });
    }

    const validTypes = ['image', 'video', 'audio', 'document'];
    if (!validTypes.includes(data.messageType)) {
      return res.status(400).json({
        error: `messageType must be one of: ${validTypes.join(', ')}`,
      });
    }

    const message = await messageService.sendMediaMessage(ctx, data);
    return res.status(201).json({ success: true, data: message });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/whatsapp/messages/interactive
 * Send interactive message
 */
router.post('/interactive', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const data: SendInteractiveMessageDto = req.body;

    if (!data.accountId || !data.contactId || !data.interactiveType || !data.interactiveData) {
      return res.status(400).json({
        error: 'accountId, contactId, interactiveType, and interactiveData are required',
      });
    }

    const message = await messageService.sendInteractiveMessage(ctx, data);
    return res.status(201).json({ success: true, data: message });
  } catch (error) {
    return next(error);
  }
});

/**
 * PATCH /api/v1/whatsapp/messages/:id/status
 * Update message status
 */
router.patch('/:id/status', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { status, errorCode, errorMessage } = req.body;

    if (!status) {
      return res.status(400).json({ error: 'status is required' });
    }

    const message = await messageService.updateStatus(ctx, req.params.id, {
      status,
      errorCode,
      errorMessage,
    });

    if (!message) {
      return res.status(404).json({ error: 'Message not found' });
    }

    return res.json({ success: true, data: message });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/whatsapp/messages/:id/mark-sent
 * Mark message as sent with WhatsApp message ID
 */
router.post('/:id/mark-sent', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { waMessageId } = req.body;

    if (!waMessageId) {
      return res.status(400).json({ error: 'waMessageId is required' });
    }

    const message = await messageService.markAsSent(ctx, req.params.id, waMessageId);
    if (!message) {
      return res.status(404).json({ error: 'Message not found' });
    }

    return res.json({ success: true, data: message });
  } catch (error) {
    return next(error);
  }
});

/**
 * DELETE /api/v1/whatsapp/messages/:id
 * Delete message
 */
router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const ctx = getServiceContext(req);
    if (!ctx.tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const deleted = await messageService.delete(ctx, req.params.id);
    if (!deleted) {
      return res.status(404).json({ error: 'Message not found' });
    }

    return res.json({ success: true, message: 'Message deleted' });
  } catch (error) {
    return next(error);
  }
});

export default router;
