/**
 * WhatsApp Contact Controller
 * API endpoints for WhatsApp contact management
 *
 * @module WhatsApp
 * @prefix /api/v1/whatsapp/contacts
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  WhatsAppContactService,
  CreateContactDto,
  UpdateContactDto,
  ServiceContext,
} from '../services';

const router = Router();
const contactService = new WhatsAppContactService();

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/contacts
 * List all contacts
 */
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, conversationStatus, optedIn, optedOut, tag, page, limit } = req.query;

    const result = await contactService.findAll(
      ctx,
      {
        accountId: accountId as string,
        conversationStatus: conversationStatus as any,
        optedIn: optedIn === 'true' ? true : optedIn === 'false' ? false : undefined,
        optedOut: optedOut === 'true' ? true : optedOut === 'false' ? false : undefined,
        tag: tag as string,
      },
      {
        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/contacts/opted-in
 * Get opted-in contacts
 */
router.get('/opted-in', 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 contacts = await contactService.findOptedIn(ctx, accountId as string);
    return res.json({ success: true, data: contacts, count: contacts.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/contacts/by-tag/:tag
 * Get contacts by tag
 */
router.get('/by-tag/: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 contacts = await contactService.findByTag(ctx, req.params.tag);
    return res.json({ success: true, data: contacts, count: contacts.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/whatsapp/contacts/statistics
 * Get contact 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 contactService.getStatistics(ctx, accountId as string);
    return res.json({ success: true, data: stats });
  } catch (error) {
    return next(error);
  }
});

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

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

/**
 * GET /api/v1/whatsapp/contacts/:id/conversation-window
 * Check conversation window status
 */
router.get('/:id/conversation-window', 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 isOpen = await contactService.checkConversationWindow(ctx, req.params.id);
    return res.json({ success: true, data: { conversationWindowOpen: isOpen } });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/whatsapp/contacts
 * Create a new contact
 */
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: CreateContactDto = req.body;

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

    const contact = await contactService.upsertByPhoneNumber(ctx, data);
    return res.status(201).json({ success: true, data: contact });
  } catch (error) {
    return next(error);
  }
});

/**
 * PATCH /api/v1/whatsapp/contacts/:id
 * Update contact
 */
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: UpdateContactDto = req.body;
    const contact = await contactService.update(ctx, req.params.id, data);

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

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

/**
 * POST /api/v1/whatsapp/contacts/:id/opt-in
 * Opt-in contact
 */
router.post('/:id/opt-in', 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 contact = await contactService.optIn(ctx, req.params.id);
    if (!contact) {
      return res.status(404).json({ error: 'Contact not found' });
    }

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

/**
 * POST /api/v1/whatsapp/contacts/:id/opt-out
 * Opt-out contact
 */
router.post('/:id/opt-out', 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 contact = await contactService.optOut(ctx, req.params.id);
    if (!contact) {
      return res.status(404).json({ error: 'Contact not found' });
    }

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

/**
 * POST /api/v1/whatsapp/contacts/:id/tags
 * Add tag to contact
 */
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 contact = await contactService.addTag(ctx, req.params.id, tag);
    if (!contact) {
      return res.status(404).json({ error: 'Contact not found' });
    }

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

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

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

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

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

export default router;
