using GestionIntegral.Api.Dtos.Distribucion;
using GestionIntegral.Api.Services.Distribucion;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;

namespace GestionIntegral.Api.Controllers.Distribucion
{
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class PublicacionesController : ControllerBase
    {
        private readonly IPublicacionService _publicacionService;
        private readonly ILogger<PublicacionesController> _logger;

        // Permisos (DP001 a DP006)
        private const string PermisoVer = "DP001";
        private const string PermisoCrear = "DP002";
        private const string PermisoModificar = "DP003";
        // DP004 (Precios) y DP005 (Recargos) se manejarán en endpoints/controladores dedicados
        private const string PermisoEliminar = "DP006";
        // DP007 (Secciones) también se manejará por separado

        public PublicacionesController(IPublicacionService publicacionService, ILogger<PublicacionesController> logger)
        {
            _publicacionService = publicacionService;
            _logger = logger;
        }

        private bool TienePermiso(string codAcc) => User.IsInRole("SuperAdmin") || User.HasClaim(c => c.Type == "permission" && c.Value == codAcc);
        private int? GetCurrentUserId()
        {
            if (int.TryParse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub"), out int userId)) return userId;
            return null;
        }

        // GET: api/publicaciones
        [HttpGet]
        [ProducesResponseType(typeof(IEnumerable<PublicacionDto>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        public async Task<IActionResult> GetAllPublicaciones([FromQuery] string? nombre, [FromQuery] int? idEmpresa, [FromQuery] bool? soloHabilitadas)
        {
            if (!TienePermiso(PermisoVer)) return Forbid();
            var publicaciones = await _publicacionService.ObtenerTodasAsync(nombre, idEmpresa, soloHabilitadas);
            return Ok(publicaciones);
        }

        // GET: api/publicaciones/dropdown
        [HttpGet("dropdown")]
        [ProducesResponseType(typeof(IEnumerable<PublicacionDropdownDto>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status500InternalServerError)]
        // No se verifica permiso DP001, solo requiere autenticación general ([Authorize] del controlador)
        public async Task<IActionResult> GetPublicacionesForDropdown([FromQuery] bool? soloHabilitadas)
        {
            try
            {
                var publicaciones = await _publicacionService.ObtenerParaDropdownAsync(soloHabilitadas);
                return Ok(publicaciones);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error al obtener publicaciones para dropdown.");
                return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al obtener publicaciones para selección.");
            }
        }

        // GET: api/publicaciones/{id}
        [HttpGet("{id:int}", Name = "GetPublicacionById")]
        [ProducesResponseType(typeof(PublicacionDto), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task<IActionResult> GetPublicacionById(int id)
        {
            if (!TienePermiso(PermisoVer)) return Forbid();
            var publicacion = await _publicacionService.ObtenerPorIdAsync(id);
            if (publicacion == null) return NotFound();
            return Ok(publicacion);
        }

        // POST: api/publicaciones
        [HttpPost]
        [ProducesResponseType(typeof(PublicacionDto), StatusCodes.Status201Created)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        public async Task<IActionResult> CreatePublicacion([FromBody] CreatePublicacionDto createDto)
        {
            if (!TienePermiso(PermisoCrear)) return Forbid();
            if (!ModelState.IsValid) return BadRequest(ModelState);
            var userId = GetCurrentUserId();
            if (userId == null) return Unauthorized();

            var (dto, error) = await _publicacionService.CrearAsync(createDto, userId.Value);
            if (error != null) return BadRequest(new { message = error });
            if (dto == null) return StatusCode(StatusCodes.Status500InternalServerError, "Error al crear.");
            return CreatedAtRoute("GetPublicacionById", new { id = dto.IdPublicacion }, dto);
        }

        // PUT: api/publicaciones/{id}
        [HttpPut("{id:int}")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task<IActionResult> UpdatePublicacion(int id, [FromBody] UpdatePublicacionDto updateDto)
        {
            if (!TienePermiso(PermisoModificar)) return Forbid();
            if (!ModelState.IsValid) return BadRequest(ModelState);
            var userId = GetCurrentUserId();
            if (userId == null) return Unauthorized();

            var (exito, error) = await _publicacionService.ActualizarAsync(id, updateDto, userId.Value);
            if (!exito)
            {
                if (error == "Publicación no encontrada.") return NotFound(new { message = error });
                return BadRequest(new { message = error });
            }
            return NoContent();
        }

        // DELETE: api/publicaciones/{id}
        [HttpDelete("{id:int}")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task<IActionResult> DeletePublicacion(int id)
        {
            if (!TienePermiso(PermisoEliminar)) return Forbid();
            var userId = GetCurrentUserId();
            if (userId == null) return Unauthorized();

            var (exito, error) = await _publicacionService.EliminarAsync(id, userId.Value);
            if (!exito)
            {
                if (error == "Publicación no encontrada.") return NotFound(new { message = error });
                return BadRequest(new { message = error });
            }
            return NoContent();
        }

        // Endpoint para obtener la configuración de días de publicación para una publicación específica
        [HttpGet("{idPublicacion:int}/dias-semana")]
        [ProducesResponseType(typeof(IEnumerable<PublicacionDiaSemanaDto>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task<IActionResult> GetConfiguracionDiasPublicacion(int idPublicacion)
        {
            // Podrías usar el mismo permiso de ver publicaciones o uno específico
            if (!TienePermiso(PermisoVer)) return Forbid();

            var publicacion = await _publicacionService.ObtenerPorIdAsync(idPublicacion);
            if (publicacion == null) return NotFound(new { message = "Publicación no encontrada." });

            var configs = await _publicacionService.ObtenerConfiguracionDiasAsync(idPublicacion);
            return Ok(configs);
        }

        // Endpoint para actualizar las configuraciones de días para una publicación
        [HttpPut("{idPublicacion:int}/dias-semana")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task<IActionResult> UpdateConfiguracionDiasPublicacion(int idPublicacion, [FromBody] UpdatePublicacionDiasSemanaRequestDto requestDto)
        {
            // Podrías usar el mismo permiso de modificar publicaciones o uno específico
            if (!TienePermiso(PermisoModificar)) return Forbid();
            if (!ModelState.IsValid) return BadRequest(ModelState);

            var userId = GetCurrentUserId();
            if (userId == null) return Unauthorized();

            var (exito, error) = await _publicacionService.ActualizarConfiguracionDiasAsync(idPublicacion, requestDto, userId.Value);
            if (!exito)
            {
                if (error == "Publicación no encontrada.") return NotFound(new { message = error });
                return BadRequest(new { message = error });
            }
            return NoContent();
        }

        // Endpoint para obtener publicaciones por día de la semana (para el modal de canillitas)
        [HttpGet("por-dia-semana")]
        [ProducesResponseType(typeof(IEnumerable<PublicacionDto>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        public async Task<IActionResult> GetPublicacionesPorDia([FromQuery] byte dia) // dia: 0=Domingo, 1=Lunes...
        {
            // Generalmente, este endpoint no necesitaría un permiso estricto si solo devuelve datos públicos
            // pero puedes añadirlo si es necesario.
            // if (!TienePermiso(PermisoVer)) return Forbid(); 

            if (dia > 6) // byte no puede ser negativo
            {
                return BadRequest(new { message = "El día de la semana debe estar entre 0 (Domingo) y 6 (Sábado)." });
            }
            var publicaciones = await _publicacionService.ObtenerPublicacionesPorDiaSemanaAsync(dia);
            return Ok(publicaciones);
        }
    }
}