using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RR3CommunityServer.Data;
using RR3CommunityServer.Models;

namespace RR3CommunityServer.Controllers;

[ApiController]
[Route("synergy/notifications")]
public class NotificationsController : ControllerBase
{
    private readonly RR3DbContext _context;
    private readonly ILogger<NotificationsController> _logger;

    public NotificationsController(RR3DbContext context, ILogger<NotificationsController> logger)
    {
        _context = context;
        _logger = logger;
    }

    // GET /synergy/notifications?synergyId=xxx&unreadOnly=false&limit=50
    [HttpGet]
    public async Task<IActionResult> GetNotifications(
        [FromQuery] string synergyId,
        [FromQuery] bool unreadOnly = false,
        [FromQuery] int limit = 50)
    {
        try
        {
            if (string.IsNullOrEmpty(synergyId))
                return BadRequest(new SynergyResponse<object> { resultCode = -1, message = "synergyId required" });

            var user = await _context.Users.FirstOrDefaultAsync(u => u.SynergyId == synergyId);
            if (user == null)
                return NotFound(new SynergyResponse<object> { resultCode = -404, message = "Player not found" });

            var now = DateTime.UtcNow;
            var query = _context.Notifications
                .Where(n => n.UserId == user.Id && (n.ExpiresAt == null || n.ExpiresAt > now));

            if (unreadOnly)
                query = query.Where(n => !n.IsRead);

            var notifications = await query
                .OrderByDescending(n => n.CreatedAt)
                .Take(limit)
                .ToListAsync();

            var unreadCount = await _context.Notifications
                .CountAsync(n => n.UserId == user.Id && !n.IsRead && (n.ExpiresAt == null || n.ExpiresAt > now));

            var dtos = notifications.Select(n => new NotificationDto
            {
                Id = n.Id,
                Type = n.Type,
                Title = n.Title,
                Message = n.Message,
                IsRead = n.IsRead,
                CreatedAt = new DateTimeOffset(n.CreatedAt).ToUnixTimeSeconds(),
                ExpiresAt = n.ExpiresAt.HasValue ? new DateTimeOffset(n.ExpiresAt.Value).ToUnixTimeSeconds() : null
            }).ToList();

            _logger.LogInformation("Retrieved {Count} notifications for {SynergyId}", dtos.Count, synergyId);

            return Ok(new SynergyResponse<NotificationsResponse>
            {
                resultCode = 0,
                data = new NotificationsResponse
                {
                    Notifications = dtos,
                    TotalCount = dtos.Count,
                    UnreadCount = unreadCount
                }
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting notifications for {SynergyId}", synergyId);
            return StatusCode(500, new SynergyResponse<object> { resultCode = -500, message = "Internal server error" });
        }
    }

    // GET /synergy/notifications/unread-count?synergyId=xxx
    [HttpGet("unread-count")]
    public async Task<IActionResult> GetUnreadCount([FromQuery] string synergyId)
    {
        try
        {
            if (string.IsNullOrEmpty(synergyId))
                return BadRequest(new SynergyResponse<object> { resultCode = -1, message = "synergyId required" });

            var user = await _context.Users.FirstOrDefaultAsync(u => u.SynergyId == synergyId);
            if (user == null)
                return Ok(new SynergyResponse<UnreadCountResponse> { resultCode = 0, data = new UnreadCountResponse { UnreadCount = 0 } });

            var now = DateTime.UtcNow;
            var count = await _context.Notifications
                .CountAsync(n => n.UserId == user.Id && !n.IsRead && (n.ExpiresAt == null || n.ExpiresAt > now));

            return Ok(new SynergyResponse<UnreadCountResponse>
            {
                resultCode = 0,
                data = new UnreadCountResponse { UnreadCount = count }
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting unread count for {SynergyId}", synergyId);
            return StatusCode(500, new SynergyResponse<object> { resultCode = -500, message = "Internal server error" });
        }
    }

    // POST /synergy/notifications/mark-read
    [HttpPost("mark-read")]
    public async Task<IActionResult> MarkRead([FromBody] MarkReadRequest request)
    {
        try
        {
            if (string.IsNullOrEmpty(request.SynergyId))
                return BadRequest(new SynergyResponse<object> { resultCode = -1, message = "synergyId required" });

            var user = await _context.Users.FirstOrDefaultAsync(u => u.SynergyId == request.SynergyId);
            if (user == null)
                return NotFound(new SynergyResponse<object> { resultCode = -404, message = "Player not found" });

            IQueryable<Notification> query = _context.Notifications.Where(n => n.UserId == user.Id && !n.IsRead);

            // If specific IDs provided, only mark those; otherwise mark all
            if (request.NotificationIds != null && request.NotificationIds.Count > 0)
                query = query.Where(n => request.NotificationIds.Contains(n.Id));

            var notifications = await query.ToListAsync();
            foreach (var n in notifications)
                n.IsRead = true;

            await _context.SaveChangesAsync();

            _logger.LogInformation("Marked {Count} notifications read for {SynergyId}", notifications.Count, request.SynergyId);

            return Ok(new SynergyResponse<object>
            {
                resultCode = 0,
                message = $"Marked {notifications.Count} notification(s) as read"
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error marking notifications read for {SynergyId}", request.SynergyId);
            return StatusCode(500, new SynergyResponse<object> { resultCode = -500, message = "Internal server error" });
        }
    }

    // POST /synergy/notifications/send  (admin/system use)
    [HttpPost("send")]
    public async Task<IActionResult> SendNotification([FromBody] SendNotificationRequest request)
    {
        try
        {
            if (string.IsNullOrEmpty(request.Title) || string.IsNullOrEmpty(request.Message))
                return BadRequest(new SynergyResponse<object> { resultCode = -1, message = "title and message required" });

            DateTime? expiresAt = request.ExpiresInHours.HasValue
                ? DateTime.UtcNow.AddHours(request.ExpiresInHours.Value)
                : null;

            int sentCount = 0;

            if (string.IsNullOrEmpty(request.SynergyId))
            {
                // Broadcast to all users
                var allUsers = await _context.Users.Select(u => u.Id).ToListAsync();
                var bulk = allUsers.Select(uid => new Notification
                {
                    UserId = uid,
                    Type = request.Type,
                    Title = request.Title,
                    Message = request.Message,
                    CreatedAt = DateTime.UtcNow,
                    ExpiresAt = expiresAt
                }).ToList();

                _context.Notifications.AddRange(bulk);
                sentCount = bulk.Count;
            }
            else
            {
                // Send to specific player
                var user = await _context.Users.FirstOrDefaultAsync(u => u.SynergyId == request.SynergyId);
                if (user == null)
                    return NotFound(new SynergyResponse<object> { resultCode = -404, message = "Player not found" });

                _context.Notifications.Add(new Notification
                {
                    UserId = user.Id,
                    Type = request.Type,
                    Title = request.Title,
                    Message = request.Message,
                    CreatedAt = DateTime.UtcNow,
                    ExpiresAt = expiresAt
                });
                sentCount = 1;
            }

            await _context.SaveChangesAsync();

            _logger.LogInformation("Sent notification '{Title}' to {Count} player(s)", request.Title, sentCount);

            return Ok(new SynergyResponse<object>
            {
                resultCode = 0,
                message = $"Notification sent to {sentCount} player(s)"
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error sending notification");
            return StatusCode(500, new SynergyResponse<object> { resultCode = -500, message = "Internal server error" });
        }
    }

    // DELETE /synergy/notifications/{id}?synergyId=xxx
    [HttpDelete("{id:int}")]
    public async Task<IActionResult> DeleteNotification(int id, [FromQuery] string synergyId)
    {
        try
        {
            if (string.IsNullOrEmpty(synergyId))
                return BadRequest(new SynergyResponse<object> { resultCode = -1, message = "synergyId required" });

            var user = await _context.Users.FirstOrDefaultAsync(u => u.SynergyId == synergyId);
            if (user == null)
                return NotFound(new SynergyResponse<object> { resultCode = -404, message = "Player not found" });

            var notification = await _context.Notifications
                .FirstOrDefaultAsync(n => n.Id == id && n.UserId == user.Id);

            if (notification == null)
                return NotFound(new SynergyResponse<object> { resultCode = -404, message = "Notification not found" });

            _context.Notifications.Remove(notification);
            await _context.SaveChangesAsync();

            _logger.LogInformation("Deleted notification {Id} for {SynergyId}", id, synergyId);

            return Ok(new SynergyResponse<object>
            {
                resultCode = 0,
                message = "Notification deleted"
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error deleting notification {Id}", id);
            return StatusCode(500, new SynergyResponse<object> { resultCode = -500, message = "Internal server error" });
        }
    }
}
