/**
 * Nivel Controller
 * API endpoints para gestión de niveles/pisos
 *
 * @module Construction (MAI-002)
 * @prefix /api/v1/niveles
 */

import { Router, Request, Response, NextFunction } from 'express';
import { NivelService, CreateNivelDto, UpdateNivelDto } from '../services/nivel.service';

const router = Router();
const nivelService = new NivelService(null as any);

/**
 * GET /api/v1/niveles
 * Lista todos los niveles 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 { torreId, search, page, limit } = req.query;

    const result = await nivelService.findAll(
      { tenantId },
      {
        torreId: torreId as string,
        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/niveles/statistics
 * Estadísticas de niveles
 */
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 { torreId } = req.query;
    const stats = await nivelService.getStatistics({ tenantId }, torreId as string);

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

/**
 * GET /api/v1/niveles/by-torre/:torreId
 * Niveles por torre
 */
router.get('/by-torre/:torreId', 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 data = await nivelService.findByTorre({ tenantId }, req.params.torreId);
    return res.json({ success: true, data, count: data.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/niveles/:id
 * Obtiene un nivel 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 nivel = await nivelService.findById({ tenantId }, req.params.id);
    if (!nivel) {
      return res.status(404).json({ error: 'Nivel no encontrado' });
    }

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

/**
 * POST /api/v1/niveles
 * Crea un nuevo nivel
 */
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: CreateNivelDto = req.body;

    if (!dto.torreId || dto.floorNumber === undefined) {
      return res.status(400).json({ error: 'torreId y floorNumber son requeridos' });
    }

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

/**
 * POST /api/v1/niveles/bulk
 * Crea múltiples niveles para una torre
 */
router.post('/bulk', 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 { torreId, totalFloors } = req.body;

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

    if (totalFloors < 1 || totalFloors > 100) {
      return res.status(400).json({ error: 'totalFloors debe estar entre 1 y 100' });
    }

    const niveles = await nivelService.createBulk({ tenantId, userId }, torreId, Number(totalFloors));
    return res.status(201).json({
      success: true,
      data: niveles,
      count: niveles.length,
      message: `${niveles.length} niveles creados`,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * PATCH /api/v1/niveles/:id
 * Actualiza un nivel
 */
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: UpdateNivelDto = req.body;

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

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

/**
 * POST /api/v1/niveles/:id/recalculate-units
 * Recalcula el total de unidades de un nivel
 */
router.post('/:id/recalculate-units', 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 nivel = await nivelService.updateUnitCount({ tenantId, userId }, req.params.id);

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

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

/**
 * DELETE /api/v1/niveles/:id
 * Elimina un nivel (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 nivelService.softDelete({ tenantId, userId }, req.params.id);

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

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

export default router;
