/**
 * Checklist Controller
 * API endpoints para plantillas de inspección de calidad
 *
 * @module Quality (MAI-009)
 * @prefix /api/v1/checklists
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  ChecklistService,
  CreateChecklistDto,
  UpdateChecklistDto,
  CreateChecklistItemDto,
  UpdateChecklistItemDto,
} from '../services/checklist.service';
import { ChecklistStage } from '../entities/checklist.entity';

const router = Router();
const checklistService = new ChecklistService(null as any, null as any);

/**
 * GET /api/v1/checklists
 * Lista todos los checklists del tenant
 */
router.get('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { stage, prototypeId, isActive, search, page, limit } = req.query;

    const result = await checklistService.findAll(
      { tenantId },
      {
        stage: stage as ChecklistStage,
        prototypeId: prototypeId as string,
        isActive: isActive !== undefined ? isActive === 'true' : undefined,
        search: search as string,
        page: page ? Number(page) : undefined,
        limit: limit ? Number(limit) : undefined,
      },
    );

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

/**
 * GET /api/v1/checklists/statistics
 * Estadísticas de checklists
 */
router.get('/statistics', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const stats = await checklistService.getStatistics({ tenantId });
    return res.json({ success: true, data: stats });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/checklists/by-stage/:stage
 * Checklists por etapa de construcción
 */
router.get('/by-stage/:stage', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const stage = req.params.stage as ChecklistStage;
    const validStages: ChecklistStage[] = [
      'foundation', 'structure', 'installations',
      'finishes', 'delivery', 'custom',
    ];

    if (!validStages.includes(stage)) {
      return res.status(400).json({ error: `Etapa inválida. Válidas: ${validStages.join(', ')}` });
    }

    const data = await checklistService.findByStage({ tenantId }, stage);
    return res.json({ success: true, data, count: data.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/checklists/by-code/:code
 * Buscar checklist por código
 */
router.get('/by-code/:code', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const checklist = await checklistService.findByCode({ tenantId }, req.params.code);
    if (!checklist) {
      return res.status(404).json({ error: 'Checklist no encontrado' });
    }

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

/**
 * GET /api/v1/checklists/:id
 * Obtiene un checklist por ID
 */
router.get('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const checklist = await checklistService.findById({ tenantId }, req.params.id);
    if (!checklist) {
      return res.status(404).json({ error: 'Checklist no encontrado' });
    }

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

/**
 * GET /api/v1/checklists/:id/with-items
 * Obtiene un checklist con todos sus items
 */
router.get('/:id/with-items', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const checklist = await checklistService.findWithItems({ tenantId }, req.params.id);
    if (!checklist) {
      return res.status(404).json({ error: 'Checklist no encontrado' });
    }

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

/**
 * POST /api/v1/checklists
 * Crea un nuevo checklist
 */
router.post('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const dto: CreateChecklistDto = req.body;

    if (!dto.code || !dto.name || !dto.stage) {
      return res.status(400).json({ error: 'code, name y stage son requeridos' });
    }

    const checklist = await checklistService.create({ tenantId, userId }, dto);
    return res.status(201).json({ success: true, data: checklist });
  } catch (error: any) {
    if (error.message?.includes('already exists')) {
      return res.status(409).json({ error: error.message });
    }
    return next(error);
  }
});

/**
 * PATCH /api/v1/checklists/:id
 * Actualiza un checklist
 */
router.patch('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const dto: UpdateChecklistDto = req.body;

    const checklist = await checklistService.update({ tenantId, userId }, req.params.id, dto);
    if (!checklist) {
      return res.status(404).json({ error: 'Checklist no encontrado' });
    }

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

/**
 * POST /api/v1/checklists/:id/activate
 * Activa un checklist
 */
router.post('/:id/activate', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const checklist = await checklistService.activate({ tenantId, userId }, req.params.id);

    if (!checklist) {
      return res.status(404).json({ error: 'Checklist no encontrado' });
    }

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

/**
 * POST /api/v1/checklists/:id/deactivate
 * Desactiva un checklist
 */
router.post('/:id/deactivate', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const checklist = await checklistService.deactivate({ tenantId, userId }, req.params.id);

    if (!checklist) {
      return res.status(404).json({ error: 'Checklist no encontrado' });
    }

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

/**
 * POST /api/v1/checklists/:id/duplicate
 * Duplica un checklist con nuevo código y nombre
 */
router.post('/:id/duplicate', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const { newCode, newName } = req.body;

    if (!newCode || !newName) {
      return res.status(400).json({ error: 'newCode y newName son requeridos' });
    }

    const checklist = await checklistService.duplicate({ tenantId, userId }, req.params.id, newCode, newName);
    if (!checklist) {
      return res.status(404).json({ error: 'Checklist no encontrado' });
    }

    return res.status(201).json({ success: true, data: checklist, message: 'Checklist duplicado' });
  } catch (error: any) {
    if (error.message?.includes('already exists')) {
      return res.status(409).json({ error: error.message });
    }
    return next(error);
  }
});

/**
 * DELETE /api/v1/checklists/:id
 * Elimina un checklist (soft delete)
 */
router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const deleted = await checklistService.softDelete({ tenantId, userId }, req.params.id);

    if (!deleted) {
      return res.status(404).json({ error: 'Checklist no encontrado' });
    }

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

// ─────────────────────────────────────────────────────────────────────────────
// ITEMS ENDPOINTS
// ─────────────────────────────────────────────────────────────────────────────

/**
 * POST /api/v1/checklists/:id/items
 * Agrega un item al checklist
 */
router.post('/:id/items', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const dto: CreateChecklistItemDto = req.body;

    if (dto.sequenceNumber === undefined || !dto.category || !dto.description) {
      return res.status(400).json({ error: 'sequenceNumber, category y description son requeridos' });
    }

    const item = await checklistService.addItem({ tenantId, userId }, req.params.id, dto);
    return res.status(201).json({ success: true, data: item });
  } catch (error: any) {
    if (error.message?.includes('not found')) {
      return res.status(404).json({ error: error.message });
    }
    return next(error);
  }
});

/**
 * PATCH /api/v1/checklists/:checklistId/items/:itemId
 * Actualiza un item del checklist
 */
router.patch('/:checklistId/items/:itemId', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const dto: UpdateChecklistItemDto = req.body;

    const item = await checklistService.updateItem({ tenantId, userId }, req.params.itemId, dto);
    if (!item) {
      return res.status(404).json({ error: 'Item no encontrado' });
    }

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

/**
 * DELETE /api/v1/checklists/:checklistId/items/:itemId
 * Elimina un item del checklist
 */
router.delete('/:checklistId/items/:itemId', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const deleted = await checklistService.removeItem({ tenantId, userId }, req.params.itemId);

    if (!deleted) {
      return res.status(404).json({ error: 'Item no encontrado' });
    }

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

/**
 * POST /api/v1/checklists/:id/items/reorder
 * Reordena los items de un checklist
 */
router.post('/:id/items/reorder', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const { itemOrders } = req.body;

    if (!itemOrders || !Array.isArray(itemOrders)) {
      return res.status(400).json({ error: 'itemOrders es requerido y debe ser un array' });
    }

    const success = await checklistService.reorderItems({ tenantId, userId }, req.params.id, itemOrders);
    if (!success) {
      return res.status(404).json({ error: 'Checklist no encontrado' });
    }

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

export default router;
