/**
 * WhatsApp Conversation Controller
 * API endpoints for conversation management
 *
 * @module WhatsApp
 * @prefix /api/v1/whatsapp/conversations
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  WhatsAppConversationService,
  CreateConversationDto,
  UpdateConversationDto,
  ServiceContext,
} from '../services';

const router = Router();
const conversationService = new WhatsAppConversationService();

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/conversations
 * List conversations
 */
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, status, priority, assignedTo, teamId, category, unassigned, page, limit } = req.query;

    const result = await conversationService.findAll(
      ctx,
      {
        accountId: accountId as string,
        contactId: contactId as string,
        status: status as any,
        priority: priority as any,
        assignedTo: assignedTo as string,
        teamId: teamId as string,
        category: category as string,
        unassigned: unassigned === 'true',
      },
      {
        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/conversations/open
 * Get open conversations
 */
router.get('/open', 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, assignedTo, teamId } = req.query;

    const conversations = await conversationService.findOpen(ctx, {
      accountId: accountId as string,
      assignedTo: assignedTo as string,
      teamId: teamId as string,
    });

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

/**
 * GET /api/v1/whatsapp/conversations/unassigned
 * Get unassigned conversations
 */
router.get('/unassigned', 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 } = req.query;
    const conversations = await conversationService.findUnassigned(ctx, accountId as string);
    return res.json({ success: true, data: conversations, count: conversations.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/conversations/my
 * Get conversations assigned to current user
 */
router.get('/my', 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' });
    }

    if (!ctx.userId) {
      return res.status(401).json({ error: 'User authentication required' });
    }

    const conversations = await conversationService.findByAgent(ctx, ctx.userId);
    return res.json({ success: true, data: conversations, count: conversations.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/conversations/statistics
 * Get conversation 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 } = req.query;
    const stats = await conversationService.getStatistics(ctx, accountId as string);
    return res.json({ success: true, data: stats });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/conversations/:id
 * Get conversation 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 conversation = await conversationService.findById(ctx, req.params.id);
    if (!conversation) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

/**
 * POST /api/v1/whatsapp/conversations
 * Create or get conversation
 */
router.post('/', 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: CreateConversationDto = req.body;

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

    const conversation = await conversationService.getOrCreate(ctx, data);
    return res.status(201).json({ success: true, data: conversation });
  } catch (error) {
    return next(error);
  }
});

/**
 * PATCH /api/v1/whatsapp/conversations/:id
 * Update conversation
 */
router.patch('/: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 data: UpdateConversationDto = req.body;
    const conversation = await conversationService.update(ctx, req.params.id, data);

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

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

/**
 * POST /api/v1/whatsapp/conversations/:id/assign
 * Assign conversation to agent
 */
router.post('/:id/assign', 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 { agentId, teamId } = req.body;

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

    const conversation = await conversationService.assign(ctx, req.params.id, agentId, teamId);
    if (!conversation) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

/**
 * POST /api/v1/whatsapp/conversations/:id/unassign
 * Unassign conversation
 */
router.post('/:id/unassign', 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 conversation = await conversationService.unassign(ctx, req.params.id);
    if (!conversation) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

/**
 * POST /api/v1/whatsapp/conversations/:id/resolve
 * Resolve conversation
 */
router.post('/:id/resolve', 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 conversation = await conversationService.resolve(ctx, req.params.id);
    if (!conversation) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

/**
 * POST /api/v1/whatsapp/conversations/:id/reopen
 * Reopen resolved conversation
 */
router.post('/:id/reopen', 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 conversation = await conversationService.reopen(ctx, req.params.id);
    if (!conversation) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

/**
 * POST /api/v1/whatsapp/conversations/:id/close
 * Close conversation
 */
router.post('/:id/close', 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 conversation = await conversationService.close(ctx, req.params.id);
    if (!conversation) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

/**
 * PATCH /api/v1/whatsapp/conversations/:id/priority
 * Update conversation priority
 */
router.patch('/:id/priority', 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 { priority } = req.body;

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

    const conversation = await conversationService.setPriority(ctx, req.params.id, priority);
    if (!conversation) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

/**
 * POST /api/v1/whatsapp/conversations/:id/tags
 * Add tag to conversation
 */
router.post('/:id/tags', 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 { tag } = req.body;

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

    const conversation = await conversationService.addTag(ctx, req.params.id, tag);
    if (!conversation) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

/**
 * DELETE /api/v1/whatsapp/conversations/:id/tags/:tag
 * Remove tag from conversation
 */
router.delete('/:id/tags/:tag', 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 conversation = await conversationService.removeTag(ctx, req.params.id, req.params.tag);
    if (!conversation) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

/**
 * POST /api/v1/whatsapp/conversations/:id/read
 * Mark conversation as read
 */
router.post('/:id/read', 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' });
    }

    await conversationService.markAsRead(ctx, req.params.id);
    return res.json({ success: true, message: 'Conversation marked as read' });
  } catch (error) {
    return next(error);
  }
});

/**
 * DELETE /api/v1/whatsapp/conversations/:id
 * Delete conversation
 */
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 conversationService.delete(ctx, req.params.id);
    if (!deleted) {
      return res.status(404).json({ error: 'Conversation not found' });
    }

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

export default router;
