/**
 * BranchInventorySettings Controller
 * API endpoints para gestión de configuración de inventario por sucursal
 *
 * @module Branches
 * @prefix /api/v1/branches/:branchId/inventory-settings
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  BranchInventorySettingsService,
  CreateBranchInventorySettingsDto,
  UpdateBranchInventorySettingsDto,
} from '../services/branch-inventory-settings.service';
import { ServiceContext } from '../services/branch.service';

const router = Router({ mergeParams: true });
const inventorySettingsService = new BranchInventorySettingsService();

/**
 * Helper to extract ServiceContext from request
 */
function getContext(req: Request): ServiceContext {
  return {
    tenantId: req.headers['x-tenant-id'] as string,
    userId: (req as any).user?.id,
  };
}

/**
 * GET /api/v1/branches/:branchId/inventory-settings
 * Obtiene la configuración de inventario de una sucursal
 */
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 { branchId } = req.params;
    const settings = await inventorySettingsService.findByBranch(getContext(req), branchId);

    if (!settings) {
      // Return effective settings with defaults if none configured
      const effective = await inventorySettingsService.getEffectiveSettings(getContext(req), branchId);
      return res.json({
        success: true,
        data: null,
        defaults: effective.defaults,
        message: 'No hay configuración específica, se usan valores por defecto',
      });
    }

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

/**
 * GET /api/v1/branches/:branchId/inventory-settings/effective
 * Obtiene la configuración efectiva (configurada o defaults)
 */
router.get('/effective', 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 { branchId } = req.params;
    const effective = await inventorySettingsService.getEffectiveSettings(getContext(req), branchId);

    // Merge settings with defaults
    const mergedSettings = {
      ...effective.defaults,
      ...(effective.settings || {}),
    };

    return res.json({
      success: true,
      data: mergedSettings,
      hasCustomSettings: !!effective.settings,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/branches/:branchId/inventory-settings
 * Crea la configuración de inventario para una sucursal
 */
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 { branchId } = req.params;
    const data: CreateBranchInventorySettingsDto = {
      ...req.body,
      branchId,
    };

    const settings = await inventorySettingsService.create(getContext(req), data);
    return res.status(201).json({ success: true, data: settings });
  } catch (error: any) {
    if (error.message?.includes('already exist')) {
      return res.status(409).json({ error: error.message });
    }
    return next(error);
  }
});

/**
 * PUT /api/v1/branches/:branchId/inventory-settings
 * Crea o actualiza la configuración de inventario (upsert)
 */
router.put('/', 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 { branchId } = req.params;
    const data: UpdateBranchInventorySettingsDto = req.body;

    const settings = await inventorySettingsService.upsertByBranch(getContext(req), branchId, data);
    return res.json({ success: true, data: settings });
  } catch (error) {
    return next(error);
  }
});

/**
 * PATCH /api/v1/branches/:branchId/inventory-settings
 * Actualiza parcialmente la configuración de inventario
 */
router.patch('/', 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 { branchId } = req.params;
    const existing = await inventorySettingsService.findByBranch(getContext(req), branchId);

    if (!existing) {
      return res.status(404).json({
        error: 'No hay configuración de inventario para esta sucursal. Use POST para crear.',
      });
    }

    const data: UpdateBranchInventorySettingsDto = req.body;
    const settings = await inventorySettingsService.update(getContext(req), existing.id, data);

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

/**
 * DELETE /api/v1/branches/:branchId/inventory-settings
 * Elimina la configuración de inventario (vuelve a defaults)
 */
router.delete('/', 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 { branchId } = req.params;
    const deleted = await inventorySettingsService.deleteByBranch(getContext(req), branchId);

    if (!deleted) {
      return res.status(404).json({ error: 'No hay configuración de inventario para esta sucursal' });
    }

    return res.json({
      success: true,
      message: 'Configuración de inventario eliminada, se usarán valores por defecto',
    });
  } catch (error) {
    return next(error);
  }
});

export default router;
