using GestionIntegral.Api.Services.Usuarios;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Security.Claims; // Para ClaimTypes
using GestionIntegral.Api.Services.Contables; // Para IPagoDistribuidorService, etc.
using GestionIntegral.Api.Services.Distribucion;
using GestionIntegral.Api.Dtos.Auditoria;
using GestionIntegral.Api.Dtos.Zonas;
using GestionIntegral.Api.Dtos.Distribucion;
using GestionIntegral.Api.Services.Impresion;
using GestionIntegral.Api.Dtos.Impresion;
using GestionIntegral.Api.Dtos.Usuarios;


namespace GestionIntegral.Api.Controllers
{
  [Route("api/auditoria")]
  [ApiController]
  [Authorize]
  public class AuditoriaController : ControllerBase
  {
    private readonly IUsuarioService _usuarioService;
    private readonly IPagoDistribuidorService _pagoDistribuidorService;
    private readonly INotaCreditoDebitoService _notaCreditoDebitoService;
    private readonly IEntradaSalidaDistService _esDistService;
    private readonly IDistribuidorService _distribuidorService;
    private readonly IEntradaSalidaCanillaService _esCanillaService;
    private readonly INovedadCanillaService _novedadCanillaService;
    private readonly ICanillaService _canillaService;
    private readonly ISaldoService _saldoService;
    private readonly ITipoPagoService _tipoPagoService;
    private readonly IEmpresaService _empresaService;
    private readonly IZonaService _zonaService;
    private readonly IOtroDestinoService _otroDestinoService;
    private readonly IPublicacionService _publicacionService;
    private readonly IPubliSeccionService _publiSeccionService;
    private readonly IPrecioService _precioService;
    private readonly IRecargoZonaService _recargoZonaService;
    private readonly IPorcPagoService _porcPagoService;
    private readonly IPorcMonCanillaService _porcMonCanillaService;
    private readonly IControlDevolucionesService _controlDevolucionesService;
    private readonly ITipoBobinaService _tipoBobinaService;
    private readonly IEstadoBobinaService _estadoBobinaService;
    private readonly IPlantaService _plantaService;
    private readonly IStockBobinaService _stockBobinaService;
    private readonly ITiradaService _tiradaService;
    private readonly IPerfilService _perfilService;
    private readonly IPermisoService _permisoService;
    private readonly ICambioParadaService _cambioParadaService;
    private readonly ICierreCuentaCorrienteService _cierreCcService;
    private readonly ILogger<AuditoriaController> _logger;

    // Permiso general para ver cualquier auditoría.
    // Podrías tener permisos más granulares por tipo de auditoría si es necesario.
    private const string PermisoVerAuditoria = "AU_GENERAL_VIEW"; // Define este permiso

    public AuditoriaController(
        IUsuarioService usuarioService,
        IPagoDistribuidorService pagoDistribuidorService,
        INotaCreditoDebitoService notaCreditoDebitoService,
        IEntradaSalidaDistService esDistService,
        IDistribuidorService distribuidorService,
        IEntradaSalidaCanillaService esCanillaService,
        INovedadCanillaService novedadCanillaService,
        ICanillaService canillaService,
        ISaldoService saldoService,
        ITipoPagoService tipoPagoService,
        IEmpresaService empresaService,
        IZonaService zonaService,
        IOtroDestinoService otroDestinoService,
        IPublicacionService publicacionService,
        IPubliSeccionService publiSeccionService,
        IPrecioService precioService,
        IRecargoZonaService recargoZonaService,
        IPorcPagoService porcPagoService,
        IPorcMonCanillaService porcMonCanillaService,
        IControlDevolucionesService controlDevolucionesService,
        ITipoBobinaService tipoBobinaService,
        IEstadoBobinaService estadoBobinaService,
        IPlantaService plantaService,
        IStockBobinaService stockBobinaService,
        ITiradaService tiradaService,
        IPerfilService perfilService,
        IPermisoService permisoService,
        ICambioParadaService cambioParadaService,
        ICierreCuentaCorrienteService cierreCcService,
        ILogger<AuditoriaController> logger)
    {
      _usuarioService = usuarioService;
      _pagoDistribuidorService = pagoDistribuidorService;
      _notaCreditoDebitoService = notaCreditoDebitoService;
      _esDistService = esDistService;
      _distribuidorService = distribuidorService;
      _esCanillaService = esCanillaService;
      _novedadCanillaService = novedadCanillaService;
      _canillaService = canillaService;
      _saldoService = saldoService;
      _tipoPagoService = tipoPagoService;
      _empresaService = empresaService;
      _zonaService = zonaService;
      _otroDestinoService = otroDestinoService;
      _publicacionService = publicacionService;
      _publiSeccionService = publiSeccionService;
      _precioService = precioService;
      _recargoZonaService = recargoZonaService;
      _porcPagoService = porcPagoService;
      _porcMonCanillaService = porcMonCanillaService;
      _controlDevolucionesService = controlDevolucionesService;
      _tipoBobinaService = tipoBobinaService;
      _estadoBobinaService = estadoBobinaService;
      _plantaService = plantaService;
      _stockBobinaService = stockBobinaService;
      _tiradaService = tiradaService;
      _perfilService = perfilService;
      _cambioParadaService = cambioParadaService;
      _permisoService = permisoService;
      _cierreCcService = cierreCcService;
      _logger = logger;
    }

