using System.Text;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SIGCM.Domain.Interfaces;
using SIGCM.Infrastructure.Repositories;
using SIGCM.Infrastructure.Services;

namespace SIGCM.API.Controllers;

[ApiController]
[Route("api/[controller]")]
[Authorize(Roles = "Cajero,Admin")]
public class ReportsController : ControllerBase
{
  private readonly IListingRepository _listingRepo;
  private readonly AuditRepository _auditRepo;

  public ReportsController(IListingRepository listingRepo, AuditRepository auditRepo)
  {
    _listingRepo = listingRepo;
    _auditRepo = auditRepo;
  }

  [HttpGet("dashboard")]
  [Authorize(Roles = "Admin,GerenteVentas")]
  public async Task<IActionResult> GetDashboard([FromQuery] DateTime? from, [FromQuery] DateTime? to)
  {
    var start = from ?? DateTime.UtcNow.Date;
    var end = to ?? DateTime.UtcNow.Date;
    var stats = await _listingRepo.GetDashboardStatsAsync(start, end);
    return Ok(stats);
  }

  [HttpGet("sales-by-category")]
  [Authorize(Roles = "Admin,GerenteVentas")]
  public async Task<IActionResult> GetSalesByCategory([FromQuery] DateTime? from, [FromQuery] DateTime? to)
  {
    var start = from ?? DateTime.UtcNow.AddMonths(-1);
    var end = to ?? DateTime.UtcNow;
    var data = await _listingRepo.GetSalesByRootCategoryAsync(start, end);

    var totalAmount = data.Sum(x => x.TotalSales);
    if (totalAmount > 0)
    {
      foreach (var item in data)
        item.Percentage = Math.Round((item.TotalSales / totalAmount) * 100, 2);
    }

    return Ok(data);
  }

  [HttpGet("audit")]
  [Authorize(Roles = "Admin")]
  public async Task<IActionResult> GetAuditLogs([FromQuery] DateTime? from, [FromQuery] DateTime? to, [FromQuery] int? userId)
  {
    var start = from ?? DateTime.UtcNow.Date;
    var end = to ?? DateTime.UtcNow.AddDays(1).Date.AddSeconds(-1);

    var logs = await _auditRepo.GetFilteredLogsAsync(start, end, userId);
    return Ok(logs);
  }

  [HttpGet("cashier")]
  [Authorize(Roles = "Cajero,Admin")]
  public async Task<IActionResult> GetCashierDashboard([FromQuery] DateTime? from, [FromQuery] DateTime? to)
  {
    var userIdClaim = User.FindFirst("Id")?.Value;
    if (string.IsNullOrEmpty(userIdClaim)) return Unauthorized();

    int userId = int.Parse(userIdClaim);
    // Si no vienen fechas, usamos hoy por defecto
    var start = from ?? DateTime.UtcNow.Date;
    var end = to ?? DateTime.UtcNow.Date;

    var stats = await _listingRepo.GetCashierStatsAsync(userId, start, end);
    return Ok(stats);
  }

  [HttpGet("export-cierre")]
  [Authorize(Roles = "Admin,Cajero")]
  public async Task<IActionResult> ExportCierre([FromQuery] DateTime from, [FromQuery] DateTime to, [FromQuery] int? userId) // <--- Agregamos userId opcional
  {
    var userIdClaim = User.FindFirst("Id")?.Value;
    var userRole = User.FindFirst(System.Security.Claims.ClaimTypes.Role)?.Value;

    // SEGURIDAD: 
    // Si es Cajero, ignoramos lo que envíe y forzamos su propio ID.
    // Si es Admin, usamos el userId que venga en la URL (si viene).
    int? targetUserId = (userRole == "Cajero") ? int.Parse(userIdClaim!) : userId;

    // 1. Obtener datos filtrados
    var data = await _listingRepo.GetDetailedReportAsync(from, to, targetUserId);

    // 2. Título Dinámico: Si hay un filtro de usuario, no es un cierre global.
    string title = (targetUserId.HasValue)
        ? $"REPORTE DE ACTIVIDAD: {data.Items.FirstOrDefault()?.Cashier ?? "Usuario Sin Cargas"}"
        : "CIERRE GLOBAL DE JORNADA";

    // 3. Generar PDF
    var pdfBytes = ReportGenerator.GenerateSalesPdf(data, title);

    string fileName = targetUserId.HasValue ? $"Actividad_Caja_{targetUserId}" : "Cierre_Global";
    return File(pdfBytes, "application/pdf", $"{fileName}_{from:yyyyMMdd}.pdf");
  }

  [HttpGet("audit/user/{userId}")]
  [Authorize(Roles = "Admin")]
  public async Task<IActionResult> GetAuditLogsByUser(int userId)
  {
    var logs = await _auditRepo.GetLogsByUserAsync(userId);
    return Ok(logs);
  }

  [HttpGet("cashier-transactions")]
  [Authorize(Roles = "Cajero,Admin")]
  public async Task<IActionResult> GetCashierTransactions(
    [FromQuery] DateTime? from,
    [FromQuery] DateTime? to,
    [FromQuery] int? userId)
  {
    // 1. Obtener datos del usuario logueado
    var userIdClaim = User.FindFirst("Id")?.Value;
    var userRole = User.FindFirst(System.Security.Claims.ClaimTypes.Role)?.Value;

    if (string.IsNullOrEmpty(userIdClaim)) return Unauthorized();

    // 2. Lógica de seguridad para el filtro de usuario:
    // Si es Admin, puede ver a cualquier cajero (usa el userId que viene por query).
    // Si es Cajero, SOLO puede verse a sí mismo (forzamos su propio ID).
    int? targetUserId = (userRole == "Admin") ? userId : int.Parse(userIdClaim);

    // 3. Manejo de fechas: 
    // Si no vienen, usamos el rango de hoy. 
    // Pero el frontend enviará los valores de los selectores.
    var startDate = from ?? DateTime.UtcNow.Date;
    var endDate = to ?? DateTime.UtcNow.Date;

    // Llamamos al repositorio con las fechas REALES enviadas desde el frontend
    var transactions = await _listingRepo.GetDetailedReportAsync(startDate, endDate, targetUserId);

    return Ok(transactions);
  }

  [HttpGet("cajeros")]
  [Authorize(Roles = "Cajero,Admin")]
  public async Task<IActionResult> GetCajeros()
  {
    var cajeros = await _listingRepo.GetActiveCashiersAsync();
    return Ok(cajeros);
  }
}