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

namespace GestionIntegral.Api.Controllers.Contables
{
    [Route("api/cierres-cc")]
    [ApiController]
    [Authorize]
    public class CierresCuentaCorrienteController : ControllerBase
    {
        private readonly ICierreCuentaCorrienteService _cierreService;
        private readonly ILogger<CierresCuentaCorrienteController> _logger;

        // Permisos asignables a perfiles. La reapertura es exclusiva de SuperAdmin
        // y se valida con User.IsInRole('SuperAdmin') — no tiene código en gral_Permisos.
        private const string PermisoCrear = "CC001";
        private const string PermisoVer = "CC003";

        public CierresCuentaCorrienteController(
            ICierreCuentaCorrienteService cierreService,
            ILogger<CierresCuentaCorrienteController> logger)
        {
            _cierreService = cierreService;
            _logger = logger;
        }

        private bool TienePermiso(string codAcc) =>
            User.IsInRole("SuperAdmin") || User.HasClaim(c => c.Type == "permission" && c.Value == codAcc);

        private bool EsSuperAdmin() => User.IsInRole("SuperAdmin");

        private int? GetCurrentUserId()
        {
            if (int.TryParse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub"), out int userId))
                return userId;
            _logger.LogWarning("No se pudo obtener el UserId del token JWT en CierresCuentaCorrienteController.");
            return null;
        }

        // POST: api/cierres-cc
        [HttpPost]
        [ProducesResponseType(typeof(CierreCuentaCorrienteDto), StatusCodes.Status201Created)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        [ProducesResponseType(StatusCodes.Status409Conflict)]
        public async Task<IActionResult> Crear([FromBody] CrearCierreDto dto)
        {
            if (!TienePermiso(PermisoCrear)) return Forbid();
            if (!ModelState.IsValid) return BadRequest(ModelState);
            var userId = GetCurrentUserId();
            if (userId == null) return Unauthorized();

            var (cierre, errorCode, errorMessage) = await _cierreService.CrearCierreAsync(dto, userId.Value);

            if (errorCode != null)
            {
                int status = errorCode switch
                {
                    "CIERRE_FECHA_ANTERIOR_A_ULTIMO" => StatusCodes.Status409Conflict,
                    "CIERRE_ERROR_INTERNO"           => StatusCodes.Status500InternalServerError,
                    _                                => StatusCodes.Status400BadRequest
                };
                return StatusCode(status, new { codigo = errorCode, mensaje = errorMessage });
            }

            return StatusCode(StatusCodes.Status201Created, cierre);
        }

        // POST: api/cierres-cc/{idCierre}/reabrir
        [HttpPost("{idCierre:int}/reabrir")]
        [ProducesResponseType(typeof(CierreCuentaCorrienteDto), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        [ProducesResponseType(StatusCodes.Status409Conflict)]
        public async Task<IActionResult> Reabrir(int idCierre, [FromBody] ReabrirCierreDto dto)
        {
            if (!EsSuperAdmin())
                return Forbid();
            if (!ModelState.IsValid) return BadRequest(ModelState);
            var userId = GetCurrentUserId();
            if (userId == null) return Unauthorized();

            var (cierre, errorCode, errorMessage) = await _cierreService.ReabrirCierreAsync(idCierre, dto, userId.Value, esSuperAdmin: true);

            if (errorCode != null)
            {
                int status = errorCode switch
                {
                    "CIERRE_NO_ENCONTRADO"           => StatusCodes.Status404NotFound,
                    "CIERRE_PERMISO_DENEGADO"        => StatusCodes.Status403Forbidden,
                    "CIERRE_HAY_POSTERIORES_VIGENTES" => StatusCodes.Status409Conflict,
                    "CIERRE_YA_ANULADO"              => StatusCodes.Status409Conflict,
                    "CIERRE_ERROR_INTERNO"           => StatusCodes.Status500InternalServerError,
                    _                                => StatusCodes.Status400BadRequest
                };
                return StatusCode(status, new { codigo = errorCode, mensaje = errorMessage });
            }

            return Ok(cierre);
        }

        // GET: api/cierres-cc?idDistribuidor=&idEmpresa=&estado=&fechaCorteDesde=&fechaCorteHasta=
        [HttpGet]
        [ProducesResponseType(typeof(IEnumerable<CierreCuentaCorrienteDto>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        public async Task<IActionResult> GetAll(
            [FromQuery] int? idDistribuidor,
            [FromQuery] int? idEmpresa,
            [FromQuery] string? estado,
            [FromQuery] DateTime? fechaCorteDesde,
            [FromQuery] DateTime? fechaCorteHasta)
        {
            if (!TienePermiso(PermisoVer)) return Forbid();
            var cierres = await _cierreService.GetAllAsync(idDistribuidor, idEmpresa, estado, fechaCorteDesde, fechaCorteHasta);
            return Ok(cierres);
        }

        // GET: api/cierres-cc/{idCierre}
        [HttpGet("{idCierre:int}")]
        [ProducesResponseType(typeof(CierreCuentaCorrienteDto), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task<IActionResult> GetById(int idCierre)
        {
            if (!TienePermiso(PermisoVer)) return Forbid();
            var cierre = await _cierreService.GetByIdAsync(idCierre);
            if (cierre == null) return NotFound(new { message = $"Cierre #{idCierre} no encontrado." });
            return Ok(cierre);
        }

        // GET: api/cierres-cc/ultimo?idDistribuidor=&idEmpresa=
        // Atajo del frontend para autorrellenar "Desde último cierre" en filtros del reporte.
        // Acepta CC003 (gestión de cierres) o RR001 (acceso al reporte que CONTIENE este atajo):
        // operadores con solo el permiso del reporte deben poder usar el atajo desde la pantalla del reporte.
        [HttpGet("ultimo")]
        [ProducesResponseType(typeof(UltimoCierreDto), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task<IActionResult> GetUltimoVigente(
            [FromQuery] int idDistribuidor,
            [FromQuery] int idEmpresa)
        {
            if (!TienePermiso(PermisoVer) && !TienePermiso("RR001")) return Forbid();
            var ultimo = await _cierreService.GetUltimoVigenteAsync(idDistribuidor, idEmpresa);
            if (ultimo == null) return NotFound(new { message = "No hay cierres vigentes para el distribuidor en la empresa indicada." });
            return Ok(ultimo);
        }

        // GET: api/cierres-cc/{idCierre}/historial
        [HttpGet("{idCierre:int}/historial")]
        [ProducesResponseType(typeof(IEnumerable<CierreCuentaCorrienteHistorialDto>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
        public async Task<IActionResult> GetHistorial(int idCierre)
        {
            if (!TienePermiso(PermisoVer)) return Forbid();
            var historial = await _cierreService.GetHistorialAsync(idCierre);
            return Ok(historial);
        }
    }
}