    private bool TienePermiso(string codAcc) => User.IsInRole("SuperAdmin") || User.HasClaim(c => c.Type == "permission" && c.Value == codAcc);
    private int? GetCurrentUserId() // Podría no ser necesario aquí si solo filtramos por usuario modificador
    {
      if (int.TryParse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub"), out int userId)) return userId;
      return null;
    }

    [HttpGet("pagos-distribuidores")]
    [ProducesResponseType(typeof(IEnumerable<PagoDistribuidorHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPagosDistribuidor(
            [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
            [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
            [FromQuery] int? idPagoAfectado) // Parámetro para filtrar por un ID de pago específico
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid(); // O un permiso más específico si lo creas
      try
      {
        var historial = await _pagoDistribuidorService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPagoAfectado);
        return Ok(historial ?? Enumerable.Empty<PagoDistribuidorHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de pagos de distribuidores.");
        return StatusCode(500, "Error interno al obtener historial de pagos.");
      }
    }

    [HttpGet("notas-credito-debito")]
    [ProducesResponseType(typeof(IEnumerable<NotaCreditoDebitoHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialNotasCD(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idNotaAfectada) // ID de la nota original
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _notaCreditoDebitoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idNotaAfectada);
        return Ok(historial ?? Enumerable.Empty<NotaCreditoDebitoHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de notas C/D.");
        return StatusCode(500, "Error interno al obtener historial de notas C/D.");
      }
    }

    [HttpGet("entradas-salidas-dist")]
    [ProducesResponseType(typeof(IEnumerable<EntradaSalidaDistHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialEntradasSalidasDist(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idParteAfectada) // ID del movimiento original
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _esDistService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idParteAfectada);
        return Ok(historial ?? Enumerable.Empty<EntradaSalidaDistHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de E/S Distribuidores.");
        return StatusCode(500, "Error interno al obtener historial de E/S Distribuidores.");
      }
    }

    [HttpGet("entradas-salidas-canilla")]
    [ProducesResponseType(typeof(IEnumerable<EntradaSalidaCanillaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialEntradasSalidasCanilla(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idParteAfectada)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _esCanillaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idParteAfectada);
        return Ok(historial ?? Enumerable.Empty<EntradaSalidaCanillaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de E/S Canillitas.");
        return StatusCode(500, "Error interno al obtener historial de E/S Canillitas.");
      }
    }

    [HttpGet("novedades-canilla")] // Endpoint consistente con el servicio frontend
    [ProducesResponseType(typeof(IEnumerable<NovedadCanillaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialNovedadesCanilla(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idNovedadAfectada) // ID de la novedad original
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _novedadCanillaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idNovedadAfectada);
        return Ok(historial ?? Enumerable.Empty<NovedadCanillaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Novedades de Canillitas.");
        return StatusCode(500, "Error interno al obtener historial de Novedades de Canillitas.");
      }
    }

    [HttpGet("ajustes-saldo")]
    [ProducesResponseType(typeof(IEnumerable<SaldoAjusteHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialAjustesSaldo(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico,
        [FromQuery] string? destino, [FromQuery] int? idDestino, [FromQuery] int? idEmpresa)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid(); // O un permiso más específico si lo creas
      try
      {
        var historial = await _saldoService.ObtenerHistorialAjustesAsync(fechaDesde, fechaHasta, idUsuarioModifico, destino, idDestino, idEmpresa);
        return Ok(historial ?? Enumerable.Empty<SaldoAjusteHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de ajustes de saldo.");
        return StatusCode(500, "Error interno al obtener historial de ajustes de saldo.");
      }
    }

    [HttpGet("tipos-pago")]
    [ProducesResponseType(typeof(IEnumerable<TipoPagoHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialTiposPago(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idTipoPagoAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        // Asumiendo que _tipoPagoService está inyectado
        var historial = await _tipoPagoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idTipoPagoAfectado);
        return Ok(historial ?? Enumerable.Empty<TipoPagoHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Tipos de Pago.");
        return StatusCode(500, "Error interno al obtener historial de Tipos de Pago.");
      }
    }

    [HttpGet("canillitas-maestro")] // Endpoint para el historial del maestro de canillitas
    [ProducesResponseType(typeof(IEnumerable<CanillaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialCanillitasMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idCanillaAfectado) // ID del canillita original
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _canillaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idCanillaAfectado);
        return Ok(historial ?? Enumerable.Empty<CanillaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Canillitas (Maestro).");
        return StatusCode(500, "Error interno al obtener historial de Canillitas (Maestro).");
      }
    }

    [HttpGet("distribuidores-maestro")]
    [ProducesResponseType(typeof(IEnumerable<DistribuidorHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialDistribuidoresMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idDistribuidorAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _distribuidorService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idDistribuidorAfectado);
        return Ok(historial ?? Enumerable.Empty<DistribuidorHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Distribuidores (Maestro).");
        return StatusCode(500, "Error interno al obtener historial de Distribuidores (Maestro).");
      }
    }

    [HttpGet("empresas-maestro")]
    [ProducesResponseType(typeof(IEnumerable<EmpresaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialEmpresasMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idEmpresaAfectada)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        // Asumiendo que _empresaService está inyectado
        var historial = await _empresaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idEmpresaAfectada);
        return Ok(historial ?? Enumerable.Empty<EmpresaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Empresas (Maestro).");
        return StatusCode(500, "Error interno al obtener historial de Empresas (Maestro).");
      }
    }

    [HttpGet("zonas-maestro")]
    [ProducesResponseType(typeof(IEnumerable<ZonaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialZonasMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idZonaAfectada)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        // Asumiendo que _zonaService está inyectado
        var historial = await _zonaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idZonaAfectada);
        return Ok(historial ?? Enumerable.Empty<ZonaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Zonas (Maestro).");
        return StatusCode(500, "Error interno al obtener historial de Zonas (Maestro).");
      }
    }

    [HttpGet("otros-destinos-maestro")]
    [ProducesResponseType(typeof(IEnumerable<OtroDestinoHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialOtrosDestinosMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idOtroDestinoAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _otroDestinoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idOtroDestinoAfectado);
        return Ok(historial ?? Enumerable.Empty<OtroDestinoHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Otros Destinos (Maestro).");
        return StatusCode(500, "Error interno al obtener historial de Otros Destinos (Maestro).");
      }
    }

    [HttpGet("publicaciones-maestro")]
    [ProducesResponseType(typeof(IEnumerable<PublicacionHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPublicacionesMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idPublicacionAfectada)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _publicacionService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPublicacionAfectada);
        return Ok(historial ?? Enumerable.Empty<PublicacionHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Publicaciones (Maestro).");
        return StatusCode(500, "Error interno al obtener historial de Publicaciones (Maestro).");
      }
    }

    [HttpGet("publi-secciones-maestro")]
    [ProducesResponseType(typeof(IEnumerable<PubliSeccionHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPubliSeccionesMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idSeccionAfectada, [FromQuery] int? idPublicacionAfectada) // Nuevos filtros
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _publiSeccionService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idSeccionAfectada, idPublicacionAfectada);
        return Ok(historial ?? Enumerable.Empty<PubliSeccionHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Secciones de Publicación.");
        return StatusCode(500, "Error interno al obtener historial de Secciones de Publicación.");
      }
    }

    [HttpGet("precios-publicacion-maestro")]
    [ProducesResponseType(typeof(IEnumerable<PrecioHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPreciosMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idPrecioAfectado, [FromQuery] int? idPublicacionAfectada)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _precioService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPrecioAfectado, idPublicacionAfectada);
        return Ok(historial ?? Enumerable.Empty<PrecioHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Precios de Publicación.");
        return StatusCode(500, "Error interno al obtener historial de Precios de Publicación.");
      }
    }

    [HttpGet("recargos-zona-maestro")]
    [ProducesResponseType(typeof(IEnumerable<RecargoZonaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialRecargosZonaMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idRecargoAfectado, [FromQuery] int? idPublicacionAfectada, [FromQuery] int? idZonaAfectada)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _recargoZonaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idRecargoAfectado, idPublicacionAfectada, idZonaAfectada);
        return Ok(historial ?? Enumerable.Empty<RecargoZonaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Recargos por Zona.");
        return StatusCode(500, "Error interno al obtener historial de Recargos por Zona.");
      }
    }

    [HttpGet("porc-pago-dist-maestro")]
    [ProducesResponseType(typeof(IEnumerable<PorcPagoHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPorcPagoDistMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idPorcentajeAfectado, [FromQuery] int? idPublicacionAfectada, [FromQuery] int? idDistribuidorAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _porcPagoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPorcentajeAfectado, idPublicacionAfectada, idDistribuidorAfectado);
        return Ok(historial ?? Enumerable.Empty<PorcPagoHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Porcentajes de Pago (Dist).");
        return StatusCode(500, "Error interno al obtener historial de Porcentajes de Pago (Dist).");
      }
    }

    [HttpGet("porc-mon-canilla-maestro")]
    [ProducesResponseType(typeof(IEnumerable<PorcMonCanillaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPorcMonCanillaMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idPorcMonAfectado, [FromQuery] int? idPublicacionAfectada, [FromQuery] int? idCanillaAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _porcMonCanillaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPorcMonAfectado, idPublicacionAfectada, idCanillaAfectado);
        return Ok(historial ?? Enumerable.Empty<PorcMonCanillaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Porc/Mon Canillita.");
        return StatusCode(500, "Error interno al obtener historial de Porc/Mon Canillita.");
      }
    }

    [HttpGet("control-devoluciones-maestro")]
    [ProducesResponseType(typeof(IEnumerable<ControlDevolucionesHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialControlDevolucionesMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idControlAfectado, [FromQuery] int? idEmpresaAfectada, [FromQuery] DateTime? fechaAfectada)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _controlDevolucionesService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idControlAfectado, idEmpresaAfectada, fechaAfectada);
        return Ok(historial ?? Enumerable.Empty<ControlDevolucionesHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Control de Devoluciones.");
        return StatusCode(500, "Error interno al obtener historial de Control de Devoluciones.");
      }
    }

    [HttpGet("tipos-bobina-maestro")]
    [ProducesResponseType(typeof(IEnumerable<TipoBobinaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialTiposBobinaMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idTipoBobinaAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _tipoBobinaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idTipoBobinaAfectado);
        return Ok(historial ?? Enumerable.Empty<TipoBobinaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Tipos de Bobina.");
        return StatusCode(500, "Error interno al obtener historial de Tipos de Bobina.");
      }
    }

    [HttpGet("estados-bobina-maestro")]
    [ProducesResponseType(typeof(IEnumerable<EstadoBobinaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialEstadosBobinaMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idEstadoBobinaAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _estadoBobinaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idEstadoBobinaAfectado);
        return Ok(historial ?? Enumerable.Empty<EstadoBobinaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Estados de Bobina.");
        return StatusCode(500, "Error interno al obtener historial de Estados de Bobina.");
      }
    }

    [HttpGet("plantas-impresion-maestro")]
    [ProducesResponseType(typeof(IEnumerable<PlantaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPlantasMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idPlantaAfectada)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _plantaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPlantaAfectada);
        return Ok(historial ?? Enumerable.Empty<PlantaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Plantas de Impresión.");
        return StatusCode(500, "Error interno al obtener historial de Plantas de Impresión.");
      }
    }

    [HttpGet("stock-bobinas-maestro")]
    [ProducesResponseType(typeof(IEnumerable<StockBobinaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialStockBobinasMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idBobinaAfectada, [FromQuery] int? idTipoBobinaFiltro,
        [FromQuery] int? idPlantaFiltro, [FromQuery] int? idEstadoBobinaFiltro)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _stockBobinaService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idBobinaAfectada, idTipoBobinaFiltro, idPlantaFiltro, idEstadoBobinaFiltro);
        return Ok(historial ?? Enumerable.Empty<StockBobinaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Stock de Bobinas.");
        return StatusCode(500, "Error interno al obtener historial de Stock de Bobinas.");
      }
    }

    [HttpGet("reg-tiradas-maestro")]
    [ProducesResponseType(typeof(IEnumerable<RegTiradaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialRegTiradasMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idRegistroAfectado, [FromQuery] int? idPublicacionFiltro,
        [FromQuery] int? idPlantaFiltro, [FromQuery] DateTime? fechaTiradaFiltro)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _tiradaService.ObtenerRegTiradasHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idRegistroAfectado, idPublicacionFiltro, idPlantaFiltro, fechaTiradaFiltro);
        return Ok(historial ?? Enumerable.Empty<RegTiradaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Registro de Tiradas.");
        return StatusCode(500, "Error interno al obtener historial de Registro de Tiradas.");
      }
    }

    [HttpGet("reg-secciones-tirada-maestro")]
    [ProducesResponseType(typeof(IEnumerable<RegSeccionTiradaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialRegSeccionesTiradaMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idTiradaAfectada, [FromQuery] int? idPublicacionFiltro,
        [FromQuery] int? idSeccionFiltro, [FromQuery] int? idPlantaFiltro, [FromQuery] DateTime? fechaTiradaFiltro)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _tiradaService.ObtenerRegSeccionesTiradaHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idTiradaAfectada, idPublicacionFiltro, idSeccionFiltro, idPlantaFiltro, fechaTiradaFiltro);
        return Ok(historial ?? Enumerable.Empty<RegSeccionTiradaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Secciones de Tirada.");
        return StatusCode(500, "Error interno al obtener historial de Secciones de Tirada.");
      }
    }

    [HttpGet("perfiles-maestro")]
    [ProducesResponseType(typeof(IEnumerable<PerfilHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPerfilesMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idPerfilAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _perfilService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPerfilAfectado);
        return Ok(historial ?? Enumerable.Empty<PerfilHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Perfiles (Maestro).");
        return StatusCode(500, "Error interno al obtener historial de Perfiles (Maestro).");
      }
    }

    [HttpGet("permisos-maestro")]
    [ProducesResponseType(typeof(IEnumerable<PermisoHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPermisosMaestro(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idPermisoAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _permisoService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPermisoAfectado);
        return Ok(historial ?? Enumerable.Empty<PermisoHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Permisos (Maestro).");
        return StatusCode(500, "Error interno al obtener historial de Permisos (Maestro).");
      }
    }

    [HttpGet("permisos-perfiles-historial")]
    [ProducesResponseType(typeof(IEnumerable<PermisosPerfilesHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialPermisosPerfiles(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idPerfilAfectado, [FromQuery] int? idPermisoAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _perfilService.ObtenerPermisosAsignadosHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idPerfilAfectado, idPermisoAfectado);
        return Ok(historial ?? Enumerable.Empty<PermisosPerfilesHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Asignación de Permisos.");
        return StatusCode(500, "Error interno al obtener historial de Asignación de Permisos.");
      }
    }

    [HttpGet("cierres-cuenta-corriente")]
    [ProducesResponseType(typeof(IEnumerable<CierreCuentaCorrienteHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialCierresCuentaCorriente(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idCierreAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _cierreCcService.ObtenerHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idCierreAfectado);
        return Ok(historial ?? Enumerable.Empty<CierreCuentaCorrienteHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Cierres de Cuenta Corriente.");
        return StatusCode(500, "Error interno al obtener historial de Cierres de Cuenta Corriente.");
      }
    }

    [HttpGet("cambios-parada-canilla")]
    [ProducesResponseType(typeof(IEnumerable<CambioParadaHistorialDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetHistorialCambiosParada(
        [FromQuery] DateTime? fechaDesde, [FromQuery] DateTime? fechaHasta,
        [FromQuery] int? idUsuarioModifico, [FromQuery] string? tipoModificacion,
        [FromQuery] int? idCanillaAfectado)
    {
      if (!TienePermiso(PermisoVerAuditoria)) return Forbid();
      try
      {
        var historial = await _cambioParadaService.ObtenerCambiosParadaHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idCanillaAfectado);
        return Ok(historial ?? Enumerable.Empty<CambioParadaHistorialDto>());
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "Error obteniendo historial de Cambios de Parada.");
        return StatusCode(500, "Error interno al obtener historial de Cambios de Parada.");
      }
    }
  }
}